File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mtr / dns.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Nov 1 09:33:48 2016 UTC (7 years, 7 months ago) by misho
Branches: mtr, elwix, MAIN
CVS tags: v0_86, HEAD
mtr 0.86

    1: /*
    2:     mtr  --  a network diagnostic tool
    3:     Copyright (C) 1997,1998  Matt Kimball
    4: 
    5:     This program is free software; you can redistribute it and/or modify
    6:     it under the terms of the GNU General Public License version 2 as 
    7:     published by the Free Software Foundation.
    8: 
    9:     This program is distributed in the hope that it will be useful,
   10:     but WITHOUT ANY WARRANTY; without even the implied warranty of
   11:     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12:     GNU General Public License for more details.
   13: 
   14:     You should have received a copy of the GNU General Public License
   15:     along with this program; if not, write to the Free Software
   16:     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   17: */
   18: 
   19: /*
   20:     Non-blocking DNS portion --
   21:     Copyright (C) 1998 by Simon Kirby <sim@neato.org>
   22:     Released under GPL, as above.
   23: */
   24: 
   25: #include "config.h"
   26: 
   27: #include <sys/types.h>
   28: #include <sys/time.h>
   29: #include <sys/select.h>
   30: #include <sys/stat.h>
   31: #include <sys/errno.h>
   32: #include <sys/socket.h>
   33: #include <netinet/in.h>
   34: #include <arpa/inet.h>
   35: 
   36: #ifndef __APPLE__
   37: #define BIND_8_COMPAT
   38: #endif
   39: #include <arpa/nameser.h>
   40: #ifdef HAVE_ARPA_NAMESER_COMPAT_H
   41: #include <arpa/nameser_compat.h>
   42: #endif
   43: #include <netdb.h>
   44: #include <resolv.h>
   45: #include <unistd.h>
   46: #include <fcntl.h>
   47: #include <ctype.h>
   48: #include <string.h>
   49: #include <stdio.h>
   50: #include <stdlib.h>
   51: #include <errno.h>
   52: #include <time.h>
   53: 
   54: #include "mtr.h"
   55: #include "dns.h"
   56: #include "net.h"
   57: 
   58: #ifdef ENABLE_IPV6
   59: #ifdef __GLIBC__
   60: #define NSSOCKADDR6(i) (myres._u._ext.nsaddrs[i])
   61: #else
   62: #define NSSOCKADDR6(i) (&(myres._u._ext.ext->nsaddrs[i].sin6))
   63: #endif
   64: #endif
   65: 
   66: 
   67: #ifdef NO_STRERROR
   68: extern int sys_nerr;
   69: extern char *sys_errlist[];
   70: #define strerror(errno) (((errno) >= 0 && (errno) < sys_nerr) ? sys_errlist[errno] : "unlisted error")
   71: #endif
   72: 
   73: #if !HAVE_DECL_ERRNO
   74: /*  Hmm, it seems Irix requires this  */
   75: extern int errno;
   76: #endif
   77: 
   78: extern int af;
   79: 
   80: /* Defines */
   81: 
   82: #undef Debug
   83: 
   84: #undef CorruptCheck
   85: #undef WipeFrees
   86: #undef WipeMallocs
   87: 
   88: #define BashSize 8192			/* Size of hash tables */
   89: #define BashModulo(x) ((x) & 8191)	/* Modulo for hash table size: */
   90: #define HostnameLength 255		/* From RFC */
   91: #define ResRetryDelay1 3
   92: #define ResRetryDelay2 4
   93: #define ResRetryDelay3 5
   94: 
   95: /* Macros */
   96: 
   97: #define nonull(s) (s) ? s : nullstring
   98: 
   99: /* Structures */
  100: 
  101: struct resolve {
  102:    struct resolve *next;
  103:    struct resolve *previous;
  104:    struct resolve *nextid;
  105:    struct resolve *previousid;
  106:    struct resolve *nextip;
  107:    struct resolve *previousip;
  108:    struct resolve *nexthost;
  109:    struct resolve *previoushost;
  110:    float expiretime; /* Fucking HPUX has a problem with "double" here. */
  111:    char *hostname;
  112:    ip_t ip;
  113:    word id;
  114:    byte state;
  115: };
  116: 
  117: /* Non-blocking nameserver interface routines */
  118: 
  119: #define MaxPacketsize (PACKETSZ)
  120: #define DomainLength (MAXDNAME)
  121: 
  122: #define OpcodeCount 3
  123: char *opcodes[OpcodeCount+1] = {
  124:    "standard query",
  125:    "inverse query",
  126:    "server status request",
  127:    "unknown",
  128: };
  129: 
  130: #define ResponsecodeCount 6
  131: char *responsecodes[ResponsecodeCount+1] = {
  132:    "no error",
  133:    "format error in query",
  134:    "server failure",
  135:    "queried domain name does not exist",
  136:    "requested query type not implemented",
  137:    "refused by name server",
  138:    "unknown error",
  139: };
  140: 
  141: #define ResourcetypeCount 17
  142: char *resourcetypes[ResourcetypeCount+1] = {
  143:    "unknown type",
  144:    "A: host address",
  145:    "NS: authoritative name server",
  146:    "MD: mail destination (OBSOLETE)",
  147:    "MF: mail forwarder (OBSOLETE)",
  148:    "CNAME: name alias",
  149:    "SOA: authority record",
  150:    "MB: mailbox domain name (EXPERIMENTAL)",
  151:    "MG: mail group member (EXPERIMENTAL)",
  152:    "MR: mail rename domain name (EXPERIMENTAL)",
  153:    "NULL: NULL RR (EXPERIMENTAL)",
  154:    "WKS: well known service description",
  155:    "PTR: domain name pointer",
  156:    "HINFO: host information",
  157:    "MINFO: mailbox or mail list information",
  158:    "MX: mail exchange",
  159:    "TXT: text string",
  160:    "unknown type",
  161: };
  162: 
  163: #define ClasstypeCount 5
  164: char *classtypes[ClasstypeCount+1] = {
  165:    "unknown class",
  166:    "IN: the Internet",
  167:    "CS: CSNET (OBSOLETE)",
  168:    "CH: CHAOS",
  169:    "HS: Hesoid [Dyer 87]",
  170:    "unknown class"
  171: };
  172: 
  173: char *rrtypes[] = {
  174:    "Unknown",
  175:    "Query",
  176:    "Answer",
  177:    "Authority reference",
  178:    "Resource reference",
  179: };
  180: 
  181: 
  182: /* Please don't use a trailing comma in enumerations: It doesn't
  183:    work on all compilers */
  184: enum {
  185:    RR_UNKNOWN,
  186:    RR_QUERY,
  187:    RR_ANSWER,
  188:    RR_AUTHORITY,
  189:    RR_RESOURCE
  190: };
  191: 
  192: typedef struct {
  193:    word id;             /* Packet id */
  194:    byte databyte_a;
  195:       /* rd:1           recursion desired
  196:        * tc:1           truncated message
  197:        * aa:1           authoritive answer
  198:        * opcode:4       purpose of message
  199:        * qr:1           response flag
  200:        */
  201:    byte databyte_b;
  202:       /* rcode:4        response code
  203:        * unassigned:2   unassigned bits
  204:        * pr:1           primary server required (non standard)
  205:        * ra:1           recursion available
  206:        */
  207:    word qdcount;        /* Query record count */
  208:    word ancount;        /* Answer record count */
  209:    word nscount;        /* Authority reference record count */
  210:    word arcount;        /* Resource reference record count */
  211: } packetheader;
  212: 
  213: #ifndef HFIXEDSZ
  214: #define HFIXEDSZ (sizeof(packetheader))
  215: #endif
  216: 
  217: /*
  218:  * Byte order independent macros for packetheader
  219:  */
  220: #define getheader_rd(x) (x->databyte_a & 1)
  221: #define getheader_tc(x) ((x->databyte_a >> 1) & 1)
  222: #define getheader_aa(x) ((x->databyte_a >> 2) & 1)
  223: #define getheader_opcode(x) ((x->databyte_a >> 3) & 15)
  224: #define getheader_qr(x) (x->databyte_a >> 7)
  225: #define getheader_rcode(x) (x->databyte_b & 15)
  226: #define getheader_pr(x) ((x->databyte_b >> 6) & 1)
  227: #define getheader_ra(x) (x->databyte_b >> 7)
  228: 
  229: #if 0
  230: 
  231: /* The execution order inside an expression is undefined! That means that
  232:    this might work, but then again, it might not... */
  233: 
  234: #define sucknetword(x) (((word)*(x) << 8) | (((x)+= 2)[-1]))
  235: #define sucknetshort(x) (((short)*(x) << 8) | (((x)+= 2)[-1]))
  236: #define sucknetdword(x) (((dword)*(x) << 24) | ((x)[1] << 16) | ((x)[2] << 8) | (((x)+= 4)[-1]))
  237: #define sucknetlong(x) (((long)*(x) << 24) | ((x)[1] << 16) | ((x)[2] << 8) | (((x)+= 4)[-1]))
  238: #else
  239: 
  240: #define sucknetword(x)  ((x)+=2,((word)  (((x)[-2] <<  8) | ((x)[-1] <<  0))))
  241: #define sucknetshort(x) ((x)+=2,((short) (((x)[-2] <<  8) | ((x)[-1] <<  0))))
  242: #define sucknetdword(x) ((x)+=4,((dword) (((x)[-4] << 24) | ((x)[-3] << 16) | \
  243:                                           ((x)[-2] <<  8) | ((x)[-1] <<  0))))
  244: #define sucknetlong(x)  ((x)+=4,((long)  (((x)[-4] << 24) | ((x)[-3] << 16) | \
  245:                                           ((x)[-2] <<  8) | ((x)[-1] <<  0))))
  246: #endif
  247: 
  248: enum {
  249:    STATE_FINISHED,
  250:    STATE_FAILED,
  251:    STATE_PTRREQ1,
  252:    STATE_PTRREQ2,
  253:    STATE_PTRREQ3
  254: };
  255: 
  256: #define Is_PTR(x) ((x->state == STATE_PTRREQ1) || (x->state == STATE_PTRREQ2) || (x->state == STATE_PTRREQ3))
  257: 
  258: dword resrecvbuf[(MaxPacketsize + 7) >> 2]; /* MUST BE DWORD ALIGNED */
  259: 
  260: struct resolve *idbash[BashSize];
  261: struct resolve *ipbash[BashSize];
  262: struct resolve *hostbash[BashSize];
  263: struct resolve *expireresolves = NULL;
  264: struct resolve *lastresolve = NULL;
  265: struct logline *streamlog = NULL;
  266: struct logline *lastlog = NULL;
  267: 
  268: ip_t alignedip;
  269: ip_t localhost;
  270: #ifdef ENABLE_IPV6
  271: ip_t localhost6;
  272: #endif
  273: 
  274: double sweeptime;
  275: 
  276: #ifdef Debug
  277: int debug = 1;
  278: #else
  279: int debug = 0;
  280: #endif
  281: 
  282: dword mem = 0;
  283: 
  284: dword res_iplookupsuccess = 0;
  285: dword res_reversesuccess = 0;
  286: dword res_nxdomain = 0;
  287: dword res_nserror = 0;
  288: dword res_hostipmismatch = 0;
  289: dword res_unknownid = 0;
  290: dword res_resend = 0;
  291: dword res_timeout = 0;
  292: 
  293: dword resolvecount = 0;
  294: 
  295: long idseed = 0xdeadbeef;
  296: long aseed;
  297: 
  298: #ifdef ENABLE_IPV6
  299: struct sockaddr_storage from_sastruct;
  300: struct sockaddr_in6 * from6 = (struct sockaddr_in6 *) &from_sastruct;
  301: #else
  302: struct sockaddr_in from_sastruct;
  303: #endif
  304: 
  305: struct sockaddr_in * from4 = (struct sockaddr_in *) &from_sastruct;
  306: struct sockaddr * from = (struct sockaddr *) &from_sastruct;
  307: 
  308: int resfd;
  309: #ifdef ENABLE_IPV6
  310: int resfd6;
  311: #endif
  312: socklen_t fromlen = sizeof from_sastruct;
  313: 
  314: char tempstring[16384+1+1];
  315: char sendstring[1024+1];
  316: char namestring[1024+1];
  317: char stackstring[1024+1];
  318: 
  319: char nullstring[] = "";
  320: 
  321: int use_dns = 1;
  322: 
  323: #ifdef res_ninit
  324: #define MY_RES_INIT() res_ninit(&myres);
  325: #define RES_MKQUERY(a, b, c, d, e, f, g, h, i) \
  326:     res_nmkquery(&myres, a, b, c, d, e, f, g, h, i)
  327: struct __res_state myres;
  328: #else
  329: #define MY_RES_INIT() res_init();
  330: #define RES_MKQUERY(a, b, c, d, e, f, g, h, i) \
  331:     res_mkquery(a, b, c, d, e, f, g, h, i)
  332: #define myres _res
  333: #endif
  334: 
  335: /* Code */
  336: #ifdef CorruptCheck
  337: #define TOT_SLACK 2
  338: #define HEAD_SLACK 1
  339: /* Need an entry for sparc systems here too. 
  340:    Don't try this on Sparc for now. */
  341: #else
  342: #ifdef sparc
  343: #define TOT_SLACK 2
  344: #define HEAD_SLACK 2
  345: #else
  346: #define TOT_SLACK 1
  347: #define HEAD_SLACK 1
  348: #endif
  349: #endif
  350: 
  351: 
  352: void *statmalloc(size_t size)
  353: {
  354:   void *p;
  355:   size_t mallocsize;
  356: 
  357:   mem+= size;
  358:   mallocsize = size + TOT_SLACK * sizeof(dword);
  359: 
  360:   p = malloc(mallocsize);
  361:   if (!p) {
  362:     fprintf(stderr,"malloc() of %u bytes failed: %s\n", (unsigned int)size, strerror(errno));
  363:     exit(-1);
  364:   }
  365:   *((dword *)p) = (dword)size;
  366: #ifdef CorruptCheck
  367:   *(byte *)((char *)p + size + sizeof(dword) + sizeof(byte) * 0) = 0xde;
  368:   *(byte *)((char *)p + size + sizeof(dword) + sizeof(byte) * 1) = 0xad;
  369:   *(byte *)((char *)p + size + sizeof(dword) + sizeof(byte) * 2) = 0xbe;
  370:   *(byte *)((char *)p + size + sizeof(dword) + sizeof(byte) * 3) = 0xef;
  371: #endif
  372:   p = (void *)((dword *)p + HEAD_SLACK);
  373: #ifdef WipeMallocs
  374:   memset(p,0xf0,size);
  375: #endif
  376:   return p;
  377: }
  378: 
  379: 
  380: void statfree(void *p)
  381: {
  382:   if (p) {
  383:     if (*((dword *)p - HEAD_SLACK) == 0) {
  384:       fprintf(stderr,"ERROR: Attempt to free pointer twice.\n");
  385:       abort();
  386:       exit(-1);
  387:     } else {
  388:       if (*((dword *)p - HEAD_SLACK) > 8192) {
  389: 	fprintf (stderr,"ERROR: Corrupted free() buffer. (header)\n");
  390:         abort();
  391: 	exit(-1);
  392:       }
  393: #ifdef CorruptCheck
  394:       if ((*(byte *)((char *)p + (*((dword *)p - 1)) + sizeof(byte) * 0) != 0xde) ||
  395: 	  (*(byte *)((char *)p + (*((dword *)p - 1)) + sizeof(byte) * 1) != 0xad) ||
  396: 	  (*(byte *)((char *)p + (*((dword *)p - 1)) + sizeof(byte) * 2) != 0xbe) ||
  397: 	  (*(byte *)((char *)p + (*((dword *)p - 1)) + sizeof(byte) * 3) != 0xef)) {
  398: 	fprintf(stderr,"ERROR: Corrupted free() buffer. (footer)\n");
  399: 	abort();
  400: 	exit(-1);
  401:       }
  402: #endif
  403:       mem-= *((dword *)p - HEAD_SLACK);
  404: #ifdef WipeFrees
  405:       memset(p,0xfe,*((dword *)p - HEAD_SLACK));
  406:       *((dword *)p - 1) = 0;
  407: #endif
  408:       free((dword *)p - HEAD_SLACK);
  409:     }
  410:   }
  411: }
  412: 
  413: 
  414: char *strtdiff(char *d,long signeddiff)
  415: {
  416:   dword diff;
  417:   dword seconds,minutes,hours;
  418:   long days;
  419: 
  420:   if ((diff = labs(signeddiff))) {
  421:     seconds = diff % 60; diff/= 60;
  422:     minutes = diff % 60; diff/= 60;
  423:     hours = diff % 24;
  424:     days = signeddiff / (60 * 60 * 24);
  425:     if (days)
  426:       sprintf(d,"%lid",days);
  427:     else
  428:       *d = '\0';
  429:     if (hours)
  430:       sprintf(d + strlen(d),"%luh",hours);
  431:     if (minutes)
  432:       sprintf(d + strlen(d),"%lum",minutes);
  433:     if (seconds)
  434:       sprintf(d + strlen(d),"%lus",seconds);
  435:   } else
  436:     sprintf(d,"0s");
  437:   return d;
  438: }
  439: 
  440: 
  441: int issetfd(fd_set *set,int fd)
  442: {
  443:   return (int)((FD_ISSET(fd,set)) && 1);
  444: }
  445: 
  446: 
  447: void setfd(fd_set *set,int fd)
  448: {
  449:   FD_SET(fd,set);
  450: }
  451: 
  452: 
  453: void clearfd(fd_set *set,int fd)
  454: {
  455:   FD_CLR(fd,set);
  456: }
  457: 
  458: 
  459: void clearset(fd_set *set)
  460: {
  461:   FD_ZERO(set);
  462: }
  463: 
  464: 
  465: char *strlongip(ip_t * ip)
  466: {
  467: #ifdef ENABLE_IPV6
  468:   static char addrstr[INET6_ADDRSTRLEN];
  469: 
  470:   return (char *) inet_ntop( af, ip, addrstr, sizeof addrstr );
  471: #else
  472:   return inet_ntoa( *ip );
  473: #endif
  474: }
  475: 
  476: 
  477: int longipstr( char *s, ip_t *dst, int af )
  478: {
  479: #ifdef ENABLE_IPV6
  480:   return inet_pton( af, s, dst );
  481: #else
  482:   return inet_aton( s, dst );
  483: #endif
  484: }
  485: 
  486: 
  487: struct hostent * dns_forward(const char *name)
  488: {
  489:   struct hostent *host;
  490: 
  491:   if ((host = gethostbyname(name)))
  492:     return host;
  493:   else
  494:     return NULL;
  495: }
  496: 
  497: 
  498: int dns_waitfd(void)
  499: {
  500:   return resfd;
  501: }
  502: #ifdef ENABLE_IPV6
  503: int dns_waitfd6(void)
  504: {
  505:   return resfd6;
  506: }
  507: #endif
  508: 
  509: 
  510: void dns_open(void)
  511: {
  512:   int option,i;
  513: 
  514:   if (!dns) return;
  515:   MY_RES_INIT();
  516:   if (!myres.nscount) {
  517:     fprintf(stderr,"No nameservers defined.\n");
  518:     exit(-1);
  519:   }
  520:   myres.options|= RES_RECURSE | RES_DEFNAMES | RES_DNSRCH;
  521:   resfd = socket(AF_INET, SOCK_DGRAM, 0);
  522:   if (resfd == -1) {
  523:     fprintf(stderr,
  524:             "Unable to allocate IPv4 socket for nameserver communication: %s\n",
  525: 	    strerror(errno));
  526:     exit(-1);
  527:   }
  528: #ifdef ENABLE_IPV6
  529:   resfd6 = socket(AF_INET6, SOCK_DGRAM, 0);
  530:   if (resfd6 == -1) {
  531:     // consider making removing this warning. For now leave it in to see 
  532:     // new code activated. -- REW
  533:     fprintf(stderr,
  534:             "Unable to allocate IPv6 socket for nameserver communication: %s\n",
  535: 	    strerror(errno));
  536:     //    exit(-1);
  537:   }
  538: #endif
  539:   option = 1;
  540:   if (setsockopt(resfd,SOL_SOCKET,SO_BROADCAST,(char *)&option,sizeof(option))) {
  541:     fprintf(stderr,
  542:             "Unable to setsockopt() on IPv4 nameserver communication socket: %s\n",
  543: 	    strerror(errno));
  544:     exit(-1);
  545:   }
  546: #ifdef ENABLE_IPV6
  547:   if (resfd6 > 0) {
  548:     if (setsockopt(resfd6,SOL_SOCKET,SO_BROADCAST,(char *)&option,sizeof(option))) {
  549:       fprintf(stderr,
  550: 	      "Unable to setsockopt() on IPv6 nameserver communication socket: %s\n",
  551: 	      strerror(errno));
  552:       exit(-1);
  553:     }
  554:   }
  555: #endif
  556:   longipstr( "127.0.0.1", &localhost, AF_INET );
  557: #ifdef ENABLE_IPV6
  558:   longipstr( "::1", &localhost6, AF_INET6 );
  559: #endif
  560:   aseed = time(NULL) ^ (time(NULL) << 3) ^ (dword)getpid();
  561:   for (i = 0;i < BashSize;i++) {
  562:     idbash[i] = NULL;
  563:     hostbash[i] = NULL;
  564:   }
  565: }
  566: 
  567: 
  568: struct resolve *allocresolve(void)
  569: {
  570:   struct resolve *rp;
  571: 
  572:   rp = (struct resolve *)statmalloc(sizeof(struct resolve));
  573:   if (!rp) {
  574:     fprintf(stderr,"statmalloc() failed: %s\n",strerror(errno));
  575:     exit(-1);
  576:   }
  577:   memset(rp,0, sizeof(struct resolve));
  578:   return rp;
  579: }
  580: 
  581: 
  582: dword getidbash(word id)
  583: {
  584:   return (dword)BashModulo(id);
  585: }
  586: 
  587: 
  588: dword getipbash(ip_t * ip)
  589: {
  590:   char *p = (char *) ip;
  591:   int i, len = 0;
  592:   dword bashvalue = 0;
  593: 
  594:   switch ( af ) {
  595:   case AF_INET:
  596:     len = sizeof (struct in_addr);
  597:     break;
  598: #ifdef ENABLE_IPV6
  599:   case AF_INET6:
  600:     len = sizeof (struct in6_addr);
  601:     break;
  602: #endif
  603:   }
  604:   for (i = 0; i < len; i++, p++) {
  605:     bashvalue^= *p;
  606:     bashvalue+= (*p >> 1) + (bashvalue >> 1);
  607:   }
  608:   return BashModulo(bashvalue);
  609: }
  610: 
  611: 
  612: dword gethostbash(char *host)
  613: {
  614:   dword bashvalue = 0;
  615: 
  616:   for (;*host;host++) {
  617:     bashvalue^= *host;
  618:     bashvalue+= (*host >> 1) + (bashvalue >> 1);
  619:   }
  620:   return BashModulo(bashvalue);
  621: }
  622: 
  623: 
  624: void linkresolveid(struct resolve *addrp)
  625: {
  626:   struct resolve *rp;
  627:   dword bashnum;
  628: 
  629:   bashnum = getidbash(addrp->id);
  630:   rp = idbash[bashnum];
  631:   if (rp) {
  632:     while ((rp->nextid) && (addrp->id > rp->nextid->id))
  633:       rp = rp->nextid;
  634:     while ((rp->previousid) && (addrp->id < rp->previousid->id))
  635:       rp = rp->previousid;
  636:     if (rp->id < addrp->id) {
  637:       addrp->previousid = rp;
  638:       addrp->nextid = rp->nextid;
  639:       if (rp->nextid)
  640: 	rp->nextid->previousid = addrp;
  641:       rp->nextid = addrp;
  642:     } else {
  643:       addrp->previousid = rp->previousid;
  644:       addrp->nextid = rp;
  645:       if (rp->previousid)
  646: 	rp->previousid->nextid = addrp;
  647:       rp->previousid = addrp;
  648:     }
  649:   } else
  650:     addrp->nextid = addrp->previousid = NULL;
  651:   idbash[bashnum] = addrp;
  652: }
  653: 
  654: 
  655: void unlinkresolveid(struct resolve *rp)
  656: {
  657:   dword bashnum;
  658: 
  659:   bashnum = getidbash(rp->id);
  660:   if (idbash[bashnum] == rp) 
  661:     idbash[bashnum] = (rp->previousid)? rp->previousid : rp->nextid;
  662:   if (rp->nextid)
  663:     rp->nextid->previousid = rp->previousid;
  664:   if (rp->previousid)
  665:     rp->previousid->nextid = rp->nextid;
  666: }
  667: 
  668: 
  669: void linkresolvehost(struct resolve *addrp)
  670: {
  671:   struct resolve *rp;
  672:   dword bashnum;
  673: 
  674:   bashnum = gethostbash(addrp->hostname);
  675:   rp = hostbash[bashnum];
  676:   if (rp) {
  677:     while ((rp->nexthost) && (strcasecmp(addrp->hostname,rp->nexthost->hostname) < 0))
  678:       rp = rp->nexthost;
  679:     while ((rp->previoushost) && (strcasecmp(addrp->hostname,rp->previoushost->hostname) > 0))
  680:       rp = rp->previoushost;
  681:     if (strcasecmp(addrp->hostname,rp->hostname) < 0) {
  682:       addrp->previoushost = rp;
  683:       addrp->nexthost = rp->nexthost;
  684:       if (rp->nexthost)
  685: 	rp->nexthost->previoushost = addrp;
  686:       rp->nexthost = addrp;
  687:     } else {
  688:       addrp->previoushost = rp->previoushost;
  689:       addrp->nexthost = rp;
  690:       if (rp->previoushost)
  691: 	rp->previoushost->nexthost = addrp;
  692:       rp->previoushost = addrp;
  693:     }
  694:   } else
  695:     addrp->nexthost = addrp->previoushost = NULL;
  696:   hostbash[bashnum] = addrp;
  697: }
  698: 
  699: 
  700: void unlinkresolvehost(struct resolve *rp)
  701: {
  702:   dword bashnum;
  703: 
  704:   bashnum = gethostbash(rp->hostname);
  705:   if (hostbash[bashnum] == rp)
  706:     hostbash[bashnum] = (rp->previoushost)? rp->previoushost : rp->nexthost;
  707:   if (rp->nexthost)
  708:     rp->nexthost->previoushost = rp->previoushost;
  709:   if (rp->previoushost)
  710:     rp->previoushost->nexthost = rp->nexthost;
  711:   statfree(rp->hostname);
  712: }
  713: 
  714: 
  715: void linkresolveip(struct resolve *addrp)
  716: {
  717:   struct resolve *rp;
  718:   dword bashnum;
  719: 
  720:   bashnum = getipbash( &(addrp->ip) );
  721:   rp = ipbash[bashnum];
  722:   if (rp) {
  723:     while ((rp->nextip) &&
  724: 	   ( addrcmp( (void *) &(addrp->ip),
  725: 		      (void *) &(rp->nextip->ip), af ) > 0 ))
  726:       rp = rp->nextip;
  727:     while ((rp->previousip) &&
  728: 	   ( addrcmp( (void *) &(addrp->ip),
  729: 		      (void *) &(rp->previousip->ip), af ) < 0 ))
  730:       rp = rp->previousip;
  731:     if ( addrcmp( (void *) &(rp->ip), (void *) &(addrp->ip), af ) < 0 ) {
  732:       addrp->previousip = rp;
  733:       addrp->nextip = rp->nextip;
  734:       if (rp->nextip)
  735: 	rp->nextip->previousip = addrp;
  736:       rp->nextip = addrp;
  737:     } else {
  738:       addrp->previousip = rp->previousip;
  739:       addrp->nextip = rp;
  740:       if (rp->previousip)
  741: 	rp->previousip->nextip = addrp;
  742:       rp->previousip = addrp;
  743:     }
  744:   } else
  745:     addrp->nextip = addrp->previousip = NULL;
  746:   ipbash[bashnum] = addrp;
  747: }
  748: 
  749: 
  750: void unlinkresolveip(struct resolve *rp)
  751: {
  752:   dword bashnum;
  753: 
  754:   bashnum = getipbash( &(rp->ip) );
  755:   if (ipbash[bashnum] == rp)
  756:     ipbash[bashnum] = (rp->previousip)? rp->previousip : rp->nextip;
  757:   if (rp->nextip)
  758:     rp->nextip->previousip = rp->previousip;
  759:   if (rp->previousip)
  760:     rp->previousip->nextip = rp->nextip;
  761: }
  762: 
  763: 
  764: void linkresolve(struct resolve *rp)
  765: {
  766:   struct resolve *irp;
  767: 
  768:   if (expireresolves) {
  769:     irp = expireresolves;
  770:     while ((irp->next) && (rp->expiretime >= irp->expiretime)) irp = irp->next;
  771:     if (rp->expiretime >= irp->expiretime) {
  772:       rp->next = NULL;
  773:       rp->previous = irp;
  774:       irp->next = rp;
  775:       lastresolve = rp;
  776:     } else {
  777:       rp->previous = irp->previous;
  778:       rp->next = irp;
  779:       if (irp->previous)
  780: 	irp->previous->next = rp;
  781:       else
  782: 	expireresolves = rp;
  783:       irp->previous = rp;
  784:     }
  785:   } else {
  786:     rp->next = NULL;
  787:     rp->previous = NULL;
  788:     expireresolves = lastresolve = rp;
  789:   }
  790:   resolvecount++;
  791: }
  792: 
  793: 
  794: void lastlinkresolve(struct resolve *rp)
  795: {
  796:   struct resolve *irp;
  797: 
  798:   if (lastresolve) {
  799:     irp = lastresolve;
  800:     while ((irp->previous) && (rp->expiretime < irp->expiretime)) irp = irp->previous;
  801:     while ((irp->next) && (rp->expiretime >= irp->expiretime)) irp = irp->next;
  802:     if (rp->expiretime >= irp->expiretime) {
  803:       rp->next = NULL;
  804:       rp->previous = irp;
  805:       irp->next = rp;
  806:       lastresolve = rp;
  807:     } else {
  808:       rp->previous = irp->previous;
  809:       rp->next = irp;
  810:       if (irp->previous)
  811: 	irp->previous->next = rp;
  812:       else
  813: 	expireresolves = rp;
  814:       irp->previous = rp;
  815:     }
  816:   } else {
  817:     rp->next = NULL;
  818:     rp->previous = NULL;
  819:     expireresolves = lastresolve = rp;
  820:   }
  821:   resolvecount++;
  822: }
  823: 
  824: 
  825: void untieresolve(struct resolve *rp)
  826: {
  827:   if (rp->previous)
  828:     rp->previous->next = rp->next;
  829:   else
  830:     expireresolves = rp->next;
  831:   if (rp->next)
  832:     rp->next->previous = rp->previous;
  833:   else
  834:     lastresolve = rp->previous;
  835:   resolvecount--;
  836: }
  837: 
  838: 
  839: void unlinkresolve(struct resolve *rp)
  840: {
  841:   untieresolve(rp);
  842:   unlinkresolveid(rp);
  843:   unlinkresolveip(rp);
  844:   if (rp->hostname)
  845:     unlinkresolvehost(rp);
  846: }
  847: 
  848: 
  849: struct resolve *findid(word id)
  850: {
  851:   struct resolve *rp;
  852:   int bashnum;
  853: 
  854:   bashnum = getidbash(id);
  855:   rp = idbash[bashnum];
  856:   if (rp) {
  857:     while ((rp->nextid) && (id >= rp->nextid->id))
  858:       rp = rp->nextid;
  859:     while ((rp->previousid) && (id <= rp->previousid->id))
  860:       rp = rp->previousid;
  861:     if (id == rp->id) {
  862:       idbash[bashnum] = rp;
  863:       return rp;
  864:     } else
  865:       return NULL;
  866:   }
  867:   return rp; /* NULL */
  868: }
  869: 
  870: 
  871: struct resolve *findhost(char *hostname)
  872: {
  873:   struct resolve *rp;
  874:   int bashnum;
  875: 
  876:   bashnum = gethostbash(hostname);
  877:   rp = hostbash[bashnum];
  878:   if (rp) {
  879:     while ((rp->nexthost) && (strcasecmp(hostname,rp->nexthost->hostname) >= 0))
  880:       rp = rp->nexthost;
  881:     while ((rp->previoushost) && (strcasecmp(hostname,rp->nexthost->hostname) <= 0))
  882:       rp = rp->previoushost;
  883:     if (strcasecmp(hostname,rp->hostname))
  884:       return NULL;
  885:     else {
  886:       hostbash[bashnum] = rp;
  887:       return rp;
  888:     }
  889:   }
  890:   return rp; /* NULL */
  891: }
  892: 
  893: 
  894: struct resolve *findip(ip_t * ip)
  895: {
  896:   struct resolve *rp;
  897:   dword bashnum;
  898: 
  899:   bashnum = getipbash(ip);
  900:   rp = ipbash[bashnum];
  901:   if (rp) {
  902:     while ((rp->nextip) &&
  903: 	   ( addrcmp( (void *) ip, (void *) &(rp->nextip->ip), af ) >= 0 ))
  904:       rp = rp->nextip;
  905:     while ((rp->previousip) &&
  906:            ( addrcmp( (void *) ip, (void *) &(rp->previousip->ip), af ) <= 0 ))
  907:       rp = rp->previousip;
  908:     if ( addrcmp( (void *) ip, (void *) &(rp->ip), af ) == 0 ) {
  909:       ipbash[bashnum] = rp;
  910:       return rp;
  911:     } else
  912:       return NULL;
  913:   }
  914:   return rp; /* NULL */
  915: }
  916: 
  917: 
  918: void restell(char *s)
  919: {
  920:   fputs(s,stderr);
  921:   fputs("\r",stderr);
  922: }
  923: 
  924: 
  925: void dorequest(char *s,int type,word id)
  926: {
  927:   packetheader *hp;
  928:   int r,i;
  929:   unsigned char buf[MaxPacketsize];
  930: 
  931:   r = RES_MKQUERY(QUERY,s,C_IN,type,NULL,0,NULL,(unsigned char*)buf,MaxPacketsize);
  932:   if (r == -1) {
  933:     restell("Resolver error: Query too large.");
  934:     return;
  935:   }
  936:   hp = (packetheader *)buf;
  937:   hp->id = id;	/* htons() deliberately left out (redundant) */
  938:   for (i = 0;i < myres.nscount;i++)
  939:     if (myres.nsaddr_list[i].sin_family == AF_INET)
  940:       (void)sendto(resfd,buf,r,0,(struct sockaddr *)&myres.nsaddr_list[i],
  941: 		   sizeof(struct sockaddr));
  942: #ifdef ENABLE_IPV6
  943:     else if (resfd6 > 0) {
  944:       if (!NSSOCKADDR6(i))
  945: 	continue;
  946:       if (NSSOCKADDR6(i)->sin6_family == AF_INET6)
  947: 	(void)sendto(resfd6,buf,r,0,(struct sockaddr *) NSSOCKADDR6(i),
  948: 		     sizeof(struct sockaddr_in6));
  949:     }
  950: #endif
  951: }
  952: 
  953: void resendrequest(struct resolve *rp,int type)
  954: {
  955:   if (type == T_A) {
  956:     dorequest(rp->hostname,type,rp->id);
  957:     if (debug) {
  958:       snprintf(tempstring, sizeof(tempstring), "Resolver: Sent reverse authentication request for \"%s\".",
  959: 	      rp->hostname);
  960:       restell(tempstring);
  961:     }
  962:   } else if (type == T_PTR) {
  963:     switch ( af ) {
  964:     case AF_INET:
  965:     sprintf(tempstring,"%u.%u.%u.%u.in-addr.arpa",
  966: 	    ((byte *)&rp->ip)[3],
  967: 	    ((byte *)&rp->ip)[2],
  968: 	    ((byte *)&rp->ip)[1],
  969: 	    ((byte *)&rp->ip)[0]);
  970:       break;
  971: #ifdef ENABLE_IPV6
  972:     case AF_INET6:
  973:       addr2ip6arpa( &(rp->ip), tempstring );
  974:       break;
  975: #endif
  976:     }
  977:     dorequest(tempstring,type,rp->id);
  978:     if (debug) {
  979:       snprintf(tempstring, sizeof(tempstring), "Resolver: Sent domain lookup request for \"%s\".",
  980: 	      strlongip( &(rp->ip) ));
  981:       restell(tempstring);
  982:     }
  983:   }
  984: }
  985: 
  986: void sendrequest(struct resolve *rp,int type)
  987: {
  988:   do {
  989:     idseed = (((idseed + idseed) | (long)time(NULL)) + idseed - 0x54bad4a) ^ aseed;
  990:     aseed^= idseed;
  991:     rp->id = (word)idseed;
  992:   } while (findid(rp->id));
  993:   linkresolveid(rp);
  994:   resendrequest(rp,type);
  995: }
  996: 
  997: 
  998: void failrp(struct resolve *rp)
  999: {
 1000:   if (rp->state == STATE_FINISHED)
 1001:     return;
 1002:   rp->state = STATE_FAILED;
 1003:   untieresolve(rp);
 1004:   if (debug)
 1005:     restell("Resolver: Lookup failed.\n");
 1006: }
 1007: 
 1008: 
 1009: void passrp(struct resolve *rp,long ttl)
 1010: {
 1011:   rp->state = STATE_FINISHED;
 1012:   rp->expiretime = sweeptime + (double)ttl;
 1013:   untieresolve(rp);
 1014:   if (debug) {
 1015:     snprintf(tempstring, sizeof(tempstring), "Resolver: Lookup successful: %s\n",rp->hostname);
 1016:     restell(tempstring);
 1017:   }
 1018: }
 1019: 
 1020: 
 1021: void parserespacket(byte *s, int l)
 1022: {
 1023:   struct resolve *rp;
 1024:   packetheader *hp;
 1025:   byte *eob;
 1026:   byte *c;
 1027:   long ttl;
 1028:   int r,usefulanswer;
 1029:   word rr,datatype,class,qdatatype,qclass;
 1030:   byte rdatalength;
 1031: 
 1032:   if (l < (int) sizeof(packetheader)) {
 1033:     restell("Resolver error: Packet smaller than standard header size.");
 1034:     return;
 1035:   }
 1036:   if (l == (int) sizeof(packetheader)) {
 1037:     restell("Resolver error: Packet has empty body.");
 1038:     return;
 1039:   }
 1040:   hp = (packetheader *)s;
 1041:   /* Convert data to host byte order */
 1042:   /* hp->id does not need to be redundantly byte-order flipped, it is only echoed by nameserver */
 1043:   rp = findid(hp->id);
 1044:   if (!rp) {
 1045:     res_unknownid++;
 1046:     return;
 1047:   }
 1048:   if ((rp->state == STATE_FINISHED) || (rp->state == STATE_FAILED))
 1049:     return;
 1050:   hp->qdcount = ntohs(hp->qdcount);
 1051:   hp->ancount = ntohs(hp->ancount);
 1052:   hp->nscount = ntohs(hp->nscount);
 1053:   hp->arcount = ntohs(hp->arcount);
 1054:   if (getheader_tc(hp)) { /* Packet truncated */
 1055:     restell("Resolver error: Nameserver packet truncated.");
 1056:     return;
 1057:   }
 1058:   if (!getheader_qr(hp)) { /* Not a reply */
 1059:     restell("Resolver error: Query packet received on nameserver communication socket.");
 1060:     return;
 1061:   }
 1062:   if (getheader_opcode(hp)) { /* Not opcode 0 (standard query) */
 1063:     restell("Resolver error: Invalid opcode in response packet.");
 1064:     return;
 1065:   }
 1066:   eob = s + l;
 1067:   c = s + HFIXEDSZ;
 1068:   switch (getheader_rcode(hp)) {
 1069:   case NOERROR:
 1070:     if (hp->ancount) {
 1071:       if (debug) {
 1072: 	snprintf(tempstring, sizeof(tempstring), "Resolver: Received nameserver reply. (qd:%u an:%u ns:%u ar:%u)",
 1073:                 hp->qdcount,hp->ancount,hp->nscount,hp->arcount);
 1074: 	restell(tempstring);
 1075:       }
 1076:       if (hp->qdcount != 1) {
 1077: 	restell("Resolver error: Reply does not contain one query.");
 1078: 	return;
 1079:       }
 1080:       if (c > eob) {
 1081: 	restell("Resolver error: Reply too short.");
 1082: 	return;
 1083:       }
 1084:       switch (rp->state) { /* Construct expected query reply */
 1085:       case STATE_PTRREQ1:
 1086:       case STATE_PTRREQ2:
 1087:       case STATE_PTRREQ3:
 1088:         switch ( af ) {
 1089:         case AF_INET:
 1090: 	sprintf(stackstring,"%u.%u.%u.%u.in-addr.arpa",
 1091: 		((byte *)&rp->ip)[3],
 1092: 		((byte *)&rp->ip)[2],
 1093: 		((byte *)&rp->ip)[1],
 1094: 		((byte *)&rp->ip)[0]);
 1095: 	break;
 1096: #ifdef ENABLE_IPV6
 1097:         case AF_INET6:
 1098:           addr2ip6arpa( &(rp->ip), stackstring );
 1099:           break;
 1100: #endif
 1101:         }
 1102:       }
 1103:       *namestring = '\0';
 1104:       r = dn_expand(s,s + l,c,namestring,MAXDNAME);
 1105:       if (r == -1) {
 1106: 	restell("Resolver error: dn_expand() failed while expanding query domain.");
 1107: 	return;
 1108:       }
 1109:       namestring[strlen(stackstring)] = '\0';
 1110:       if (strcasecmp(stackstring,namestring)) {
 1111: 	if (debug) {
 1112: 	  snprintf(tempstring, sizeof(tempstring), "Resolver: Unknown query packet dropped. (\"%s\" does not match \"%s\")",
 1113: 		  stackstring,namestring);
 1114: 	  restell(tempstring);
 1115: 	}
 1116: 	return;
 1117:       }
 1118:       if (debug) {
 1119: 	snprintf(tempstring, sizeof(tempstring), "Resolver: Queried domain name: \"%s\"",namestring);
 1120: 	restell(tempstring);
 1121:       }
 1122:       c+= r;
 1123:       if (c + 4 > eob) {
 1124: 	restell("Resolver error: Query resource record truncated.");
 1125: 	return;
 1126:       }
 1127:       qdatatype = sucknetword(c);
 1128:       qclass = sucknetword(c);
 1129:       if (qclass != C_IN) {
 1130: 	snprintf(tempstring, sizeof(tempstring), "Resolver error: Received unsupported query class: %u (%s)",
 1131:                 qclass,qclass < ClasstypeCount ? classtypes[qclass] :
 1132: 		classtypes[ClasstypeCount]);
 1133: 	restell(tempstring);
 1134:       }
 1135:       switch (qdatatype) {
 1136:       case T_PTR:
 1137: 	if (!Is_PTR(rp))
 1138: 	  if (debug) {
 1139: 	    restell("Resolver warning: Ignoring response with unexpected query type \"PTR\".");
 1140: 	    return;
 1141: 	  }
 1142: 	break;
 1143:       default:
 1144: 	snprintf(tempstring, sizeof(tempstring), "Resolver error: Received unimplemented query type: %u (%s)",
 1145: 		qdatatype,qdatatype < ResourcetypeCount ?
 1146: 		resourcetypes[qdatatype] : resourcetypes[ResourcetypeCount]);
 1147: 	restell(tempstring);
 1148:       }
 1149:       for (rr = hp->ancount + hp->nscount + hp->arcount;rr;rr--) {
 1150: 	if (c > eob) {
 1151: 	  restell("Resolver error: Packet does not contain all specified resouce records.");
 1152: 	  return;
 1153: 	}
 1154: 	*namestring = '\0';
 1155: 	r = dn_expand(s,s + l,c,namestring,MAXDNAME);
 1156: 	if (r == -1) {
 1157: 	  restell("Resolver error: dn_expand() failed while expanding answer domain.");
 1158: 	  return;
 1159: 	}
 1160: 	namestring[strlen(stackstring)] = '\0';
 1161: 	if (strcasecmp(stackstring,namestring))
 1162: 	  usefulanswer = 0;
 1163: 	else
 1164: 	  usefulanswer = 1;
 1165: 	if (debug) {
 1166: 	  snprintf(tempstring, sizeof(tempstring), "Resolver: answered domain query: \"%s\"",namestring);
 1167: 	  restell(tempstring);
 1168: 	}
 1169: 	c+= r;
 1170: 	if (c + 10 > eob) {
 1171: 	  restell("Resolver error: Resource record truncated.");
 1172: 	  return;
 1173: 	}
 1174: 	datatype = sucknetword(c);
 1175: 	class = sucknetword(c);
 1176: 	ttl = sucknetlong(c);
 1177: 	rdatalength = sucknetword(c);
 1178: 	if (class != qclass) {
 1179: 	  snprintf(tempstring, sizeof(tempstring), "query class: %u (%s)",qclass,qclass < ClasstypeCount ?
 1180: 		  classtypes[qclass] : classtypes[ClasstypeCount]);
 1181: 	  restell(tempstring);
 1182: 	  snprintf(tempstring, sizeof(tempstring), "rr class: %u (%s)",class,class < ClasstypeCount ?
 1183: 		  classtypes[class] : classtypes[ClasstypeCount]);
 1184: 	  restell(tempstring);
 1185: 	  restell("Resolver error: Answered class does not match queried class.");
 1186: 	  return;
 1187: 	}
 1188: 	if (!rdatalength) {
 1189: 	  restell("Resolver error: Zero size rdata.");
 1190: 	  return;
 1191: 	}
 1192: 	if (c + rdatalength > eob) {
 1193: 	  restell("Resolver error: Specified rdata length exceeds packet size.");
 1194: 	  return;
 1195: 	}
 1196: 	if (datatype == qdatatype || datatype == T_CNAME) {
 1197: 	  if (debug) {
 1198: 	    snprintf(tempstring, sizeof(tempstring), "Resolver: TTL: %s",strtdiff(sendstring,ttl));
 1199: 	    restell(tempstring);
 1200: 	  }
 1201: 	  if (usefulanswer)
 1202: 	    switch (datatype) {
 1203: 	    case T_A:
 1204: 	      if (rdatalength != 4) {
 1205: 		snprintf(tempstring, sizeof(tempstring), "Resolver error: Unsupported rdata format for \"A\" type. (%u bytes)",
 1206: 			rdatalength);
 1207: 		restell(tempstring);
 1208: 		return;
 1209: 	      }
 1210: 	      if ( addrcmp( (void *) &(rp->ip), (void *) c, af ) == 0 ) {
 1211: 		snprintf(tempstring, sizeof(tempstring), "Resolver: Reverse authentication failed: %s != ",
 1212: 			strlongip( &(rp->ip) ));
 1213: 		addrcpy( (void *) &alignedip, (void *) c, af );
 1214: 		strcat(tempstring,strlongip( &alignedip ));
 1215: 		restell(tempstring);
 1216: 		res_hostipmismatch++;
 1217: 		failrp(rp);
 1218: 	      } else {
 1219: 		snprintf(tempstring, sizeof(tempstring), "Resolver: Reverse authentication complete: %s == \"%s\".",
 1220: 			strlongip( &(rp->ip) ),nonull(rp->hostname));
 1221: 		restell(tempstring);
 1222: 		res_reversesuccess++;
 1223: 		passrp(rp,ttl);
 1224: 		return;
 1225: 	      }
 1226: 	      break;
 1227: 	    case T_PTR:
 1228: 	    case T_CNAME:
 1229: 	      *namestring = '\0';
 1230: 	      r = dn_expand(s,s + l,c,namestring,MAXDNAME);
 1231: 	      if (r == -1) {
 1232: 		restell("Resolver error: dn_expand() failed while expanding domain in rdata.");
 1233: 		return;
 1234: 	      }
 1235: 	      if (debug) {
 1236: 		snprintf(tempstring, sizeof(tempstring), "Resolver: Answered domain: \"%s\"",namestring);
 1237: 		restell(tempstring);
 1238: 	      }
 1239: 	      if (r > HostnameLength) {
 1240: 		restell("Resolver error: Domain name too long.");
 1241: 		failrp(rp);
 1242: 		return;
 1243: 	      }
 1244: 	      if (datatype == T_CNAME) {
 1245: 		strcpy(stackstring,namestring);
 1246: 		break;
 1247: 	      }
 1248: 	      if (!rp->hostname) {
 1249: 		rp->hostname = (char *)statmalloc(strlen(namestring) + 1);
 1250: 		if (!rp->hostname) {
 1251: 		  fprintf(stderr,"statmalloc() error: %s\n",strerror(errno));
 1252: 		  exit(-1);
 1253: 		}
 1254: 		strcpy(rp->hostname,namestring);
 1255: 		linkresolvehost(rp);
 1256: 		passrp(rp,ttl);
 1257: 		res_iplookupsuccess++;
 1258: 	      }
 1259: 	      break;
 1260: 	    default:
 1261: 	      snprintf(tempstring, sizeof(tempstring), "Resolver error: Received unimplemented data type: %u (%s)",
 1262: 		      datatype,datatype < ResourcetypeCount ?
 1263: 		      resourcetypes[datatype] : resourcetypes[ResourcetypeCount]);
 1264: 	      restell(tempstring);
 1265: 	    }
 1266: 	} else {
 1267: 	  if (debug) {
 1268: 	    snprintf(tempstring, sizeof(tempstring), "Resolver: Ignoring resource type %u. (%s)",
 1269: 		    datatype,datatype < ResourcetypeCount ?
 1270: 		    resourcetypes[datatype] : resourcetypes[ResourcetypeCount]);
 1271: 	    restell(tempstring);
 1272: 	  }
 1273: 	}
 1274: 	c+= rdatalength;
 1275:       }
 1276:     } else
 1277:       restell("Resolver error: No error returned but no answers given.");
 1278:     break;
 1279:   case NXDOMAIN:
 1280:     if (debug)
 1281:       restell("Resolver: Host not found.");
 1282:     res_nxdomain++;
 1283:     failrp(rp);
 1284:     break;
 1285:   default:
 1286:     snprintf(tempstring, sizeof(tempstring), "Resolver: Received error response %u. (%s)",
 1287: 	    getheader_rcode(hp),getheader_rcode(hp) < ResponsecodeCount ?
 1288: 	    responsecodes[getheader_rcode(hp)] : responsecodes[ResponsecodeCount]);
 1289:     restell(tempstring);
 1290:     res_nserror++;
 1291:   }
 1292: }
 1293: 
 1294: 
 1295: void dns_ack(void)
 1296: {
 1297:   int r,i;
 1298: 
 1299:   r = recvfrom(resfd,(byte *)resrecvbuf,MaxPacketsize,0,
 1300:                from, &fromlen);
 1301:   if (r > 0) {
 1302:     /* Check to see if this server is actually one we sent to */
 1303:     if ( addrcmp( (void *) &(from4->sin_addr), (void *) &localhost,
 1304:                   (int) AF_INET ) == 0 ) {
 1305:       for (i = 0;i < myres.nscount;i++)
 1306: 	if ( addrcmp( (void *) &(myres.nsaddr_list[i].sin_addr),
 1307: 		      (void *) &(from4->sin_addr), (int) AF_INET ) == 0 ||
 1308: 	     addrcmp( (void *) &(myres.nsaddr_list[i].sin_addr),
 1309: 		      (void *) &unspec_addr, (int) AF_INET ) == 0 )	/* 0.0.0.0 replies as 127.0.0.1 */
 1310: 	  break;
 1311:     } else
 1312:       for (i = 0;i < myres.nscount;i++)
 1313: 	if ( addrcmp( (void *) &(myres.nsaddr_list[i].sin_addr),
 1314: 		      (void *) &(from4->sin_addr), AF_INET ) == 0 )
 1315: 	  break;
 1316:     if (i == myres.nscount) {
 1317:       snprintf(tempstring, sizeof(tempstring), "Resolver error: Received reply from unknown source: %s",
 1318: 	      inet_ntoa(from4->sin_addr ));
 1319:       restell(tempstring);
 1320:     } else
 1321:       parserespacket((byte *)resrecvbuf,r);
 1322:   } else {
 1323:     snprintf(tempstring, sizeof(tempstring), "Resolver: Socket error: %s",strerror(errno));
 1324:     restell(tempstring);
 1325:   }
 1326: }
 1327: #ifdef ENABLE_IPV6
 1328: void dns_ack6(void)
 1329: {
 1330:   int r,i;
 1331:   static char addrstr[INET6_ADDRSTRLEN];
 1332: 
 1333:   // Probably not necessary. -- REW
 1334:   if (resfd6 < 0) return; 
 1335: 
 1336:   r = recvfrom(resfd6,(byte *)resrecvbuf,MaxPacketsize,0,
 1337:                from, &fromlen);
 1338:   if (r > 0) {
 1339:     /* Check to see if this server is actually one we sent to */
 1340:     if ( addrcmp( (void *) &(from6->sin6_addr), (void *) &localhost6,
 1341:                   (int) AF_INET6 ) == 0 ) {
 1342:       for (i = 0;i < myres.nscount;i++) {
 1343:         if (!NSSOCKADDR6(i))
 1344:           continue;
 1345: 
 1346: 	if ( addrcmp( (void *) &(NSSOCKADDR6(i)->sin6_addr),
 1347: 		      (void *) &(from6->sin6_addr), (int) AF_INET6 ) == 0 ||
 1348: 	     addrcmp( (void *) &(NSSOCKADDR6(i)->sin6_addr),
 1349: 		      (void *) &unspec_addr, (int) AF_INET6 ) == 0 )	/* 0.0.0.0 replies as 127.0.0.1 */
 1350: 	  break;
 1351:       }
 1352:     } else
 1353:       for (i = 0;i < myres.nscount;i++) {
 1354:         if (!NSSOCKADDR6(i))
 1355:           continue;
 1356: 	if ( addrcmp( (void *) &(NSSOCKADDR6(i)->sin6_addr),
 1357: 		      (void *) &(from6->sin6_addr), AF_INET6 ) == 0 )
 1358: 	  break;
 1359:       }
 1360:     if (i == myres.nscount) {
 1361:       snprintf(tempstring, sizeof(tempstring), 
 1362: 	       "Resolver error: Received reply from unknown source: %s",
 1363: 	       inet_ntop( AF_INET6, &(from6->sin6_addr), addrstr,
 1364: 			  sizeof addrstr ));
 1365:       restell(tempstring);
 1366:     } else
 1367:       parserespacket((byte *)resrecvbuf,r);
 1368:   } else {
 1369:     snprintf(tempstring, sizeof(tempstring), "Resolver: Socket error: %s",strerror(errno));
 1370:     restell(tempstring);
 1371:   }
 1372: }
 1373: #endif
 1374: 
 1375: 
 1376: int istime(double x,double *sinterval)
 1377: {
 1378:   if (x) {
 1379:     if (x > sweeptime) {
 1380:       if (*sinterval > x - sweeptime)
 1381: 	*sinterval = x - sweeptime;
 1382:     } else
 1383:       return 1;
 1384:   }
 1385:   return 0;
 1386: }
 1387: 
 1388: 
 1389: void dns_events(double *sinterval)
 1390: {
 1391:   struct resolve *rp,*nextrp;
 1392: 
 1393:   for (rp = expireresolves;(rp) && (sweeptime >= rp->expiretime);rp = nextrp) {
 1394:     nextrp = rp->next;
 1395:     switch (rp->state) {
 1396:     case STATE_FINISHED:	/* TTL has expired */
 1397:     case STATE_FAILED:	/* Fake TTL has expired */
 1398:       if (debug) {
 1399: 	snprintf(tempstring, sizeof(tempstring), "Resolver: Cache record for \"%s\" (%s) has expired. (state: %u)  Marked for expire at: %g, time: %g.",
 1400:                 nonull(rp->hostname), strlongip( &(rp->ip) ), 
 1401: 		rp->state, rp->expiretime, sweeptime);
 1402: 	restell(tempstring);
 1403:       }
 1404:       unlinkresolve(rp);
 1405:       break;
 1406:     case STATE_PTRREQ1:	/* First T_PTR send timed out */
 1407:       resendrequest(rp,T_PTR);
 1408:       restell("Resolver: Send #2 for \"PTR\" query...");
 1409:       rp->state++;
 1410:       rp->expiretime = sweeptime + ResRetryDelay2;
 1411:       (void)istime(rp->expiretime,sinterval);
 1412:       res_resend++;
 1413:       break;
 1414:     case STATE_PTRREQ2:	/* Second T_PTR send timed out */
 1415:       resendrequest(rp,T_PTR);
 1416:       restell("Resolver: Send #3 for \"PTR\" query...");
 1417:       rp->state++;
 1418:       rp->expiretime = sweeptime + ResRetryDelay3;
 1419:       (void)istime(rp->expiretime,sinterval);
 1420:       res_resend++;
 1421:       break;
 1422:     case STATE_PTRREQ3:	/* Third T_PTR timed out */
 1423:       restell("Resolver: \"PTR\" query timed out.");
 1424:       failrp(rp);
 1425:       (void)istime(rp->expiretime,sinterval);
 1426:       res_timeout++;
 1427:       break;
 1428:     }
 1429:   }
 1430:   if (expireresolves)
 1431:     (void)istime(expireresolves->expiretime,sinterval);
 1432: }
 1433: 
 1434: 
 1435: char *dns_lookup2(ip_t * ip)
 1436: {
 1437:   struct resolve *rp;
 1438: 
 1439:   if ((rp = findip(ip))) {
 1440:     if ((rp->state == STATE_FINISHED) || (rp->state == STATE_FAILED)) {
 1441:       if ((rp->state == STATE_FINISHED) && (rp->hostname)) {
 1442: 	if (debug) {
 1443: 	  snprintf(tempstring, sizeof(tempstring), "Resolver: Used cached record: %s == \"%s\".\n",
 1444: 		  strlongip(ip),rp->hostname);
 1445: 	  restell(tempstring);
 1446: 	}
 1447: 	return rp->hostname;
 1448:       } else {
 1449: 	if (debug) {
 1450: 	  snprintf(tempstring, sizeof(tempstring), "Resolver: Used failed record: %s == ???\n",
 1451: 		  strlongip(ip));
 1452: 	  restell(tempstring);
 1453: 	}
 1454: 	return NULL;
 1455:       }
 1456:     }
 1457:     return NULL;
 1458:   }
 1459:   if (debug)
 1460:     fprintf(stderr,"Resolver: Added to new record.\n");
 1461:   rp = allocresolve();
 1462:   rp->state = STATE_PTRREQ1;
 1463:   rp->expiretime = sweeptime + ResRetryDelay1;
 1464:   addrcpy( (void *) &(rp->ip), (void *) ip, af );
 1465:   linkresolve(rp);
 1466:   addrcpy( (void *) &(rp->ip), (void *) ip, af );
 1467:   linkresolveip(rp);
 1468:   sendrequest(rp,T_PTR);
 1469:   return NULL;
 1470: }
 1471: 
 1472: 
 1473: char *dns_lookup(ip_t * ip)
 1474: {
 1475:   char *t;
 1476: 
 1477:   if (!dns) return NULL;
 1478:   t = dns_lookup2(ip);
 1479:   return (t && use_dns) ? t : NULL;
 1480: }
 1481: 
 1482: #ifdef ENABLE_IPV6
 1483: /* Returns an ip6.arpa character string. */
 1484: void addr2ip6arpa( ip_t * ip, char * buf ) {
 1485:   unsigned char * p = (unsigned char *) ip;
 1486:   char * b = buf;
 1487:   int i;
 1488: 
 1489:   for ( i = sizeof (struct in6_addr) - 1; i >= 0; i-- ) {
 1490:         sprintf( b, "%x.%x.", p[i] % 16, p[i] >> 4 );
 1491:         b += 4;
 1492:   }
 1493:   sprintf( b, "ip6.arpa" );
 1494:   return;
 1495: }
 1496: #endif
 1497: 
 1498: /* Resolve an IP address to a hostname. */ 
 1499: struct hostent *addr2host( const char *addr, int af ) {
 1500:   int len = 0;
 1501:   switch ( af ) {
 1502:   case AF_INET:
 1503:     len = sizeof( struct in_addr );
 1504:     break;
 1505: #ifdef ENABLE_IPV6
 1506:   case AF_INET6:
 1507:     len = sizeof( struct in6_addr );
 1508:     break;
 1509: #endif
 1510:   }
 1511:   return gethostbyaddr( addr, len, af );
 1512: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>