src/mod/dns.mod/coredns.c File Reference

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <errno.h>
Include dependency graph for coredns.c:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  packetheader

Defines

#define BASH_SIZE   8192
#define HOSTNAMELEN   255
#define RES_ERR   "DNS Resolver error: "
#define RES_MSG   "DNS Resolver: "
#define RES_WRN   "DNS Resolver warning: "
#define MAX_PACKETSIZE   (PACKETSZ)
#define MAX_DOMAINLEN   (MAXDNAME)
#define nonull(s)   (s) ? s : nullstring
#define BASH_MODULO(x)   ((x) & 8191)
#define HFIXEDSZ   (sizeof(packetheader))
#define getheader_rd(x)   (x->databyte_a & 1)
#define getheader_tc(x)   ((x->databyte_a >> 1) & 1)
#define getheader_aa(x)   ((x->databyte_a >> 2) & 1)
#define getheader_opcode(x)   ((x->databyte_a >> 3) & 15)
#define getheader_qr(x)   (x->databyte_a >> 7)
#define getheader_rcode(x)   (x->databyte_b & 15)
#define getheader_pr(x)   ((x->databyte_b >> 6) & 1)
#define getheader_ra(x)   (x->databyte_b >> 7)
#define sucknetword(x)   ((x)+=2,((u_16bit_t) (((x)[-2] << 8) | ((x)[-1] << 0))))
#define sucknetshort(x)   ((x)+=2,((short) (((x)[-2] << 8) | ((x)[-1] << 0))))
#define sucknetdword(x)
#define sucknetlong(x)

Functions

static struct resolveallocresolve ()
static u_32bit_t getidbash (u_16bit_t id)
static u_32bit_t getipbash (IP ip)
static u_32bit_t gethostbash (char *host)
static void linkresolveid (struct resolve *addrp)
static void unlinkresolveid (struct resolve *rp)
static void linkresolvehost (struct resolve *addrp)
static void unlinkresolvehost (struct resolve *rp)
static void linkresolveip (struct resolve *addrp)
static void unlinkresolveip (struct resolve *rp)
static void linkresolve (struct resolve *rp)
static void untieresolve (struct resolve *rp)
static void unlinkresolve (struct resolve *rp)
static struct resolvefindid (u_16bit_t id)
static struct resolvefindhost (char *hostn)
static struct resolvefindip (IP ip)
static void dorequest (char *s, int type, u_16bit_t id)
static void resendrequest (struct resolve *rp, int type)
static void sendrequest (struct resolve *rp, int type)
static void failrp (struct resolve *rp, int type)
static void passrp (struct resolve *rp, long ttl, int type)
static void parserespacket (u_8bit_t *s, int l)
static void dns_ack (void)
static void dns_check_expires (void)
static void dns_lookup (IP ip)
static void dns_forward (char *hostn)
static int init_dns_network (void)
static int init_dns_core (void)

Variables

static u_32bit_t resrecvbuf [((PACKETSZ)+7) >> 2]
static struct resolveidbash [8192]
static struct resolveipbash [8192]
static struct resolvehostbash [8192]
static struct resolveexpireresolves = 0
static IP localhost
static long idseed = 0xdeadbeef
static long aseed
static int resfd
static char tempstring [512]
static char namestring [1024+1]
static char stackstring [1024+1]
static const char nullstring [] = ""

Define Documentation

#define BASH_MODULO (  )     ((x) & 8191)

Definition at line 61 of file coredns.c.

Referenced by gethostbash(), getidbash(), and getipbash().

#define BASH_SIZE   8192

Definition at line 48 of file coredns.c.

Referenced by init_dns_core().

#define getheader_aa (  )     ((x->databyte_a >> 2) & 1)

Definition at line 144 of file coredns.c.

#define getheader_opcode (  )     ((x->databyte_a >> 3) & 15)

Definition at line 145 of file coredns.c.

Referenced by parserespacket().

#define getheader_pr (  )     ((x->databyte_b >> 6) & 1)

Definition at line 148 of file coredns.c.

#define getheader_qr (  )     (x->databyte_a >> 7)

Definition at line 146 of file coredns.c.

Referenced by parserespacket().

#define getheader_ra (  )     (x->databyte_b >> 7)

Definition at line 149 of file coredns.c.

#define getheader_rcode (  )     (x->databyte_b & 15)

Definition at line 147 of file coredns.c.

Referenced by parserespacket().

#define getheader_rd (  )     (x->databyte_a & 1)

Definition at line 142 of file coredns.c.

#define getheader_tc (  )     ((x->databyte_a >> 1) & 1)

Definition at line 143 of file coredns.c.

Referenced by parserespacket().

#define HFIXEDSZ   (sizeof(packetheader))

Definition at line 136 of file coredns.c.

Referenced by parserespacket().

#define HOSTNAMELEN   255

Definition at line 49 of file coredns.c.

Referenced by parserespacket().

#define MAX_DOMAINLEN   (MAXDNAME)

Definition at line 56 of file coredns.c.

#define MAX_PACKETSIZE   (PACKETSZ)

Definition at line 55 of file coredns.c.

Referenced by dns_ack(), and dorequest().

#define nonull (  )     (s) ? s : nullstring

Definition at line 60 of file coredns.c.

Referenced by dns_check_expires(), and dns_event_failure().

#define RES_ERR   "DNS Resolver error: "

Definition at line 51 of file coredns.c.

Referenced by dns_ack(), dorequest(), and parserespacket().

#define RES_MSG   "DNS Resolver: "
#define RES_WRN   "DNS Resolver warning: "

Definition at line 53 of file coredns.c.

Referenced by dns_check_expires(), and parserespacket().

#define sucknetdword (  ) 
Value:
((x)+=4,((dword) (((x)[-4] << 24) | ((x)[-3] << 16) | \
                                          ((x)[-2] <<  8) | ((x)[-1] <<  0))))

Definition at line 153 of file coredns.c.

#define sucknetlong (  ) 
Value:
((x)+=4,((long)  (((x)[-4] << 24) | ((x)[-3] << 16) | \
                                          ((x)[-2] <<  8) | ((x)[-1] <<  0))))

