From: Roger Wolff Date: Sun, 17 Aug 2014 13:09:01 +0000 (+0200) Subject: New DNS works for IPV4.... X-Git-Tag: v0.88~43^2~7^2~7 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=02a9e6193e5dec01198f7824b7ed92f320b4e7a9;p=thirdparty%2Fmtr.git New DNS works for IPV4.... --- diff --git a/dns.c b/dns.c index 32b83c2..f126b24 100644 --- a/dns.c +++ b/dns.c @@ -55,412 +55,19 @@ #include "dns.h" #include "net.h" -#ifdef ENABLE_IPV6 -#ifdef __GLIBC__ -#define NSSOCKADDR6(i) (myres._u._ext.nsaddrs[i]) -#else -#define NSSOCKADDR6(i) (&(myres._u._ext.ext->nsaddrs[i].sin6)) -#endif -#endif - - -#ifdef NO_STRERROR -extern int sys_nerr; -extern char *sys_errlist[]; -#define strerror(errno) (((errno) >= 0 && (errno) < sys_nerr) ? sys_errlist[errno] : "unlisted error") -#endif - -#if !HAVE_DECL_ERRNO -/* Hmm, it seems Irix requires this */ -extern int errno; -#endif - extern int af; -/* Defines */ - -#undef Debug - -#undef CorruptCheck -#undef WipeFrees -#undef WipeMallocs - -#define BashSize 8192 /* Size of hash tables */ -#define BashModulo(x) ((x) & 8191) /* Modulo for hash table size: */ -#define HostnameLength 255 /* From RFC */ -#define ResRetryDelay1 3 -#define ResRetryDelay2 4 -#define ResRetryDelay3 5 - -/* Macros */ - -#define nonull(s) (s) ? s : nullstring - -/* Structures */ - -struct resolve { - struct resolve *next; - struct resolve *previous; - struct resolve *nextid; - struct resolve *previousid; - struct resolve *nextip; - struct resolve *previousip; - struct resolve *nexthost; - struct resolve *previoushost; - float expiretime; /* Fucking HPUX has a problem with "double" here. */ - char *hostname; - ip_t ip; - word id; - byte state; -}; - -/* Non-blocking nameserver interface routines */ - -#define MaxPacketsize (PACKETSZ) -#define DomainLength (MAXDNAME) - -#define OpcodeCount 3 -char *opcodes[OpcodeCount+1] = { - "standard query", - "inverse query", - "server status request", - "unknown", -}; - -#define ResponsecodeCount 6 -char *responsecodes[ResponsecodeCount+1] = { - "no error", - "format error in query", - "server failure", - "queried domain name does not exist", - "requested query type not implemented", - "refused by name server", - "unknown error", -}; - -#define ResourcetypeCount 17 -char *resourcetypes[ResourcetypeCount+1] = { - "unknown type", - "A: host address", - "NS: authoritative name server", - "MD: mail destination (OBSOLETE)", - "MF: mail forwarder (OBSOLETE)", - "CNAME: name alias", - "SOA: authority record", - "MB: mailbox domain name (EXPERIMENTAL)", - "MG: mail group member (EXPERIMENTAL)", - "MR: mail rename domain name (EXPERIMENTAL)", - "NULL: NULL RR (EXPERIMENTAL)", - "WKS: well known service description", - "PTR: domain name pointer", - "HINFO: host information", - "MINFO: mailbox or mail list information", - "MX: mail exchange", - "TXT: text string", - "unknown type", -}; - -#define ClasstypeCount 5 -char *classtypes[ClasstypeCount+1] = { - "unknown class", - "IN: the Internet", - "CS: CSNET (OBSOLETE)", - "CH: CHAOS", - "HS: Hesoid [Dyer 87]", - "unknown class" -}; - -char *rrtypes[] = { - "Unknown", - "Query", - "Answer", - "Authority reference", - "Resource reference", -}; - - -/* Please don't use a trailing comma in enumerations: It doesn't - work on all compilers */ -enum { - RR_UNKNOWN, - RR_QUERY, - RR_ANSWER, - RR_AUTHORITY, - RR_RESOURCE -}; - -typedef struct { - word id; /* Packet id */ - byte databyte_a; - /* rd:1 recursion desired - * tc:1 truncated message - * aa:1 authoritive answer - * opcode:4 purpose of message - * qr:1 response flag - */ - byte databyte_b; - /* rcode:4 response code - * unassigned:2 unassigned bits - * pr:1 primary server required (non standard) - * ra:1 recursion available - */ - word qdcount; /* Query record count */ - word ancount; /* Answer record count */ - word nscount; /* Authority reference record count */ - word arcount; /* Resource reference record count */ -} packetheader; - -#ifndef HFIXEDSZ -#define HFIXEDSZ (sizeof(packetheader)) -#endif - -/* - * Byte order independent macros for packetheader - */ -#define getheader_rd(x) (x->databyte_a & 1) -#define getheader_tc(x) ((x->databyte_a >> 1) & 1) -#define getheader_aa(x) ((x->databyte_a >> 2) & 1) -#define getheader_opcode(x) ((x->databyte_a >> 3) & 15) -#define getheader_qr(x) (x->databyte_a >> 7) -#define getheader_rcode(x) (x->databyte_b & 15) -#define getheader_pr(x) ((x->databyte_b >> 6) & 1) -#define getheader_ra(x) (x->databyte_b >> 7) - -#if 0 - -/* The execution order inside an expression is undefined! That means that - this might work, but then again, it might not... */ - -#define sucknetword(x) (((word)*(x) << 8) | (((x)+= 2)[-1])) -#define sucknetshort(x) (((short)*(x) << 8) | (((x)+= 2)[-1])) -#define sucknetdword(x) (((dword)*(x) << 24) | ((x)[1] << 16) | ((x)[2] << 8) | (((x)+= 4)[-1])) -#define sucknetlong(x) (((long)*(x) << 24) | ((x)[1] << 16) | ((x)[2] << 8) | (((x)+= 4)[-1])) -#else - -#define sucknetword(x) ((x)+=2,((word) (((x)[-2] << 8) | ((x)[-1] << 0)))) -#define sucknetshort(x) ((x)+=2,((short) (((x)[-2] << 8) | ((x)[-1] << 0)))) -#define sucknetdword(x) ((x)+=4,((dword) (((x)[-4] << 24) | ((x)[-3] << 16) | \ - ((x)[-2] << 8) | ((x)[-1] << 0)))) -#define sucknetlong(x) ((x)+=4,((long) (((x)[-4] << 24) | ((x)[-3] << 16) | \ - ((x)[-2] << 8) | ((x)[-1] << 0)))) -#endif - -enum { - STATE_FINISHED, - STATE_FAILED, - STATE_PTRREQ1, - STATE_PTRREQ2, - STATE_PTRREQ3 -}; - -#define Is_PTR(x) ((x->state == STATE_PTRREQ1) || (x->state == STATE_PTRREQ2) || (x->state == STATE_PTRREQ3)) - -dword resrecvbuf[(MaxPacketsize + 7) >> 2]; /* MUST BE DWORD ALIGNED */ - -struct resolve *idbash[BashSize]; -struct resolve *ipbash[BashSize]; -struct resolve *hostbash[BashSize]; -struct resolve *expireresolves = NULL; -struct resolve *lastresolve = NULL; -struct logline *streamlog = NULL; -struct logline *lastlog = NULL; - -ip_t alignedip; -ip_t localhost; -#ifdef ENABLE_IPV6 -ip_t localhost6; -#endif - -double sweeptime; - -#ifdef Debug -int debug = 1; -#else -int debug = 0; -#endif - -dword mem = 0; - -dword res_iplookupsuccess = 0; -dword res_reversesuccess = 0; -dword res_nxdomain = 0; -dword res_nserror = 0; -dword res_hostipmismatch = 0; -dword res_unknownid = 0; -dword res_resend = 0; -dword res_timeout = 0; - -dword resolvecount = 0; - -long idseed = 0xdeadbeef; -long aseed; - -#ifdef ENABLE_IPV6 -struct sockaddr_storage from_sastruct; -struct sockaddr_in6 * from6 = (struct sockaddr_in6 *) &from_sastruct; -#else -struct sockaddr_in from_sastruct; -#endif - -struct sockaddr_in * from4 = (struct sockaddr_in *) &from_sastruct; -struct sockaddr * from = (struct sockaddr *) &from_sastruct; - -int resfd; -#ifdef ENABLE_IPV6 -int resfd6; -#endif -socklen_t fromlen = sizeof from_sastruct; - -char tempstring[16384+1+1]; -char sendstring[1024+1]; -char namestring[1024+1]; -char stackstring[1024+1]; - -char nullstring[] = ""; int use_dns = 1; -#ifdef res_ninit -#define MY_RES_INIT() res_ninit(&myres); -#define RES_MKQUERY(a, b, c, d, e, f, g, h, i) \ - res_nmkquery(&myres, a, b, c, d, e, f, g, h, i) -struct __res_state myres; -#else -#define MY_RES_INIT() res_init(); -#define RES_MKQUERY(a, b, c, d, e, f, g, h, i) \ - res_mkquery(a, b, c, d, e, f, g, h, i) -#define myres _res -#endif - -/* Code */ -#ifdef CorruptCheck -#define TOT_SLACK 2 -#define HEAD_SLACK 1 -/* Need an entry for sparc systems here too. - Don't try this on Sparc for now. */ -#else -#ifdef sparc -#define TOT_SLACK 2 -#define HEAD_SLACK 2 -#else -#define TOT_SLACK 1 -#define HEAD_SLACK 1 -#endif -#endif - - -void *statmalloc(size_t size) -{ - void *p; - size_t mallocsize; - - mem+= size; - mallocsize = size + TOT_SLACK * sizeof(dword); - - p = malloc(mallocsize); - if (!p) { - fprintf(stderr,"malloc() of %u bytes failed: %s\n", (unsigned int)size, strerror(errno)); - exit(-1); - } - *((dword *)p) = (dword)size; -#ifdef CorruptCheck - *(byte *)((char *)p + size + sizeof(dword) + sizeof(byte) * 0) = 0xde; - *(byte *)((char *)p + size + sizeof(dword) + sizeof(byte) * 1) = 0xad; - *(byte *)((char *)p + size + sizeof(dword) + sizeof(byte) * 2) = 0xbe; - *(byte *)((char *)p + size + sizeof(dword) + sizeof(byte) * 3) = 0xef; -#endif - p = (void *)((dword *)p + HEAD_SLACK); -#ifdef WipeMallocs - memset(p,0xf0,size); -#endif - return p; -} - - -void statfree(void *p) -{ - if (p) { - if (*((dword *)p - HEAD_SLACK) == 0) { - fprintf(stderr,"ERROR: Attempt to free pointer twice.\n"); - abort(); - exit(-1); - } else { - if (*((dword *)p - HEAD_SLACK) > 8192) { - fprintf (stderr,"ERROR: Corrupted free() buffer. (header)\n"); - abort(); - exit(-1); - } -#ifdef CorruptCheck - if ((*(byte *)((char *)p + (*((dword *)p - 1)) + sizeof(byte) * 0) != 0xde) || - (*(byte *)((char *)p + (*((dword *)p - 1)) + sizeof(byte) * 1) != 0xad) || - (*(byte *)((char *)p + (*((dword *)p - 1)) + sizeof(byte) * 2) != 0xbe) || - (*(byte *)((char *)p + (*((dword *)p - 1)) + sizeof(byte) * 3) != 0xef)) { - fprintf(stderr,"ERROR: Corrupted free() buffer. (footer)\n"); - abort(); - exit(-1); - } -#endif - mem-= *((dword *)p - HEAD_SLACK); -#ifdef WipeFrees - memset(p,0xfe,*((dword *)p - HEAD_SLACK)); - *((dword *)p - 1) = 0; -#endif - free((dword *)p - HEAD_SLACK); - } - } -} - - -char *strtdiff(char *d,long signeddiff) -{ - dword diff; - dword seconds,minutes,hours; - long days; - - if ((diff = labs(signeddiff))) { - seconds = diff % 60; diff/= 60; - minutes = diff % 60; diff/= 60; - hours = diff % 24; - days = signeddiff / (60 * 60 * 24); - if (days) - sprintf(d,"%lid",days); - else - *d = '\0'; - if (hours) - sprintf(d + strlen(d),"%luh",hours); - if (minutes) - sprintf(d + strlen(d),"%lum",minutes); - if (seconds) - sprintf(d + strlen(d),"%lus",seconds); - } else - sprintf(d,"0s"); - return d; -} - -int issetfd(fd_set *set,int fd) -{ - return (int)((FD_ISSET(fd,set)) && 1); -} - - -void setfd(fd_set *set,int fd) -{ - FD_SET(fd,set); -} - - -void clearfd(fd_set *set,int fd) -{ - FD_CLR(fd,set); -} - - -void clearset(fd_set *set) -{ - FD_ZERO(set); -} +struct dns_results { + ip_t ip; + char *name; + struct dns_results *next; +}; +struct dns_results *results; char *strlongip(ip_t * ip) { @@ -495,978 +102,186 @@ struct hostent * dns_forward(const char *name) } -int dns_waitfd(void) +struct dns_results *findip (ip_t *ip) { - return resfd; -} -#ifdef ENABLE_IPV6 -int dns_waitfd6(void) -{ - return resfd6; -} -#endif - - -void dns_open(void) -{ - int option,i; - - if (!dns) return; - MY_RES_INIT(); - if (!myres.nscount) { - fprintf(stderr,"No nameservers defined.\n"); - exit(-1); - } - myres.options|= RES_RECURSE | RES_DEFNAMES | RES_DNSRCH; - resfd = socket(AF_INET, SOCK_DGRAM, 0); - if (resfd == -1) { - fprintf(stderr, - "Unable to allocate IPv4 socket for nameserver communication: %s\n", - strerror(errno)); - exit(-1); + struct dns_results *t; + + //printf ("Looking for: %s\n", strlongip (ip)); + for (t=results;t;t=t->next) { + //printf ("comparing: %s\n", strlongip (&t->ip)); + if (addrcmp ( (void *)ip, (void*) &t->ip, af) == 0) + return t; } -#ifdef ENABLE_IPV6 - resfd6 = socket(AF_INET6, SOCK_DGRAM, 0); - if (resfd6 == -1) { - // consider making removing this warning. For now leave it in to see - // new code activated. -- REW - fprintf(stderr, - "Unable to allocate IPv6 socket for nameserver communication: %s\n", - strerror(errno)); - // exit(-1); - } -#endif - option = 1; - if (setsockopt(resfd,SOL_SOCKET,SO_BROADCAST,(char *)&option,sizeof(option))) { - fprintf(stderr, - "Unable to setsockopt() on IPv4 nameserver communication socket: %s\n", - strerror(errno)); - exit(-1); - } -#ifdef ENABLE_IPV6 - if (resfd6 > 0) { - if (setsockopt(resfd6,SOL_SOCKET,SO_BROADCAST,(char *)&option,sizeof(option))) { - fprintf(stderr, - "Unable to setsockopt() on IPv6 nameserver communication socket: %s\n", - strerror(errno)); - exit(-1); - } - } -#endif - longipstr( "127.0.0.1", &localhost, AF_INET ); -#ifdef ENABLE_IPV6 - longipstr( "::1", &localhost6, AF_INET6 ); -#endif - aseed = time(NULL) ^ (time(NULL) << 3) ^ (dword)getpid(); - for (i = 0;i < BashSize;i++) { - idbash[i] = NULL; - hostbash[i] = NULL; - } -} - -struct resolve *allocresolve(void) -{ - struct resolve *rp; - - rp = (struct resolve *)statmalloc(sizeof(struct resolve)); - if (!rp) { - fprintf(stderr,"statmalloc() failed: %s\n",strerror(errno)); - exit(-1); - } - memset(rp,0, sizeof(struct resolve)); - return rp; + return NULL; } -dword getidbash(word id) -{ - return (dword)BashModulo(id); -} +static int todns[2], fromdns[2]; +FILE *fromdnsfp; -dword getipbash(ip_t * ip) -{ - char *p = (char *) ip; - int i, len = 0; - dword bashvalue = 0; - - switch ( af ) { - case AF_INET: - len = sizeof (struct in_addr); - break; -#ifdef ENABLE_IPV6 - case AF_INET6: - len = sizeof (struct in6_addr); - break; -#endif - } - for (i = 0; i < len; i++, p++) { - bashvalue^= *p; - bashvalue+= (*p >> 1) + (bashvalue >> 1); - } - return BashModulo(bashvalue); +#if 0 +void handle_sigchld(int sig) { + while (waitpid((pid_t)(-1), 0, WNOHANG) > 0) {} } +#endif - -dword gethostbash(char *host) +void dns_open(void) { - dword bashvalue = 0; - - for (;*host;host++) { - bashvalue^= *host; - bashvalue+= (*host >> 1) + (bashvalue >> 1); + int pid; + + if (pipe (todns) < 0) { + perror ("can't make a pipe for DNS process"); + exit (-1); } - return BashModulo(bashvalue); -} - - -void linkresolveid(struct resolve *addrp) -{ - struct resolve *rp; - dword bashnum; - - bashnum = getidbash(addrp->id); - rp = idbash[bashnum]; - if (rp) { - while ((rp->nextid) && (addrp->id > rp->nextid->id)) - rp = rp->nextid; - while ((rp->previousid) && (addrp->id < rp->previousid->id)) - rp = rp->previousid; - if (rp->id < addrp->id) { - addrp->previousid = rp; - addrp->nextid = rp->nextid; - if (rp->nextid) - rp->nextid->previousid = addrp; - rp->nextid = addrp; - } else { - addrp->previousid = rp->previousid; - addrp->nextid = rp; - if (rp->previousid) - rp->previousid->nextid = addrp; - rp->previousid = addrp; - } - } else - addrp->nextid = addrp->previousid = NULL; - idbash[bashnum] = addrp; -} + if (pipe (fromdns) < 0) { + perror ("can't make a pipe for DNS process"); + exit (-1); + } -void unlinkresolveid(struct resolve *rp) -{ - dword bashnum; - - bashnum = getidbash(rp->id); - if (idbash[bashnum] == rp) - idbash[bashnum] = (rp->previousid)? rp->previousid : rp->nextid; - if (rp->nextid) - rp->nextid->previousid = rp->previousid; - if (rp->previousid) - rp->previousid->nextid = rp->nextid; -} + pid = fork (); + //pid = 1; + if (pid < 0) { + perror ("can't fork for DNS process"); + exit (-1); + } + if (pid == 0) { + char buf[1024]; + int i; + FILE *infp, *outfp; + // The child: We're going to handle the DNS requests here. + close (todns[1]); // close the pipe ends we don't need. + close (fromdns[0]); -void linkresolvehost(struct resolve *addrp) -{ - struct resolve *rp; - dword bashnum; - - bashnum = gethostbash(addrp->hostname); - rp = hostbash[bashnum]; - if (rp) { - while ((rp->nexthost) && (strcasecmp(addrp->hostname,rp->nexthost->hostname) < 0)) - rp = rp->nexthost; - while ((rp->previoushost) && (strcasecmp(addrp->hostname,rp->previoushost->hostname) > 0)) - rp = rp->previoushost; - if (strcasecmp(addrp->hostname,rp->hostname) < 0) { - addrp->previoushost = rp; - addrp->nexthost = rp->nexthost; - if (rp->nexthost) - rp->nexthost->previoushost = addrp; - rp->nexthost = addrp; - } else { - addrp->previoushost = rp->previoushost; - addrp->nexthost = rp; - if (rp->previoushost) - rp->previoushost->nexthost = addrp; - rp->previoushost = addrp; + if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) { + perror("signal"); + exit(1); } - } else - addrp->nexthost = addrp->previoushost = NULL; - hostbash[bashnum] = addrp; -} - - -void unlinkresolvehost(struct resolve *rp) -{ - dword bashnum; - - bashnum = gethostbash(rp->hostname); - if (hostbash[bashnum] == rp) - hostbash[bashnum] = (rp->previoushost)? rp->previoushost : rp->nexthost; - if (rp->nexthost) - rp->nexthost->previoushost = rp->previoushost; - if (rp->previoushost) - rp->previoushost->nexthost = rp->nexthost; - statfree(rp->hostname); -} - -void linkresolveip(struct resolve *addrp) -{ - struct resolve *rp; - dword bashnum; - - bashnum = getipbash( &(addrp->ip) ); - rp = ipbash[bashnum]; - if (rp) { - while ((rp->nextip) && - ( addrcmp( (void *) &(addrp->ip), - (void *) &(rp->nextip->ip), af ) > 0 )) - rp = rp->nextip; - while ((rp->previousip) && - ( addrcmp( (void *) &(addrp->ip), - (void *) &(rp->previousip->ip), af ) < 0 )) - rp = rp->previousip; - if ( addrcmp( (void *) &(rp->ip), (void *) &(addrp->ip), af ) < 0 ) { - addrp->previousip = rp; - addrp->nextip = rp->nextip; - if (rp->nextip) - rp->nextip->previousip = addrp; - rp->nextip = addrp; - } else { - addrp->previousip = rp->previousip; - addrp->nextip = rp; - if (rp->previousip) - rp->previousip->nextip = addrp; - rp->previousip = addrp; + // Close all unneccessary FDs. + for (i=3;inextip = addrp->previousip = NULL; - ipbash[bashnum] = addrp; -} - - -void unlinkresolveip(struct resolve *rp) -{ - dword bashnum; - - bashnum = getipbash( &(rp->ip) ); - if (ipbash[bashnum] == rp) - ipbash[bashnum] = (rp->previousip)? rp->previousip : rp->nextip; - if (rp->nextip) - rp->nextip->previousip = rp->previousip; - if (rp->previousip) - rp->previousip->nextip = rp->nextip; -} - - -void linkresolve(struct resolve *rp) -{ - struct resolve *irp; - - if (expireresolves) { - irp = expireresolves; - while ((irp->next) && (rp->expiretime >= irp->expiretime)) irp = irp->next; - if (rp->expiretime >= irp->expiretime) { - rp->next = NULL; - rp->previous = irp; - irp->next = rp; - lastresolve = rp; - } else { - rp->previous = irp->previous; - rp->next = irp; - if (irp->previous) - irp->previous->next = rp; - else - expireresolves = rp; - irp->previous = rp; + infp = fdopen (todns[0],"r"); + outfp = fdopen (fromdns[1],"w"); + + while (fgets (buf, 1024, infp)) { + ip_t host; + struct sockaddr_in sa; + char hostname [0x100]; + char result [0x100]; + // Find IPV6 version + if (!fork ()) { + longipstr (buf, &host, af); + printf ("resolving %s\n", strlongip (&host)); + sa.sin_family = af; + addrcpy ((void *) &sa.sin_addr, &host, af); + + //longipstr (buf, (void *)&sa.sin_addr, af); + + getnameinfo ((struct sockaddr *)&sa, sizeof (sa), + hostname, 0x100, NULL, 0, 0); + sprintf (result, "%s %s\n", strlongip ((ip_t *)&sa.sin_addr), hostname); + //sprintf (result, "%s name%s\n", strlongip (&host), strlongip (&host)); + printf ("resoved: %s -> %s\n", strlongip (&host), hostname); + write (fromdns[1], result, strlen (result)); + exit (0); + } } + exit (0); } else { - rp->next = NULL; - rp->previous = NULL; - expireresolves = lastresolve = rp; - } - resolvecount++; -} + int flags; - -void lastlinkresolve(struct resolve *rp) -{ - struct resolve *irp; - - if (lastresolve) { - irp = lastresolve; - while ((irp->previous) && (rp->expiretime < irp->expiretime)) irp = irp->previous; - while ((irp->next) && (rp->expiretime >= irp->expiretime)) irp = irp->next; - if (rp->expiretime >= irp->expiretime) { - rp->next = NULL; - rp->previous = irp; - irp->next = rp; - lastresolve = rp; - } else { - rp->previous = irp->previous; - rp->next = irp; - if (irp->previous) - irp->previous->next = rp; - else - expireresolves = rp; - irp->previous = rp; - } - } else { - rp->next = NULL; - rp->previous = NULL; - expireresolves = lastresolve = rp; + // the parent. + close (todns[0]); // close the pipe ends we don't need. + close (fromdns[1]); + fromdnsfp = fdopen (fromdns[0],"r"); + flags = fcntl(fromdns[0], F_GETFL, 0); + flags |= O_NONBLOCK; + fcntl(fromdns[0], F_SETFL, flags); } - resolvecount++; } - -void untieresolve(struct resolve *rp) -{ - if (rp->previous) - rp->previous->next = rp->next; - else - expireresolves = rp->next; - if (rp->next) - rp->next->previous = rp->previous; - else - lastresolve = rp->previous; - resolvecount--; -} - - -void unlinkresolve(struct resolve *rp) +int dns_waitfd (void) { - untieresolve(rp); - unlinkresolveid(rp); - unlinkresolveip(rp); - if (rp->hostname) - unlinkresolvehost(rp); + return fromdns[0]; } -struct resolve *findid(word id) -{ - struct resolve *rp; - int bashnum; - - bashnum = getidbash(id); - rp = idbash[bashnum]; - if (rp) { - while ((rp->nextid) && (id >= rp->nextid->id)) - rp = rp->nextid; - while ((rp->previousid) && (id <= rp->previousid->id)) - rp = rp->previousid; - if (id == rp->id) { - idbash[bashnum] = rp; - return rp; - } else - return NULL; - } - return rp; /* NULL */ -} - -struct resolve *findhost(char *hostname) +void dns_ack(void) { - struct resolve *rp; - int bashnum; - - bashnum = gethostbash(hostname); - rp = hostbash[bashnum]; - if (rp) { - while ((rp->nexthost) && (strcasecmp(hostname,rp->nexthost->hostname) >= 0)) - rp = rp->nexthost; - while ((rp->previoushost) && (strcasecmp(hostname,rp->nexthost->hostname) <= 0)) - rp = rp->previoushost; - if (strcasecmp(hostname,rp->hostname)) - return NULL; - else { - hostbash[bashnum] = rp; - return rp; - } - } - return rp; /* NULL */ -} + char buf[0x100], host[0x100], name[0x100]; + ip_t hostip; + struct dns_results *r; + //read (fromdns[0], buf, 0x100); + while ( fgets (buf, 0x100, fromdnsfp )) { + sscanf (buf, "%s %s", host, name); -struct resolve *findip(ip_t * ip) -{ - struct resolve *rp; - dword bashnum; - - bashnum = getipbash(ip); - rp = ipbash[bashnum]; - if (rp) { - while ((rp->nextip) && - ( addrcmp( (void *) ip, (void *) &(rp->nextip->ip), af ) >= 0 )) - rp = rp->nextip; - while ((rp->previousip) && - ( addrcmp( (void *) ip, (void *) &(rp->previousip->ip), af ) <= 0 )) - rp = rp->previousip; - if ( addrcmp( (void *) ip, (void *) &(rp->ip), af ) == 0 ) { - ipbash[bashnum] = rp; - return rp; - } else - return NULL; + longipstr (host, &hostip, af); + r = findip (&hostip); + if (r) + r->name = strdup (name); + else + fprintf (stderr, "dns_ack: Couldn't find host %s\n", host); } - return rp; /* NULL */ } -void restell(char *s) -{ - fputs(s,stderr); - fputs("\r",stderr); -} - -void dorequest(char *s,int type,word id) -{ - packetheader *hp; - int r,i; - unsigned char buf[MaxPacketsize]; - - r = RES_MKQUERY(QUERY,s,C_IN,type,NULL,0,NULL,(unsigned char*)buf,MaxPacketsize); - if (r == -1) { - restell("Resolver error: Query too large."); - return; - } - hp = (packetheader *)buf; - hp->id = id; /* htons() deliberately left out (redundant) */ - for (i = 0;i < myres.nscount;i++) - if (myres.nsaddr_list[i].sin_family == AF_INET) - (void)sendto(resfd,buf,r,0,(struct sockaddr *)&myres.nsaddr_list[i], - sizeof(struct sockaddr)); -#ifdef ENABLE_IPV6 - else if (resfd6 > 0) { - if (!NSSOCKADDR6(i)) - continue; - if (NSSOCKADDR6(i)->sin6_family == AF_INET6) - (void)sendto(resfd6,buf,r,0,(struct sockaddr *) NSSOCKADDR6(i), - sizeof(struct sockaddr_in6)); - } -#endif -} - -void resendrequest(struct resolve *rp,int type) -{ - if (type == T_A) { - dorequest(rp->hostname,type,rp->id); - if (debug) { - snprintf(tempstring, sizeof(tempstring), "Resolver: Sent reverse authentication request for \"%s\".", - rp->hostname); - restell(tempstring); - } - } else if (type == T_PTR) { - switch ( af ) { - case AF_INET: - sprintf(tempstring,"%u.%u.%u.%u.in-addr.arpa", - ((byte *)&rp->ip)[3], - ((byte *)&rp->ip)[2], - ((byte *)&rp->ip)[1], - ((byte *)&rp->ip)[0]); - break; #ifdef ENABLE_IPV6 - case AF_INET6: - addr2ip6arpa( &(rp->ip), tempstring ); - break; -#endif - } - dorequest(tempstring,type,rp->id); - if (debug) { - snprintf(tempstring, sizeof(tempstring), "Resolver: Sent domain lookup request for \"%s\".", - strlongip( &(rp->ip) )); - restell(tempstring); - } - } -} - -void sendrequest(struct resolve *rp,int type) -{ - do { - idseed = (((idseed + idseed) | (long)time(NULL)) + idseed - 0x54bad4a) ^ aseed; - aseed^= idseed; - rp->id = (word)idseed; - } while (findid(rp->id)); - linkresolveid(rp); - resendrequest(rp,type); -} - -void failrp(struct resolve *rp) +int dns_waitfd6 (void) { - if (rp->state == STATE_FINISHED) - return; - rp->state = STATE_FAILED; - untieresolve(rp); - if (debug) - restell("Resolver: Lookup failed.\n"); + return -1; } - -void passrp(struct resolve *rp,long ttl) +void dns_ack6(void) { - rp->state = STATE_FINISHED; - rp->expiretime = sweeptime + (double)ttl; - untieresolve(rp); - if (debug) { - snprintf(tempstring, sizeof(tempstring), "Resolver: Lookup successful: %s\n",rp->hostname); - restell(tempstring); - } + return; } - -void parserespacket(byte *s, int l) -{ - struct resolve *rp; - packetheader *hp; - byte *eob; - byte *c; - long ttl; - int r,usefulanswer; - word rr,datatype,class,qdatatype,qclass; - byte rdatalength; - - if (l < (int) sizeof(packetheader)) { - restell("Resolver error: Packet smaller than standard header size."); - return; - } - if (l == (int) sizeof(packetheader)) { - restell("Resolver error: Packet has empty body."); - return; - } - hp = (packetheader *)s; - /* Convert data to host byte order */ - /* hp->id does not need to be redundantly byte-order flipped, it is only echoed by nameserver */ - rp = findid(hp->id); - if (!rp) { - res_unknownid++; - return; - } - if ((rp->state == STATE_FINISHED) || (rp->state == STATE_FAILED)) - return; - hp->qdcount = ntohs(hp->qdcount); - hp->ancount = ntohs(hp->ancount); - hp->nscount = ntohs(hp->nscount); - hp->arcount = ntohs(hp->arcount); - if (getheader_tc(hp)) { /* Packet truncated */ - restell("Resolver error: Nameserver packet truncated."); - return; - } - if (!getheader_qr(hp)) { /* Not a reply */ - restell("Resolver error: Query packet received on nameserver communication socket."); - return; - } - if (getheader_opcode(hp)) { /* Not opcode 0 (standard query) */ - restell("Resolver error: Invalid opcode in response packet."); - return; - } - eob = s + l; - c = s + HFIXEDSZ; - switch (getheader_rcode(hp)) { - case NOERROR: - if (hp->ancount) { - if (debug) { - snprintf(tempstring, sizeof(tempstring), "Resolver: Received nameserver reply. (qd:%u an:%u ns:%u ar:%u)", - hp->qdcount,hp->ancount,hp->nscount,hp->arcount); - restell(tempstring); - } - if (hp->qdcount != 1) { - restell("Resolver error: Reply does not contain one query."); - return; - } - if (c > eob) { - restell("Resolver error: Reply too short."); - return; - } - switch (rp->state) { /* Construct expected query reply */ - case STATE_PTRREQ1: - case STATE_PTRREQ2: - case STATE_PTRREQ3: - switch ( af ) { - case AF_INET: - sprintf(stackstring,"%u.%u.%u.%u.in-addr.arpa", - ((byte *)&rp->ip)[3], - ((byte *)&rp->ip)[2], - ((byte *)&rp->ip)[1], - ((byte *)&rp->ip)[0]); - break; -#ifdef ENABLE_IPV6 - case AF_INET6: - addr2ip6arpa( &(rp->ip), stackstring ); - break; #endif - } - } - *namestring = '\0'; - r = dn_expand(s,s + l,c,namestring,MAXDNAME); - if (r == -1) { - restell("Resolver error: dn_expand() failed while expanding query domain."); - return; - } - namestring[strlen(stackstring)] = '\0'; - if (strcasecmp(stackstring,namestring)) { - if (debug) { - snprintf(tempstring, sizeof(tempstring), "Resolver: Unknown query packet dropped. (\"%s\" does not match \"%s\")", - stackstring,namestring); - restell(tempstring); - } - return; - } - if (debug) { - snprintf(tempstring, sizeof(tempstring), "Resolver: Queried domain name: \"%s\"",namestring); - restell(tempstring); - } - c+= r; - if (c + 4 > eob) { - restell("Resolver error: Query resource record truncated."); - return; - } - qdatatype = sucknetword(c); - qclass = sucknetword(c); - if (qclass != C_IN) { - snprintf(tempstring, sizeof(tempstring), "Resolver error: Received unsupported query class: %u (%s)", - qclass,qclass < ClasstypeCount ? classtypes[qclass] : - classtypes[ClasstypeCount]); - restell(tempstring); - } - switch (qdatatype) { - case T_PTR: - if (!Is_PTR(rp)) - if (debug) { - restell("Resolver warning: Ignoring response with unexpected query type \"PTR\"."); - return; - } - break; - default: - snprintf(tempstring, sizeof(tempstring), "Resolver error: Received unimplemented query type: %u (%s)", - qdatatype,qdatatype < ResourcetypeCount ? - resourcetypes[qdatatype] : resourcetypes[ResourcetypeCount]); - restell(tempstring); - } - for (rr = hp->ancount + hp->nscount + hp->arcount;rr;rr--) { - if (c > eob) { - restell("Resolver error: Packet does not contain all specified resouce records."); - return; - } - *namestring = '\0'; - r = dn_expand(s,s + l,c,namestring,MAXDNAME); - if (r == -1) { - restell("Resolver error: dn_expand() failed while expanding answer domain."); - return; - } - namestring[strlen(stackstring)] = '\0'; - if (strcasecmp(stackstring,namestring)) - usefulanswer = 0; - else - usefulanswer = 1; - if (debug) { - snprintf(tempstring, sizeof(tempstring), "Resolver: answered domain query: \"%s\"",namestring); - restell(tempstring); - } - c+= r; - if (c + 10 > eob) { - restell("Resolver error: Resource record truncated."); - return; - } - datatype = sucknetword(c); - class = sucknetword(c); - ttl = sucknetlong(c); - rdatalength = sucknetword(c); - if (class != qclass) { - snprintf(tempstring, sizeof(tempstring), "query class: %u (%s)",qclass,qclass < ClasstypeCount ? - classtypes[qclass] : classtypes[ClasstypeCount]); - restell(tempstring); - snprintf(tempstring, sizeof(tempstring), "rr class: %u (%s)",class,class < ClasstypeCount ? - classtypes[class] : classtypes[ClasstypeCount]); - restell(tempstring); - restell("Resolver error: Answered class does not match queried class."); - return; - } - if (!rdatalength) { - restell("Resolver error: Zero size rdata."); - return; - } - if (c + rdatalength > eob) { - restell("Resolver error: Specified rdata length exceeds packet size."); - return; - } - if (datatype == qdatatype || datatype == T_CNAME) { - if (debug) { - snprintf(tempstring, sizeof(tempstring), "Resolver: TTL: %s",strtdiff(sendstring,ttl)); - restell(tempstring); - } - if (usefulanswer) - switch (datatype) { - case T_A: - if (rdatalength != 4) { - snprintf(tempstring, sizeof(tempstring), "Resolver error: Unsupported rdata format for \"A\" type. (%u bytes)", - rdatalength); - restell(tempstring); - return; - } - if ( addrcmp( (void *) &(rp->ip), (void *) c, af ) == 0 ) { - snprintf(tempstring, sizeof(tempstring), "Resolver: Reverse authentication failed: %s != ", - strlongip( &(rp->ip) )); - addrcpy( (void *) &alignedip, (void *) c, af ); - strcat(tempstring,strlongip( &alignedip )); - restell(tempstring); - res_hostipmismatch++; - failrp(rp); - } else { - snprintf(tempstring, sizeof(tempstring), "Resolver: Reverse authentication complete: %s == \"%s\".", - strlongip( &(rp->ip) ),nonull(rp->hostname)); - restell(tempstring); - res_reversesuccess++; - passrp(rp,ttl); - return; - } - break; - case T_PTR: - case T_CNAME: - *namestring = '\0'; - r = dn_expand(s,s + l,c,namestring,MAXDNAME); - if (r == -1) { - restell("Resolver error: dn_expand() failed while expanding domain in rdata."); - return; - } - if (debug) { - snprintf(tempstring, sizeof(tempstring), "Resolver: Answered domain: \"%s\"",namestring); - restell(tempstring); - } - if (r > HostnameLength) { - restell("Resolver error: Domain name too long."); - failrp(rp); - return; - } - if (datatype == T_CNAME) { - strcpy(stackstring,namestring); - break; - } - if (!rp->hostname) { - rp->hostname = (char *)statmalloc(strlen(namestring) + 1); - if (!rp->hostname) { - fprintf(stderr,"statmalloc() error: %s\n",strerror(errno)); - exit(-1); - } - strcpy(rp->hostname,namestring); - linkresolvehost(rp); - passrp(rp,ttl); - res_iplookupsuccess++; - } - break; - default: - snprintf(tempstring, sizeof(tempstring), "Resolver error: Received unimplemented data type: %u (%s)", - datatype,datatype < ResourcetypeCount ? - resourcetypes[datatype] : resourcetypes[ResourcetypeCount]); - restell(tempstring); - } - } else { - if (debug) { - snprintf(tempstring, sizeof(tempstring), "Resolver: Ignoring resource type %u. (%s)", - datatype,datatype < ResourcetypeCount ? - resourcetypes[datatype] : resourcetypes[ResourcetypeCount]); - restell(tempstring); - } - } - c+= rdatalength; - } - } else - restell("Resolver error: No error returned but no answers given."); - break; - case NXDOMAIN: - if (debug) - restell("Resolver: Host not found."); - res_nxdomain++; - failrp(rp); - break; - default: - snprintf(tempstring, sizeof(tempstring), "Resolver: Received error response %u. (%s)", - getheader_rcode(hp),getheader_rcode(hp) < ResponsecodeCount ? - responsecodes[getheader_rcode(hp)] : responsecodes[ResponsecodeCount]); - restell(tempstring); - res_nserror++; - } -} -void dns_ack(void) +char *dns_lookup2(ip_t * ip) { - int r,i; - - r = recvfrom(resfd,(byte *)resrecvbuf,MaxPacketsize,0, - from, &fromlen); - if (r > 0) { - /* Check to see if this server is actually one we sent to */ - if ( addrcmp( (void *) &(from4->sin_addr), (void *) &localhost, - (int) AF_INET ) == 0 ) { - for (i = 0;i < myres.nscount;i++) - if ( addrcmp( (void *) &(myres.nsaddr_list[i].sin_addr), - (void *) &(from4->sin_addr), (int) AF_INET ) == 0 || - addrcmp( (void *) &(myres.nsaddr_list[i].sin_addr), - (void *) &unspec_addr, (int) AF_INET ) == 0 ) /* 0.0.0.0 replies as 127.0.0.1 */ - break; - } else - for (i = 0;i < myres.nscount;i++) - if ( addrcmp( (void *) &(myres.nsaddr_list[i].sin_addr), - (void *) &(from4->sin_addr), AF_INET ) == 0 ) - break; - if (i == myres.nscount) { - snprintf(tempstring, sizeof(tempstring), "Resolver error: Received reply from unknown source: %s", - inet_ntoa(from4->sin_addr )); - restell(tempstring); - } else - parserespacket((byte *)resrecvbuf,r); + struct dns_results *r; + char buf[0x100]; + + r = findip (ip); + if (r) { + // we've got a result. + if (r->name) + return r->name; + else + return strlongip (ip); } else { - snprintf(tempstring, sizeof(tempstring), "Resolver: Socket error: %s",strerror(errno)); - restell(tempstring); - } -} -#ifdef ENABLE_IPV6 -void dns_ack6(void) -{ - int r,i; - static char addrstr[INET6_ADDRSTRLEN]; - - // Probably not necessary. -- REW - if (resfd6 < 0) return; - - r = recvfrom(resfd6,(byte *)resrecvbuf,MaxPacketsize,0, - from, &fromlen); - if (r > 0) { - /* Check to see if this server is actually one we sent to */ - if ( addrcmp( (void *) &(from6->sin6_addr), (void *) &localhost6, - (int) AF_INET6 ) == 0 ) { - for (i = 0;i < myres.nscount;i++) { - if (!NSSOCKADDR6(i)) - continue; - - if ( addrcmp( (void *) &(NSSOCKADDR6(i)->sin6_addr), - (void *) &(from6->sin6_addr), (int) AF_INET6 ) == 0 || - addrcmp( (void *) &(NSSOCKADDR6(i)->sin6_addr), - (void *) &unspec_addr, (int) AF_INET6 ) == 0 ) /* 0.0.0.0 replies as 127.0.0.1 */ - break; - } - } else - for (i = 0;i < myres.nscount;i++) { - if (!NSSOCKADDR6(i)) - continue; - if ( addrcmp( (void *) &(NSSOCKADDR6(i)->sin6_addr), - (void *) &(from6->sin6_addr), AF_INET6 ) == 0 ) - break; - } - if (i == myres.nscount) { - snprintf(tempstring, sizeof(tempstring), - "Resolver error: Received reply from unknown source: %s", - inet_ntop( AF_INET6, &(from6->sin6_addr), addrstr, - sizeof addrstr )); - restell(tempstring); - } else - parserespacket((byte *)resrecvbuf,r); - } else { - snprintf(tempstring, sizeof(tempstring), "Resolver: Socket error: %s",strerror(errno)); - restell(tempstring); - } -} -#endif + r = malloc (sizeof (struct dns_results)); + //r->ip = *ip; + memcpy (&r->ip, ip, sizeof (r->ip)); + r->name = NULL; + r->next = results; + results = r; + printf ("lookup: %s\n", strlongip (ip)); -int istime(double x,double *sinterval) -{ - if (x) { - if (x > sweeptime) { - if (*sinterval > x - sweeptime) - *sinterval = x - sweeptime; - } else - return 1; + sprintf (buf, "%s\n", strlongip (ip)); + write (todns[1], buf, strlen (buf)); } - return 0; + return strlongip (ip); } void dns_events(double *sinterval) { - struct resolve *rp,*nextrp; - - for (rp = expireresolves;(rp) && (sweeptime >= rp->expiretime);rp = nextrp) { - nextrp = rp->next; - switch (rp->state) { - case STATE_FINISHED: /* TTL has expired */ - case STATE_FAILED: /* Fake TTL has expired */ - if (debug) { - snprintf(tempstring, sizeof(tempstring), "Resolver: Cache record for \"%s\" (%s) has expired. (state: %u) Marked for expire at: %g, time: %g.", - nonull(rp->hostname), strlongip( &(rp->ip) ), - rp->state, rp->expiretime, sweeptime); - restell(tempstring); - } - unlinkresolve(rp); - break; - case STATE_PTRREQ1: /* First T_PTR send timed out */ - resendrequest(rp,T_PTR); - restell("Resolver: Send #2 for \"PTR\" query..."); - rp->state++; - rp->expiretime = sweeptime + ResRetryDelay2; - (void)istime(rp->expiretime,sinterval); - res_resend++; - break; - case STATE_PTRREQ2: /* Second T_PTR send timed out */ - resendrequest(rp,T_PTR); - restell("Resolver: Send #3 for \"PTR\" query..."); - rp->state++; - rp->expiretime = sweeptime + ResRetryDelay3; - (void)istime(rp->expiretime,sinterval); - res_resend++; - break; - case STATE_PTRREQ3: /* Third T_PTR timed out */ - restell("Resolver: \"PTR\" query timed out."); - failrp(rp); - (void)istime(rp->expiretime,sinterval); - res_timeout++; - break; - } - } - if (expireresolves) - (void)istime(expireresolves->expiretime,sinterval); -} - - -char *dns_lookup2(ip_t * ip) -{ - struct resolve *rp; - - if ((rp = findip(ip))) { - if ((rp->state == STATE_FINISHED) || (rp->state == STATE_FAILED)) { - if ((rp->state == STATE_FINISHED) && (rp->hostname)) { - if (debug) { - snprintf(tempstring, sizeof(tempstring), "Resolver: Used cached record: %s == \"%s\".\n", - strlongip(ip),rp->hostname); - restell(tempstring); - } - return rp->hostname; - } else { - if (debug) { - snprintf(tempstring, sizeof(tempstring), "Resolver: Used failed record: %s == ???\n", - strlongip(ip)); - restell(tempstring); - } - return NULL; - } - } - return NULL; - } - if (debug) - fprintf(stderr,"Resolver: Added to new record.\n"); - rp = allocresolve(); - rp->state = STATE_PTRREQ1; - rp->expiretime = sweeptime + ResRetryDelay1; - addrcpy( (void *) &(rp->ip), (void *) ip, af ); - linkresolve(rp); - addrcpy( (void *) &(rp->ip), (void *) ip, af ); - linkresolveip(rp); - sendrequest(rp,T_PTR); - return NULL; + return; } @@ -1479,22 +294,23 @@ char *dns_lookup(ip_t * ip) return (t && use_dns) ? t : NULL; } + +#if 0 +char *strlongip(ip_t * ip) +{ #ifdef ENABLE_IPV6 -/* Returns an ip6.arpa character string. */ -void addr2ip6arpa( ip_t * ip, char * buf ) { - unsigned char * p = (unsigned char *) ip; - char * b = buf; - int i; - - for ( i = sizeof (struct in6_addr) - 1; i >= 0; i-- ) { - sprintf( b, "%x.%x.", p[i] % 16, p[i] >> 4 ); - b += 4; - } - sprintf( b, "ip6.arpa" ); - return; + static char addrstr[INET6_ADDRSTRLEN]; + + return (char *) inet_ntop( af, ip, addrstr, sizeof addrstr ); +#else + return inet_ntoa( *ip ); +#endif } #endif + +// XXX check if necessary/exported. + /* Resolve an IP address to a hostname. */ struct hostent *addr2host( const char *addr, int af ) { int len = 0; @@ -1510,3 +326,6 @@ struct hostent *addr2host( const char *addr, int af ) { } return gethostbyaddr( addr, len, af ); } + + +