#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <errno.h>
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 resolve * | allocresolve () |
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 resolve * | findid (u_16bit_t id) |
static struct resolve * | findhost (char *hostn) |
static struct resolve * | findip (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 resolve * | idbash [8192] |
static struct resolve * | ipbash [8192] |
static struct resolve * | hostbash [8192] |
static struct resolve * | expireresolves = 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 BASH_MODULO | ( | x | ) | ((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_opcode | ( | x | ) | ((x->databyte_a >> 3) & 15) |
Definition at line 145 of file coredns.c.
Referenced by parserespacket().
#define getheader_qr | ( | x | ) | (x->databyte_a >> 7) |
Definition at line 146 of file coredns.c.
Referenced by parserespacket().
#define getheader_rcode | ( | x | ) | (x->databyte_b & 15) |
Definition at line 147 of file coredns.c.
Referenced by parserespacket().
#define getheader_tc | ( | x | ) | ((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_PACKETSIZE (PACKETSZ) |
Definition at line 55 of file coredns.c.
Referenced by dns_ack(), and dorequest().
#define nonull | ( | s | ) | (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: " |
Definition at line 52 of file coredns.c.
Referenced by dns_ack(), dns_check_expires(), dns_forward(), dns_lookup(), failrp(), parserespacket(), passrp(), and resendrequest().
#define RES_WRN "DNS Resolver warning: " |
Definition at line 53 of file coredns.c.
Referenced by dns_check_expires(), and parserespacket().
#define sucknetdword | ( | x | ) |
#define sucknetlong | ( | x | ) |
((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 | ) | ((x)+=2,((short) (((x)[-2] << 8) | ((x)[-1] << 0)))) |
#define sucknetword | ( | x | ) | ((x)+=2,((u_16bit_t) (((x)[-2] << 8) | ((x)[-1] << 0)))) |
Definition at line 151 of file coredns.c.
Referenced by parserespacket().
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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().
long idseed = 0xdeadbeef [static] |
Definition at line 168 of file coredns.c.
Referenced by sendrequest().
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] |
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] |
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().