Definition at line 155 of file coredns.c.

Referenced by parserespacket().

#define sucknetshort (  )     ((x)+=2,((short) (((x)[-2] << 8) | ((x)[-1] << 0))))

Definition at line 152 of file coredns.c.

#define sucknetword (  )     ((x)+=2,((u_16bit_t) (((x)[-2] << 8) | ((x)[-1] << 0))))

Definition at line 151 of file coredns.c.

Referenced by parserespacket().


Function Documentation

static struct resolve* allocresolve (  )  [static, read]

Definition at line 222 of file coredns.c.

References egg_bzero, and nmalloc.

Referenced by dns_forward(), and dns_lookup().

00223 {
00224   struct resolve *rp;
00225 
00226   rp = nmalloc(sizeof *rp);
00227   egg_bzero(rp, sizeof(struct resolve));
00228   return rp;
00229 }

Here is the caller graph for this function:

static void dns_ack ( void   )  [static]

Definition at line 925 of file coredns.c.

References ddebug1, iptostr, localhost, MAX_PACKETSIZE, parserespacket(), RES_ERR, RES_MSG, resfd, and resrecvbuf.

Referenced by dns_socket().

00926 {
00927   struct sockaddr_in from;
00928   unsigned int fromlen = sizeof(struct sockaddr_in);
00929   int r, i;
00930 
00931   r = recvfrom(resfd, (u_8bit_t *) resrecvbuf, MAX_PACKETSIZE, 0,
00932                (struct sockaddr *) &from, &fromlen);
00933   if (r <= 0) {
00934     ddebug1(RES_MSG "Socket error: %s", strerror(errno));
00935     return;
00936   }
00937   /* Check to see if this server is actually one we sent to */
00938   if (from.sin_addr.s_addr == localhost) {
00939     for (i = 0; i < _res.nscount; i++)
00940       /* 0.0.0.0 replies as 127.0.0.1 */
00941       if ((_res.nsaddr_list[i].sin_addr.s_addr == from.sin_addr.s_addr) ||
00942           (!_res.nsaddr_list[i].sin_addr.s_addr))
00943         break;
00944   } else {
00945     for (i = 0; i < _res.nscount; i++)
00946       if (_res.nsaddr_list[i].sin_addr.s_addr == from.sin_addr.s_addr)
00947         break;
00948   }
00949   if (i == _res.nscount) {
00950     ddebug1(RES_ERR "Received reply from unknown source: %s",
00951             iptostr(from.sin_addr.s_addr));
00952   } else
00953     parserespacket((u_8bit_t *) resrecvbuf, r);
00954 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void dns_check_expires ( void   )  [static]

Definition at line 958 of file coredns.c.

References ddebug0, ddebug1, ddebug4, dns_maxsends, resolve::expiretime, failrp(), resolve::hostn, resolve::ip, iptostr, resolve::next, nonull, now, RES_MSG, RES_WRN, resendrequest(), resolve::sends, resolve::state, STATE_AREQ, STATE_FAILED, STATE_FINISHED, STATE_PTRREQ, unlinkresolve(), and untieresolve().

Referenced by dns_close(), and dns_start().

00959 {
00960   struct resolve *rp, *nextrp;
00961 
00962   /* Walk through sorted list ... */
00963   for (rp = expireresolves; (rp) && (now >= rp->expiretime); rp = nextrp) {
00964     nextrp = rp->next;
00965     untieresolve(rp);
00966     switch (rp->state) {
00967     case STATE_FINISHED:       /* TTL has expired */
00968     case STATE_FAILED:         /* Fake TTL has expired */
00969       ddebug4(RES_MSG
00970               "Cache record for \"%s\" (%s) has expired. (state: %u)  Marked for expire at: %ld.",
00971               nonull(rp->hostn), iptostr(rp->ip), rp->state, rp->expiretime);
00972       unlinkresolve(rp);
00973       break;
00974     case STATE_PTRREQ:         /* T_PTR send timed out */
00975       if (rp->sends <= dns_maxsends) {
00976         ddebug1(RES_MSG "Resend #%d for \"PTR\" query...", rp->sends - 1);
00977         resendrequest(rp, T_PTR);
00978       } else {
00979         ddebug0(RES_MSG "\"PTR\" query timed out.");
00980         failrp(rp, T_PTR);
00981       }
00982       break;
00983     case STATE_AREQ:           /* T_A send timed out */
00984       if (rp->sends <= dns_maxsends) {
00985         ddebug1(RES_MSG "Resend #%d for \"A\" query...", rp->sends - 1);
00986         resendrequest(rp, T_A);
00987       } else {
00988         ddebug0(RES_MSG "\"A\" query timed out.");
00989         failrp(rp, T_A);
00990       }
00991       break;
00992     default:                   /* Unknown state, let it expire */
00993       ddebug1(RES_WRN "Unknown request state %d. Request expired.", rp->state);
00994       failrp(rp, 0);
00995     }
00996   }
00997 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void dns_forward ( char *  hostn  )  [static]

Definition at line 1031 of file coredns.c.

References allocresolve(), call_ipbyhost, ddebug0, ddebug1, ddebug2, dns_event_failure(), dns_event_success(), egg_inet_aton, findhost(), resolve::hostn, resolve::ip, iptostr, linkresolvehost(), nmalloc, RES_MSG, sendrequest(), resolve::sends, resolve::state, STATE_AREQ, STATE_FAILED, and STATE_FINISHED.

Referenced by dns_close(), and dns_start().

01032 {
01033   struct resolve *rp;
01034   struct in_addr inaddr;
01035 
01036   /* Check if someone passed us an IP address as hostname
01037    * and return it straight away.
01038    */
01039   if (egg_inet_aton(hostn, &inaddr)) {
01040     call_ipbyhost(hostn, ntohl(inaddr.s_addr), 1);
01041     return;
01042   }
01043   if ((rp = findhost(hostn))) {
01044     if (rp->state == STATE_FINISHED || rp->state == STATE_FAILED) {
01045       if (rp->state == STATE_FINISHED && rp->ip) {
01046         ddebug2(RES_MSG "Used cached record: %s == \"%s\".", hostn,
01047                 iptostr(rp->ip));
01048         dns_event_success(rp, T_A);
01049       } else {
01050         ddebug1(RES_MSG "Used failed record: %s == ???", hostn);
01051         dns_event_failure(rp, T_A);
01052       }
01053     }
01054     return;
01055   }
01056   ddebug0(RES_MSG "Creating new record");
01057   rp = allocresolve();
01058   rp->state = STATE_AREQ;
01059   rp->sends = 1;
01060   rp->hostn = nmalloc(strlen(hostn) + 1);
01061   strcpy(rp->hostn, hostn);
01062   linkresolvehost(rp);
01063   sendrequest(rp, T_A);
01064 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void dns_lookup ( IP  ip  )  [static]

Definition at line 1001 of file coredns.c.

References allocresolve(), ddebug0, ddebug1, ddebug2, dns_event_failure(), dns_event_success(), findip(), resolve::hostn, resolve::ip, iptostr, linkresolveip(), RES_MSG, sendrequest(), resolve::sends, resolve::state, STATE_FAILED, STATE_FINISHED, and STATE_PTRREQ.

Referenced by dns_close(), and dns_start().

01002 {
01003   struct resolve *rp;
01004 
01005   ip = htonl(ip);
01006   if ((rp = findip(ip))) {
01007     if (rp->state == STATE_FINISHED || rp->state == STATE_FAILED) {
01008       if (rp->state == STATE_FINISHED && rp->hostn) {
01009         ddebug2(RES_MSG "Used cached record: %s == \"%s\".",
01010                 iptostr(ip), rp->hostn);
01011         dns_event_success(rp, T_PTR);
01012       } else {
01013         ddebug1(RES_MSG "Used failed record: %s == ???", iptostr(ip));
01014         dns_event_failure(rp, T_PTR);
01015       }
01016     }
01017     return;
01018   }
01019 
01020   ddebug0(RES_MSG "Creating new record");
01021   rp = allocresolve();
01022   rp->state = STATE_PTRREQ;
01023   rp->sends = 1;
01024   rp->ip = ip;
01025   linkresolveip(rp);
01026   sendrequest(rp, T_PTR);
01027 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void dorequest ( char *  s,
int  type,
u_16bit_t  id 
) [static]

Definition at line 561 of file coredns.c.

References ddebug0, packetheader::id, MAX_PACKETSIZE, nfree, nmalloc, NULL, RES_ERR, and resfd.

Referenced by resendrequest().

00562 {
00563   packetheader *hp;
00564   int r, i;
00565   u_8bit_t *buf;
00566 
00567   /* Use malloc here instead of a static buffer, as per res_mkquery()'s manual
00568    * buf should be aligned on an eight byte boundary. malloc() should return a
00569    * pointer to an address properly aligned for any data type. Failing to
00570    * provide a aligned buffer will result in a SIGBUS crash atleast on SPARC
00571    * CPUs.
00572    */
00573   buf = nmalloc(MAX_PACKETSIZE + 1);
00574   r = res_mkquery(QUERY, s, C_IN, type, NULL, 0, NULL, buf, MAX_PACKETSIZE);
00575   if (r == -1) {
00576     ddebug0(RES_ERR "Query too large.");
00577     return;
00578   }
00579   hp = (packetheader *) buf;
00580   hp->id = id;                  /* htons() deliberately left out (redundant) */
00581   for (i = 0; i < _res.nscount; i++)
00582     (void) sendto(resfd, buf, r, 0,
00583                   (struct sockaddr *) &_res.nsaddr_list[i],
00584                   sizeof(struct sockaddr));
00585   nfree(buf);
00586 }

Here is the caller graph for this function:

static void failrp ( struct resolve rp,
int  type 
) [static]

Definition at line 629 of file coredns.c.

References ddebug0, dns_event_failure(), dns_negcache, resolve::expiretime, linkresolve(), now, RES_MSG, resolve::state, STATE_FAILED, STATE_FINISHED, and untieresolve().

Referenced by dns_check_expires(), and parserespacket().

00630 {
00631   if (rp->state == STATE_FINISHED)
00632     return;
00633   rp->expiretime = now + dns_negcache;
00634   rp->state = STATE_FAILED;
00635 
00636   /* Expire time was changed, reinsert entry to maintain order */
00637   untieresolve(rp);
00638   linkresolve(rp);
00639 
00640   ddebug0(RES_MSG "Lookup failed.");
00641   dns_event_failure(rp, type);
00642 }

Here is the call graph for this function:

Here is the caller graph for this function:

static struct resolve* findhost ( char *  hostn  )  [static, read]

Definition at line 507 of file coredns.c.

References egg_strcasecmp, gethostbash(), resolve::hostn, resolve::nexthost, NULL, and resolve::previoushost.

Referenced by dns_forward().

00508 {
00509   struct resolve *rp;
00510   int bashnum;
00511 
00512   bashnum = gethostbash(hostn);
00513   rp = hostbash[bashnum];
00514   if (rp) {
00515     while ((rp->nexthost) &&
00516           (egg_strcasecmp(hostn, rp->nexthost->hostn) >= 0))
00517       rp = rp->nexthost;
00518     while ((rp->previoushost) &&
00519            (egg_strcasecmp(hostn, rp->previoushost->hostn) <= 0))
00520       rp = rp->previoushost;
00521     if (egg_strcasecmp(hostn, rp->hostn))
00522       return NULL;
00523     else {
00524       hostbash[bashnum] = rp;
00525       return rp;
00526     }
00527   }
00528   return rp;                    /* NULL */
00529 }

Here is the call graph for this function:

Here is the caller graph for this function:

static struct resolve* findid ( u_16bit_t  id  )  [static, read]

Definition at line 484 of file coredns.c.

References getidbash(), resolve::id, resolve::nextid, NULL, and resolve::previousid.

Referenced by parserespacket(), and sendrequest().

00485 {
00486   struct resolve *rp;
00487   int bashnum;
00488 
00489   bashnum = getidbash(id);
00490   rp = idbash[bashnum];
00491   if (rp) {
00492     while ((rp->nextid) && (id >= rp->nextid->id))
00493       rp = rp->nextid;
00494     while ((rp->previousid) && (id <= rp->previousid->id))
00495       rp = rp->previousid;
00496     if (id == rp->id) {
00497       idbash[bashnum] = rp;
00498       return rp;
00499     } else
00500       return NULL;
00501   }
00502   return rp;                    /* NULL */
00503 }

Here is the call graph for this function:

Here is the caller graph for this function:

static struct resolve* findip ( IP  ip  )  [static, read]

Definition at line 533 of file coredns.c.

References getipbash(), resolve::ip, resolve::nextip, NULL, and resolve::previousip.

Referenced by dns_lookup().

00534 {
00535   struct resolve *rp;
00536   u_32bit_t bashnum;
00537 
00538   bashnum = getipbash(ip);
00539   rp = ipbash[bashnum];
00540   if (rp) {
00541     while ((rp->nextip) && (ip >= rp->nextip->ip))
00542       rp = rp->nextip;
00543     while ((rp->previousip) && (ip <= rp->previousip->ip))
00544       rp = rp->previousip;
00545     if (ip == rp->ip) {
00546       ipbash[bashnum] = rp;
00547       return rp;
00548     } else
00549       return NULL;
00550   }
00551   return rp;                    /* NULL */
00552 }

Here is the call graph for this function:

Here is the caller graph for this function:

static u_32bit_t gethostbash ( char *  host  )  [static]

Definition at line 252 of file coredns.c.

References BASH_MODULO.

Referenced by findhost(), linkresolvehost(), and unlinkresolvehost().

00253 {
00254   u_32bit_t bashvalue = 0;
00255 
00256   for (; *host; host++) {
00257     bashvalue ^= *host;
00258     bashvalue += (*host >> 1) + (bashvalue >> 1);
00259   }
00260   return BASH_MODULO(bashvalue);
00261 }

Here is the caller graph for this function:

static u_32bit_t getidbash ( u_16bit_t  id  )  [inline, static]

Definition at line 238 of file coredns.c.

References BASH_MODULO.

Referenced by findid(), linkresolveid(), and unlinkresolveid().

00239 {
00240   return (u_32bit_t) BASH_MODULO(id);
00241 }

Here is the caller graph for this function:

static u_32bit_t getipbash ( IP  ip  )  [inline, static]

Definition at line 245 of file coredns.c.

References BASH_MODULO.

Referenced by findip(), linkresolveip(), and unlinkresolveip().

00246 {
00247   return (u_32bit_t) BASH_MODULO(ip);
00248 }

Here is the caller graph for this function:

static int init_dns_core ( void   )  [static]

Definition at line 1103 of file coredns.c.

References aseed, BASH_SIZE, init_dns_network(), LOG_MISC, NULL, and putlog.

Referenced by dns_start().

01104 {
01105   int i;
01106 
01107   /* Initialise the resolv library. */
01108   res_init();
01109   if (!_res.nscount)
01110     putlog(LOG_MISC, "*", "No nameservers found.");
01111   _res.options |= RES_RECURSE | RES_DEFNAMES | RES_DNSRCH;
01112   for (i = 0; i < _res.nscount; i++)
01113     _res.nsaddr_list[i].sin_family = AF_INET;
01114 
01115   if (!init_dns_network())
01116     return 0;
01117 
01118   /* Initialise the hash tables. */
01119   aseed = time(NULL) ^ (time(NULL) << 3) ^ (u_32bit_t) getpid();
01120   for (i = 0; i < BASH_SIZE; i++) {
01121     idbash[i] = NULL;
01122     ipbash[i] = NULL;
01123     hostbash[i] = NULL;
01124   }
01125   expireresolves = NULL;
01126   return 1;
01127 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int init_dns_network ( void   )  [static]

Definition at line 1068 of file coredns.c.

References allocsock, egg_inet_aton, killsock, localhost, LOG_MISC, putlog, resfd, and SOCK_PASS.

Referenced by eof_dns_socket(), and init_dns_core().

01069 {
01070   int option;
01071   struct in_addr inaddr;
01072 
01073   resfd = socket(AF_INET, SOCK_DGRAM, 0);
01074   if (resfd == -1) {
01075     putlog(LOG_MISC, "*",
01076            "Unable to allocate socket for nameserver communication: %s",
01077            strerror(errno));
01078     return 0;
01079   }
01080   if (allocsock(resfd, SOCK_PASS) == -1) {
01081     putlog(LOG_MISC, "*",
01082            "Unable to allocate socket in socklist for nameserver communication");
01083     killsock(resfd);
01084     return 0;
01085   }
01086   option = 1;
01087   if (setsockopt(resfd, SOL_SOCKET, SO_BROADCAST, (char *) &option,
01088                  sizeof(option))) {
01089     putlog(LOG_MISC, "*",
01090            "Unable to setsockopt() on nameserver communication socket: %s",
01091            strerror(errno));
01092     killsock(resfd);
01093     return 0;
01094   }
01095 
01096   egg_inet_aton("127.0.0.1", &inaddr);
01097   localhost = inaddr.s_addr;
01098   return 1;
01099 }

Here is the caller graph for this function:

static void linkresolve ( struct resolve rp  )  [static]

Definition at line 427 of file coredns.c.

References resolve::expiretime, irp, resolve::next, NULL, and resolve::previous.

Referenced by failrp(), passrp(), and resendrequest().

00428 {
00429   struct resolve *irp;
00430 
00431   if (expireresolves) {
00432     irp = expireresolves;
00433     while ((irp->next) && (rp->expiretime >= irp->expiretime))
00434       irp = irp->next;
00435     if (rp->expiretime >= irp->expiretime) {
00436       rp->next = NULL;
00437       rp->previous = irp;
00438       irp->next = rp;
00439     } else {
00440       rp->previous = irp->previous;
00441       rp->next = irp;
00442       if (irp->previous)
00443         irp->previous->next = rp;
00444       else
00445         expireresolves = rp;
00446       irp->previous = rp;
00447     }
00448   } else {
00449     rp->next = NULL;
00450     rp->previous = NULL;
00451     expireresolves = rp;
00452   }
00453 }

Here is the caller graph for this function:

static void linkresolvehost ( struct resolve addrp  )  [static]

Definition at line 317 of file coredns.c.

References egg_strcasecmp, gethostbash(), resolve::hostn, resolve::nexthost, NULL, and resolve::previoushost.

Referenced by dns_forward(), and parserespacket().

00318 {
00319   struct resolve *rp;
00320   u_32bit_t bashnum;
00321   int ret;
00322 
00323   bashnum = gethostbash(addrp->hostn);
00324   rp = hostbash[bashnum];
00325   if (rp) {
00326     while ((rp->nexthost) &&
00327            (egg_strcasecmp(addrp->hostn, rp->nexthost->hostn) < 0))
00328       rp = rp->nexthost;
00329     while ((rp->previoushost) &&
00330            (egg_strcasecmp(addrp->hostn, rp->previoushost->hostn) > 0))
00331       rp = rp->previoushost;
00332     ret = egg_strcasecmp(addrp->hostn, rp->hostn);
00333     if (ret < 0) {
00334       addrp->previoushost = rp;
00335       addrp->nexthost = rp->nexthost;
00336       if (rp->nexthost)
00337         rp->nexthost->previoushost = addrp;
00338       rp->nexthost = addrp;
00339     } else if (ret > 0) {
00340       addrp->previoushost = rp->previoushost;
00341       addrp->nexthost = rp;
00342       if (rp->previoushost)
00343         rp->previoushost->nexthost = addrp;
00344       rp->previoushost = addrp;
00345     } else                        /* Trying to add the same host! */
00346       return;
00347   } else
00348     addrp->nexthost = addrp->previoushost = NULL;
00349   hostbash[bashnum] = addrp;
00350 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void linkresolveid ( struct resolve addrp  )  [static]

Definition at line 265 of file coredns.c.

References getidbash(), resolve::id, resolve::nextid, NULL, and resolve::previousid.

Referenced by sendrequest().

00266 {
00267   struct resolve *rp;
00268   u_32bit_t bashnum;
00269 
00270   bashnum = getidbash(addrp->id);
00271   rp = idbash[bashnum];
00272   if (rp) {
00273     while ((rp->nextid) && (addrp->id > rp->nextid->id))
00274       rp = rp->nextid;
00275     while ((rp->previousid) && (addrp->id < rp->previousid->id))
00276       rp = rp->previousid;
00277     if (rp->id < addrp->id) {
00278       addrp->previousid = rp;
00279       addrp->nextid = rp->nextid;
00280       if (rp->nextid)
00281         rp->nextid->previousid = addrp;
00282       rp->nextid = addrp;
00283     } else if (rp->id > addrp->id) {
00284       addrp->previousid = rp->previousid;
00285       addrp->nextid = rp;
00286       if (rp->previousid)
00287         rp->previousid->nextid = addrp;
00288       rp->previousid = addrp;
00289     } else                        /* Trying to add the same id! */
00290       return;
00291   } else
00292     addrp->nextid = addrp->previousid = NULL;
00293   idbash[bashnum] = addrp;
00294 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void linkresolveip ( struct resolve addrp  )  [static]

Definition at line 374 of file coredns.c.

References getipbash(), resolve::ip, resolve::nextip, NULL, and resolve::previousip.

Referenced by dns_lookup(), and parserespacket().

00375 {
00376   struct resolve *rp;
00377   u_32bit_t bashnum;
00378 
00379   bashnum = getipbash(addrp->ip);
00380   rp = ipbash[bashnum];
00381   if (rp) {
00382     while ((rp->nextip) && (addrp->ip > rp->nextip->ip))
00383       rp = rp->nextip;
00384     while ((rp->previousip) && (addrp->ip < rp->previousip->ip))
00385       rp = rp->previousip;
00386     if (rp->ip < addrp->ip) {
00387       addrp->previousip = rp;
00388       addrp->nextip = rp->nextip;
00389       if (rp->nextip)
00390         rp->nextip->previousip = addrp;
00391       rp->nextip = addrp;
00392     } else if (rp->ip > addrp->ip) {
00393       addrp->previousip = rp->previousip;
00394       addrp->nextip = rp;
00395       if (rp->previousip)
00396         rp->previousip->nextip = addrp;
00397       rp->previousip = addrp;
00398     } else                        /* Trying to add the same ip! */
00399       return;
00400   } else
00401     addrp->nextip = addrp->previousip = NULL;
00402   ipbash[bashnum] = addrp;
00403 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void parserespacket ( u_8bit_t s,
int  l 
) [static]

Definition at line 667 of file coredns.c.

References packetheader::ancount, packetheader::arcount, ddebug0, ddebug1, ddebug2, ddebug4, debug0, egg_strcasecmp, failrp(), findid(), getheader_opcode, getheader_qr, getheader_rcode, getheader_tc, HFIXEDSZ, resolve::hostn, HOSTNAMELEN, packetheader::id, resolve::ip, IS_A, IS_PTR, linkresolvehost(), linkresolveip(), my_memcpy, namestring, nmalloc, packetheader::nscount, passrp(), packetheader::qdcount, RES_ERR, RES_MSG, RES_WRN, stackstring, resolve::state, STATE_AREQ, STATE_FAILED, STATE_FINISHED, STATE_PTRREQ, sucknetlong, and sucknetword.

Referenced by dns_ack().

00668 {
00669   struct resolve *rp;
00670   packetheader *hp;
00671   u_8bit_t *eob;
00672   u_8bit_t *c;
00673   long ttl;
00674   int r, usefulanswer;
00675   u_16bit_t rr, datatype, class, qdatatype, qclass;
00676   u_8bit_t rdatalength;
00677 
00678   if (l < sizeof(packetheader)) {
00679     debug0(RES_ERR "Packet smaller than standard header size.");
00680     return;
00681   }
00682   if (l == sizeof(packetheader)) {
00683     debug0(RES_ERR "Packet has empty body.");
00684     return;
00685   }
00686   hp = (packetheader *) s;
00687   /* Convert data to host byte order
00688    *
00689    * hp->id does not need to be redundantly byte-order flipped, it
00690    * is only echoed by nameserver
00691    */
00692   rp = findid(hp->id);
00693   if (!rp)
00694     return;
00695   if ((rp->state == STATE_FINISHED) || (rp->state == STATE_FAILED))
00696     return;
00697   hp->qdcount = ntohs(hp->qdcount);
00698   hp->ancount = ntohs(hp->ancount);
00699   hp->nscount = ntohs(hp->nscount);
00700   hp->arcount = ntohs(hp->arcount);
00701   if (getheader_tc(hp)) {       /* Packet truncated */
00702     ddebug0(RES_ERR "Nameserver packet truncated.");
00703     return;
00704   }
00705   if (!getheader_qr(hp)) {      /* Not a reply */
00706     ddebug0(RES_ERR "Query packet received on nameserver communication "
00707             "socket.");
00708     return;
00709   }
00710   if (getheader_opcode(hp)) {   /* Not opcode 0 (standard query) */
00711     ddebug0(RES_ERR "Invalid opcode in response packet.");
00712     return;
00713   }
00714   eob = s + l;
00715   c = s + HFIXEDSZ;
00716   switch (getheader_rcode(hp)) {
00717   case NOERROR:
00718     if (hp->ancount) {
00719       ddebug4(RES_MSG "Received nameserver reply. (qd:%u an:%u ns:%u ar:%u)",
00720               hp->qdcount, hp->ancount, hp->nscount, hp->arcount);
00721       if (hp->qdcount != 1) {
00722         ddebug0(RES_ERR "Reply does not contain one query.");
00723         return;
00724       }
00725       if (c > eob) {
00726         ddebug0(RES_ERR "Reply too short.");
00727         return;
00728       }
00729       switch (rp->state) {      /* Construct expected query reply */
00730       case STATE_PTRREQ:
00731         sprintf(stackstring,
00732                 "%u.%u.%u.%u.in-addr.arpa",
00733                 ((u_8bit_t *) & rp->ip)[3],
00734                 ((u_8bit_t *) & rp->ip)[2],
00735                 ((u_8bit_t *) & rp->ip)[1], ((u_8bit_t *) & rp->ip)[0]);
00736         break;
00737       case STATE_AREQ:
00738         strncpy(stackstring, rp->hostn, 1024);
00739       }
00740       *namestring = '\0';
00741       r = dn_expand(s, s + l, c, namestring, MAXDNAME);
00742       if (r == -1) {
00743         ddebug0(RES_ERR "dn_expand() failed while expanding query domain.");
00744         return;
00745       }
00746       namestring[strlen(stackstring)] = '\0';
00747       if (egg_strcasecmp(stackstring, namestring)) {
00748         ddebug2(RES_MSG "Unknown query packet dropped. (\"%s\" does not "
00749                 "match \"%s\")", stackstring, namestring);
00750         return;
00751       }
00752       ddebug1(RES_MSG "Queried domain name: \"%s\"", namestring);
00753       c += r;
00754       if (c + 4 > eob) {
00755         ddebug0(RES_ERR "Query resource record truncated.");
00756         return;
00757       }
00758       qdatatype = sucknetword(c);
00759       qclass = sucknetword(c);
00760       if (qclass != C_IN) {
00761         ddebug2(RES_ERR "Received unsupported query class: %u (%s)",
00762                 qclass, (qclass < CLASSTYPES_COUNT) ?
00763                 classtypes[qclass] : classtypes[CLASSTYPES_COUNT]);
00764       }
00765       switch (qdatatype) {
00766       case T_PTR:
00767         if (!IS_PTR(rp)) {
00768           ddebug0(RES_WRN "Ignoring response with unexpected query type "
00769                   "\"PTR\".");
00770           return;
00771         }
00772         break;
00773       case T_A:
00774         if (!IS_A(rp)) {
00775           ddebug0(RES_WRN "Ignoring response with unexpected query type "
00776                   "\"PTR\".");
00777           return;
00778         }
00779         break;
00780       default:
00781         ddebug2(RES_ERR "Received unimplemented query type: %u (%s)",
00782                 qdatatype, (qdatatype < RESOURCETYPES_COUNT) ?
00783                 resourcetypes[qdatatype] : resourcetypes[RESOURCETYPES_COUNT]);
00784       }
00785       for (rr = hp->ancount + hp->nscount + hp->arcount; rr; rr--) {
00786         if (c > eob) {
00787           ddebug0(RES_ERR "Packet does not contain all specified resouce "
00788                   "records.");
00789           return;
00790         }
00791         *namestring = '\0';
00792         r = dn_expand(s, s + l, c, namestring, MAXDNAME);
00793         if (r == -1) {
00794           ddebug0(RES_ERR "dn_expand() failed while expanding answer domain.");
00795           return;
00796         }
00797         namestring[strlen(stackstring)] = '\0';
00798         if (egg_strcasecmp(stackstring, namestring))
00799           usefulanswer = 0;
00800         else
00801           usefulanswer = 1;
00802         ddebug1(RES_MSG "answered domain query: \"%s\"", namestring);
00803         c += r;
00804         if (c + 10 > eob) {
00805           ddebug0(RES_ERR "Resource record truncated.");
00806           return;
00807         }
00808         datatype = sucknetword(c);
00809         class = sucknetword(c);
00810         ttl = sucknetlong(c);
00811         rdatalength = sucknetword(c);
00812         if (class != qclass) {
00813           ddebug2(RES_MSG "query class: %u (%s)",
00814                   qclass, (qclass < CLASSTYPES_COUNT) ?
00815                   classtypes[qclass] : classtypes[CLASSTYPES_COUNT]);
00816           ddebug2(RES_MSG "rr class: %u (%s)", class,
00817                   (class < CLASSTYPES_COUNT) ?
00818                   classtypes[class] : classtypes[CLASSTYPES_COUNT]);
00819           ddebug0(RES_ERR "Answered class does not match queried class.");
00820           return;
00821         }
00822         if (!rdatalength) {
00823           ddebug0(RES_ERR "Zero size rdata.");
00824           return;
00825         }
00826         if (c + rdatalength > eob) {
00827           ddebug0(RES_ERR "Specified rdata length exceeds packet size.");
00828           return;
00829         }
00830         if (datatype == qdatatype) {
00831           ddebug1(RES_MSG "TTL: %s", strtdiff(sendstring, ttl));
00832           ddebug1(RES_MSG "TYPE: %s", (datatype < RESOURCETYPES_COUNT) ?
00833                   resourcetypes[datatype] :
00834                   resourcetypes[RESOURCETYPES_COUNT]);
00835           if (usefulanswer)
00836             switch (datatype) {
00837             case T_A:
00838               if (rdatalength != 4) {
00839                 ddebug1(RES_ERR "Unsupported rdata format for \"A\" type. "
00840                         "(%u bytes)", rdatalength);
00841                 return;
00842               }
00843               my_memcpy(&rp->ip, (IP *) c, sizeof(IP));
00844               linkresolveip(rp);
00845               passrp(rp, ttl, T_A);
00846               return;
00847             case T_PTR:
00848               *namestring = '\0';
00849               r = dn_expand(s, s + l, c, namestring, MAXDNAME);
00850               if (r == -1) {
00851                 ddebug0(RES_ERR "dn_expand() failed while expanding domain in "
00852                         "rdata.");
00853                 return;
00854               }
00855               ddebug1(RES_MSG "Answered domain: \"%s\"", namestring);
00856               if (r > HOSTNAMELEN) {
00857                 ddebug0(RES_ERR "Domain name too long.");
00858                 failrp(rp, T_PTR);
00859                 return;
00860               }
00861               if (!rp->hostn) {
00862                 rp->hostn = nmalloc(strlen(namestring) + 1);
00863                 strcpy(rp->hostn, namestring);
00864                 linkresolvehost(rp);
00865                 passrp(rp, ttl, T_PTR);
00866                 return;
00867               }
00868               break;
00869             default:
00870               ddebug2(RES_ERR "Received unimplemented data type: %u (%s)",
00871                       datatype, (datatype < RESOURCETYPES_COUNT) ?
00872                       resourcetypes[datatype] :
00873                       resourcetypes[RESOURCETYPES_COUNT]);
00874             }
00875         } else if (datatype == T_CNAME) {
00876           *namestring = '\0';
00877           r = dn_expand(s, s + l, c, namestring, MAXDNAME);
00878           if (r == -1) {
00879             ddebug0(RES_ERR "dn_expand() failed while expanding domain in "
00880                     "rdata.");
00881             return;
00882           }
00883           ddebug1(RES_MSG "answered domain is CNAME for: %s", namestring);
00884           /* The next responses will be related to the domain
00885            * pointed to by CNAME, so we need to update which
00886            * respones we regard as important.
00887            */
00888           strncpy(stackstring, namestring, 1024);
00889         } else {
00890           ddebug2(RES_MSG "Ignoring resource type %u. (%s)",
00891                   datatype, (datatype < RESOURCETYPES_COUNT) ?
00892                   resourcetypes[datatype] :
00893                   resourcetypes[RESOURCETYPES_COUNT]);
00894         }
00895         c += rdatalength;
00896       }
00897     } else
00898       ddebug0(RES_ERR "No error returned but no answers given.");
00899     break;
00900   case NXDOMAIN:
00901     ddebug0(RES_MSG "Host not found.");
00902     switch (rp->state) {
00903     case STATE_PTRREQ:
00904       failrp(rp, T_PTR);
00905       break;
00906     case STATE_AREQ:
00907       failrp(rp, T_A);
00908       break;
00909     default:
00910       failrp(rp, 0);
00911       break;
00912     }
00913     break;
00914   default:
00915     ddebug2(RES_MSG "Received error response %u. (%s)",
00916             getheader_rcode(hp), (getheader_rcode(hp) < RESPONSECODES_COUNT) ?
00917             responsecodes[getheader_rcode(hp)] :
00918             responsecodes[RESPONSECODES_COUNT]);
00919   }
00920 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void passrp ( struct resolve rp,
long  ttl,
int  type 
) [static]

Definition at line 647 of file coredns.c.

References ddebug1, dns_cache, dns_event_success(), resolve::expiretime, resolve::hostn, linkresolve(), now, RES_MSG, resolve::state, STATE_FINISHED, time_t, and untieresolve().

Referenced by parserespacket().

00648 {
00649   rp->state = STATE_FINISHED;
00650 
00651   /* Do not cache entries for too long. */
00652   if (ttl < dns_cache)
00653     rp->expiretime = now + (time_t) ttl;
00654   else
00655     rp->expiretime = now + dns_cache;
00656 
00657   /* Expire time was changed, reinsert entry to maintain order */
00658   untieresolve(rp);
00659   linkresolve(rp);
00660 
00661   ddebug1(RES_MSG "Lookup successful: %s", rp->hostn);
00662   dns_event_success(rp, type);
00663 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void resendrequest ( struct resolve rp,
int  type 
) [static]

Definition at line 590 of file coredns.c.

References ddebug1, dns_retrydelay, dorequest(), resolve::expiretime, resolve::hostn, resolve::id, resolve::ip, iptostr, linkresolve(), now, RES_MSG, resolve::sends, and tempstring.

Referenced by dns_check_expires(), and sendrequest().

00591 {
00592   rp->sends++;
00593   /* Update expire time */
00594   rp->expiretime = now + (dns_retrydelay * rp->sends);
00595   /* Add (back) to expire list */
00596   linkresolve(rp);
00597 
00598   if (type == T_A) {
00599     dorequest(rp->hostn, type, rp->id);
00600     ddebug1(RES_MSG "Sent domain lookup request for \"%s\".", rp->hostn);
00601   } else if (type == T_PTR) {
00602     sprintf(tempstring, "%u.%u.%u.%u.in-addr.arpa",
00603             ((u_8bit_t *) & rp->ip)[3],
00604             ((u_8bit_t *) & rp->ip)[2],
00605             ((u_8bit_t *) & rp->ip)[1], ((u_8bit_t *) & rp->ip)[0]);
00606     dorequest(tempstring, type, rp->id);
00607     ddebug1(RES_MSG "Sent domain lookup request for \"%s\".", iptostr(rp->ip));
00608   }
00609 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void sendrequest ( struct resolve rp,
int  type 
) [static]

Definition at line 613 of file coredns.c.

References aseed, findid(), resolve::id, idseed, linkresolveid(), NULL, and resendrequest().

Referenced by dns_forward(), and dns_lookup().

00614 {
00615   /* Create unique id */
00616   do {
00617     idseed = (((idseed + idseed) | (long) time(NULL))
00618               + idseed - 0x54bad4a) ^ aseed;
00619     aseed ^= idseed;
00620     rp->id = (u_16bit_t) idseed;
00621   } while (findid(rp->id));
00622   linkresolveid(rp);            /* Add id to id hash table */
00623   resendrequest(rp, type);      /* Send request */
00624 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void unlinkresolve ( struct resolve rp  )  [static]

Definition at line 470 of file coredns.c.

References resolve::hostn, nfree, unlinkresolvehost(), unlinkresolveid(), unlinkresolveip(), and untieresolve().

Referenced by dns_check_expires().

00471 {
00472 
00473   untieresolve(rp);             /* Not really needed. Left in to be on the
00474                                  * safe side. */
00475   unlinkresolveid(rp);
00476   unlinkresolveip(rp);
00477   if (rp->hostn)
00478     unlinkresolvehost(rp);
00479   nfree(rp);
00480 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void unlinkresolvehost ( struct resolve rp  )  [static]

Definition at line 354 of file coredns.c.

References gethostbash(), resolve::hostn, resolve::nexthost, nfree, and resolve::previoushost.

Referenced by unlinkresolve().

00355 {
00356   u_32bit_t bashnum;
00357 
00358   bashnum = gethostbash(rp->hostn);
00359   if (hostbash[bashnum] == rp) {
00360     if (rp->previoushost)
00361       hostbash[bashnum] = rp->previoushost;
00362     else
00363       hostbash[bashnum] = rp->nexthost;
00364   }
00365   if (rp->nexthost)
00366     rp->nexthost->previoushost = rp->previoushost;
00367   if (rp->previoushost)
00368     rp->previoushost->nexthost = rp->nexthost;
00369   nfree(rp->hostn);
00370 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void unlinkresolveid ( struct resolve rp  )  [static]

Definition at line 298 of file coredns.c.

References getidbash(), resolve::id, resolve::nextid, and resolve::previousid.

Referenced by unlinkresolve().

00299 {
00300   u_32bit_t bashnum;
00301 
00302   bashnum = getidbash(rp->id);
00303   if (idbash[bashnum] == rp) {
00304     if (rp->previousid)
00305       idbash[bashnum] = rp->previousid;
00306     else
00307       idbash[bashnum] = rp->nextid;
00308   }
00309   if (rp->nextid)
00310     rp->nextid->previousid = rp->previousid;
00311   if (rp->previousid)
00312     rp->previousid->nextid = rp->nextid;
00313 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void unlinkresolveip ( struct resolve rp  )  [static]

Definition at line 407 of file coredns.c.

References getipbash(), resolve::ip, resolve::nextip, and resolve::previousip.

Referenced by unlinkresolve().

00408 {
00409   u_32bit_t bashnum;
00410 
00411   bashnum = getipbash(rp->ip);
00412   if (ipbash[bashnum] == rp) {
00413     if (rp->previousip)
00414       ipbash[bashnum] = rp->previousip;
00415     else
00416       ipbash[bashnum] = rp->nextip;
00417   }
00418   if (rp->nextip)
00419     rp->nextip->previousip = rp->previousip;
00420   if (rp->previousip)
00421     rp->previousip->nextip = rp->nextip;
00422 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void untieresolve ( struct resolve rp  )  [static]

Definition at line 457 of file coredns.c.

References resolve::next, and resolve::previous.

Referenced by dns_check_expires(), failrp(), passrp(), and unlinkresolve().

00458 {
00459   if (rp->previous)
00460     rp->previous->next = rp->next;
00461   else
00462     expireresolves = rp->next;
00463   if (rp->next)
00464     rp->next->previous = rp->previous;
00465 }

Here is the caller graph for this function:


Variable Documentation

long aseed [static]

Definition at line 169 of file coredns.c.

Referenced by init_dns_core(), and sendrequest().

struct resolve* expireresolves = 0 [static]

Definition at line 164 of file coredns.c.

Referenced by dns_cache_expmem(), and dns_free_cache().

struct resolve* hostbash[8192] [static]

Definition at line 163 of file coredns.c.

struct resolve* idbash[8192] [static]

Definition at line 161 of file coredns.c.

long idseed = 0xdeadbeef [static]

Definition at line 168 of file coredns.c.

Referenced by sendrequest().

struct resolve* ipbash[8192] [static]

Definition at line 162 of file coredns.c.

IP localhost [static]

Definition at line 166 of file coredns.c.

Referenced by dns_ack(), and init_dns_network().

char namestring[1024+1] [static]

Definition at line 174 of file coredns.c.

Referenced by parserespacket().

const char nullstring[] = "" [static]

Definition at line 181 of file coredns.c.

int resfd [static]

Definition at line 171 of file coredns.c.

Referenced by dns_ack(), dns_close(), dns_start(), dorequest(), eof_dns_socket(), and init_dns_network().

u_32bit_t resrecvbuf[((PACKETSZ)+7) >> 2] [static]

Definition at line 159 of file coredns.c.

Referenced by dns_ack().

char stackstring[1024+1] [static]

Definition at line 175 of file coredns.c.

Referenced by parserespacket().

char tempstring[512] [static]

Definition at line 173 of file coredns.c.

Referenced by resendrequest().


Generated on 7 Sep 2016 for Eggdrop by  doxygen 1.6.1