Annotation of embedaddon/mtr/dns.c, revision 1.1.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>