#include "dnslib.h" #include #include /* make a full dns query including header. Returns length of packet. */ int makequery (char *name, u_int16_t type, u_int8_t *buffer, u_int16_t id) { HEADER *head; head = (HEADER *)buffer; bzero (head, DNSHDRSIZE); head->id = htons (id); head->qr = 0; head->opcode = 0; head->aa = 0; head->tc = 0; head->rd = 1; head->ra = 0; head->rcode = 0; head->qdcount = htons (1); head->ancount = 0; head->nscount = 0; head->arcount = 0; return (makeqbody (name, type, buffer + DNSHDRSIZE) + DNSHDRSIZE); } /* convert a \0-terminated string to a DNS domain name. * www.yahoo.com(.) => \003www\005yahoo\003\com\000 */ int formatname (char *in, u_int8_t *out) { char *start = in, c = 0; int n = strlen (in); in += n - 1; out += n + 1; *out-- = 0; n = 0; while (in >= start) { c = *in--; if (c == '.') { *out-- = n; n = 0; } else { *out-- = c; n++; } } if (n) *out-- = n; return (strlen (out + 1) + 1); } /* simple function for making a, ptr and ns resource records * doesn't support more complicated stuph. */ int makeRR (char *name, u_int16_t type, u_int16_t class, u_int32_t ttl, char *rdata, char *buf) { int n; rrec_body *rec; char *ptr = buf; /* name the resource record pertains too */ ptr += formatname (name, ptr); rec = (rrec_body *)ptr; rec->type = htons (type); rec->class = htons (class); rec->ttl = htonl (ttl); rec->rdlength = 0; ptr += 10; switch (type) { case T_A: *(u_int32_t *)ptr = inet_addr (rdata); rec->rdlength = htons (4); ptr += 4; break; case T_PTR: case T_NS: n = formatname (rdata, ptr); ptr += n; rec->rdlength = htons (n); break; default: /**/ } return (ptr - buf); } /* make just the body of a DNS query. */ int makeqbody (char *name, u_int16_t type, u_int8_t *buffer) { int len; len = formatname (name, buffer); buffer += len; PUTSHORT (type, buffer); PUTSHORT (C_IN, buffer); return (len + 4); } /* uncompress compressed dns names. ugh. * works for normal formatted dns names too.. * returns the length of the first part of the compressed name (i.e. * before redirection). */ int uncompress (u_int8_t *in, char *out, u_int8_t *msg) { u_int8_t *start = in, *end = NULL; u_int8_t len; u_int16_t off; while ((len = *in++)) { if (len & INDIR_MASK) { if (end == NULL) end = in + 1; off = (len & ~INDIR_MASK); off |= *in++ << 8; off = ntohs (off); in = msg + off; continue; } memcpy (out, in, len); out += len; in += len; *out++ = '.'; } if (end == NULL) end = in; *out++ = 0; return (end - start); }