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

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

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