Annotation of embedaddon/mtr/dns.c, revision 1.1

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

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