coredns.c 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115
  1. /*
  2. * dnscore.c -- part of dns.mod
  3. * This file contains all core functions needed for the eggdrop dns module.
  4. * Many of them are only minimaly modified from the original source.
  5. *
  6. * Modified/written by Fabian Knittel <fknittel@gmx.de>
  7. *
  8. */
  9. /*
  10. * Borrowed from mtr -- a network diagnostic tool
  11. * Copyright (C) 1997,1998 Matt Kimball <mkimball@xmission.com>
  12. * Released under the GPL, as above.
  13. *
  14. * Non-blocking DNS portion --
  15. * Copyright (C) 1998 Simon Kirby <sim@neato.org>
  16. * Released under the GPL, as above.
  17. */
  18. #include "src/net.h"
  19. #include <sys/socket.h>
  20. #include <netinet/in.h>
  21. #include <arpa/inet.h>
  22. #include <arpa/nameser.h>
  23. #include <resolv.h>
  24. #include <errno.h>
  25. /* Defines */
  26. #define BASH_SIZE 8192 /* Size of hash tables */
  27. #define HOSTNAMELEN 255 /* From RFC */
  28. #define RES_RETRYDELAY 3
  29. #define RES_MAXSENDS 4
  30. #define RES_FAILEDDELAY 600 /* TTL for failed records (in
  31. seconds). */
  32. #define RES_MAX_TTL 86400 /* Maximum TTL (in seconds). */
  33. #define RES_ERR "DNS Resolver error: "
  34. #define RES_MSG "DNS Resolver: "
  35. #define RES_WRN "DNS Resolver warning: "
  36. #define MAX_PACKETSIZE (PACKETSZ)
  37. #define MAX_DOMAINLEN (MAXDNAME)
  38. /* Macros */
  39. #define nonull(s) (s) ? s : nullstring
  40. #define BASH_MODULO(x) ((x) & 8191) /* Modulo for hash table size */
  41. /* Non-blocking nameserver interface routines */
  42. #ifdef DEBUG_DNS
  43. # define RESPONSECODES_COUNT 6
  44. static char *responsecodes[RESPONSECODES_COUNT + 1] = {
  45. "no error",
  46. "format error in query",
  47. "server failure",
  48. "queried domain name does not exist",
  49. "requested query type not implemented",
  50. "refused by name server",
  51. "unknown error",
  52. };
  53. #endif /* DEBUG_DNS */
  54. #ifdef DEBUG_DNS
  55. # define RESOURCETYPES_COUNT 18
  56. static const char *resourcetypes[RESOURCETYPES_COUNT + 1] = {
  57. "unknown type",
  58. "A: host address",
  59. "AAAA: host address v6",
  60. "NS: authoritative name server",
  61. "MD: mail destination (OBSOLETE)",
  62. "MF: mail forwarder (OBSOLETE)",
  63. "CNAME: name alias",
  64. "SOA: authority record",
  65. "MB: mailbox domain name (EXPERIMENTAL)",
  66. "MG: mail group member (EXPERIMENTAL)",
  67. "MR: mail rename domain name (EXPERIMENTAL)",
  68. "NULL: NULL RR (EXPERIMENTAL)",
  69. "WKS: well known service description",
  70. "PTR: domain name pointer",
  71. "HINFO: host information",
  72. "MINFO: mailbox or mail list information",
  73. "MX: mail exchange",
  74. "TXT: text string",
  75. "unknown type",
  76. };
  77. #endif /* DEBUG_DNS */
  78. #ifdef DEBUG_DNS
  79. # define CLASSTYPES_COUNT 5
  80. static const char *classtypes[CLASSTYPES_COUNT + 1] = {
  81. "unknown class",
  82. "IN: the Internet",
  83. "CS: CSNET (OBSOLETE)",
  84. "CH: CHAOS",
  85. "HS: Hesoid [Dyer 87]",
  86. "unknown class"
  87. };
  88. #endif /* DEBUG_DNS */
  89. typedef struct {
  90. u_16bit_t id; /* Packet id */
  91. u_8bit_t databyte_a;
  92. /* rd:1 recursion desired
  93. * tc:1 truncated message
  94. * aa:1 authoritive answer
  95. * opcode:4 purpose of message
  96. * qr:1 response flag
  97. */
  98. u_8bit_t databyte_b;
  99. /* rcode:4 response code
  100. * unassigned:2 unassigned bits
  101. * pr:1 primary server required (non standard)
  102. * ra:1 recursion available
  103. */
  104. u_16bit_t qdcount; /* Query record count */
  105. u_16bit_t ancount; /* Answer record count */
  106. u_16bit_t nscount; /* Authority reference record count */
  107. u_16bit_t arcount; /* Resource reference record count */
  108. } packetheader;
  109. #ifndef HFIXEDSZ
  110. #define HFIXEDSZ (sizeof(packetheader))
  111. #endif
  112. /*
  113. * Byte order independent macros for packetheader
  114. */
  115. #define getheader_rd(x) (x->databyte_a & 1)
  116. #define getheader_tc(x) ((x->databyte_a >> 1) & 1)
  117. #define getheader_aa(x) ((x->databyte_a >> 2) & 1)
  118. #define getheader_opcode(x) ((x->databyte_a >> 3) & 15)
  119. #define getheader_qr(x) (x->databyte_a >> 7)
  120. #define getheader_rcode(x) (x->databyte_b & 15)
  121. #define getheader_pr(x) ((x->databyte_b >> 6) & 1)
  122. #define getheader_ra(x) (x->databyte_b >> 7)
  123. #define sucknetword(x) ((x)+=2,((u_16bit_t) (((x)[-2] << 8) | ((x)[-1] << 0))))
  124. #define sucknetshort(x) ((x)+=2,((short) (((x)[-2] << 8) | ((x)[-1] << 0))))
  125. #define sucknetdword(x) ((x)+=4,((dword) (((x)[-4] << 24) | ((x)[-3] << 16) | \
  126. ((x)[-2] << 8) | ((x)[-1] << 0))))
  127. #define sucknetlong(x) ((x)+=4,((long) (((x)[-4] << 24) | ((x)[-3] << 16) | \
  128. ((x)[-2] << 8) | ((x)[-1] << 0))))
  129. static u_32bit_t resrecvbuf[(MAX_PACKETSIZE + 7) >> 2]; /* MUST BE DWORD ALIGNED */
  130. static struct resolve *idbash[BASH_SIZE];
  131. static struct resolve *ipbash[BASH_SIZE];
  132. static struct resolve *hostbash[BASH_SIZE];
  133. static struct resolve *expireresolves = NULL;
  134. static IP localhost;
  135. static long idseed = 0xdeadbeef;
  136. static long aseed;
  137. static int resfd;
  138. static char tempstring[512] = "";
  139. static char namestring[1024 + 1] = "";
  140. static char stackstring[1024 + 1] = "";
  141. #ifdef DEBUG_DNS
  142. static char sendstring[1024 + 1] = "";
  143. #endif /* DEBUG_DNS */
  144. static const char nullstring[] = "";
  145. /*
  146. * Miscellaneous helper functions
  147. */
  148. #ifdef DEBUG_DNS
  149. /* Displays the time difference passed in signeddiff.
  150. */
  151. static char *strtdiff(char *d, long signeddiff)
  152. {
  153. u_32bit_t diff;
  154. u_32bit_t seconds, minutes, hours;
  155. long day;
  156. if ((diff = labs(signeddiff))) {
  157. seconds = diff % 60;
  158. diff /= 60;
  159. minutes = diff % 60;
  160. diff /= 60;
  161. hours = diff % 24;
  162. day = signeddiff / 86400;
  163. if (day)
  164. sprintf(d, "%lid", day);
  165. else
  166. *d = '\0';
  167. if (hours)
  168. sprintf(d + strlen(d), "%uh", hours);
  169. if (minutes)
  170. sprintf(d + strlen(d), "%um", minutes);
  171. if (seconds)
  172. sprintf(d + strlen(d), "%us", seconds);
  173. } else
  174. sprintf(d, "0s");
  175. return d;
  176. }
  177. #endif /* DEBUG_DNS */
  178. /* Allocate memory to hold one resolve request structure.
  179. */
  180. static struct resolve *allocresolve()
  181. {
  182. struct resolve *rp = NULL;
  183. rp = (struct resolve *) calloc(1, sizeof(struct resolve));
  184. return rp;
  185. }
  186. /*
  187. * Hash and linked-list related functions
  188. */
  189. /* Return the hash bucket number for id.
  190. */
  191. inline static u_32bit_t getidbash(u_16bit_t id)
  192. {
  193. return (u_32bit_t) BASH_MODULO(id);
  194. }
  195. /* Return the hash bucket number for ip.
  196. */
  197. inline static u_32bit_t getipbash(IP ip)
  198. {
  199. return (u_32bit_t) BASH_MODULO(ip);
  200. }
  201. /* Return the hash bucket number for host.
  202. */
  203. static u_32bit_t gethostbash(char *host)
  204. {
  205. u_32bit_t bashvalue = 0;
  206. for (; *host; host++) {
  207. bashvalue ^= *host;
  208. bashvalue += (*host >> 1) + (bashvalue >> 1);
  209. }
  210. return BASH_MODULO(bashvalue);
  211. }
  212. /* Insert request structure addrp into the id hash table.
  213. */
  214. static void linkresolveid(struct resolve *addrp)
  215. {
  216. struct resolve *rp = NULL;
  217. u_32bit_t bashnum;
  218. bashnum = getidbash(addrp->id);
  219. rp = idbash[bashnum];
  220. if (rp) {
  221. while ((rp->nextid) && (addrp->id > rp->nextid->id))
  222. rp = rp->nextid;
  223. while ((rp->previousid) && (addrp->id < rp->previousid->id))
  224. rp = rp->previousid;
  225. if (rp->id < addrp->id) {
  226. addrp->previousid = rp;
  227. addrp->nextid = rp->nextid;
  228. if (rp->nextid)
  229. rp->nextid->previousid = addrp;
  230. rp->nextid = addrp;
  231. } else if (rp->id > addrp->id) {
  232. addrp->previousid = rp->previousid;
  233. addrp->nextid = rp;
  234. if (rp->previousid)
  235. rp->previousid->nextid = addrp;
  236. rp->previousid = addrp;
  237. } else /* Trying to add the same id! */
  238. return;
  239. } else
  240. addrp->nextid = addrp->previousid = NULL;
  241. idbash[bashnum] = addrp;
  242. }
  243. /* Remove request structure rp from the id hash table.
  244. */
  245. static void unlinkresolveid(struct resolve *rp)
  246. {
  247. u_32bit_t bashnum;
  248. bashnum = getidbash(rp->id);
  249. if (idbash[bashnum] == rp) {
  250. if (rp->previousid)
  251. idbash[bashnum] = rp->previousid;
  252. else
  253. idbash[bashnum] = rp->nextid;
  254. }
  255. if (rp->nextid)
  256. rp->nextid->previousid = rp->previousid;
  257. if (rp->previousid)
  258. rp->previousid->nextid = rp->nextid;
  259. }
  260. /* Insert request structure addrp into the host hash table.
  261. */
  262. static void linkresolvehost(struct resolve *addrp)
  263. {
  264. struct resolve *rp = NULL;
  265. u_32bit_t bashnum;
  266. int ret;
  267. bashnum = gethostbash(addrp->hostn);
  268. rp = hostbash[bashnum];
  269. if (rp) {
  270. while ((rp->nexthost) &&
  271. (egg_strcasecmp(addrp->hostn, rp->nexthost->hostn) < 0))
  272. rp = rp->nexthost;
  273. while ((rp->previoushost) &&
  274. (egg_strcasecmp(addrp->hostn, rp->previoushost->hostn) > 0))
  275. rp = rp->previoushost;
  276. ret = egg_strcasecmp(addrp->hostn, rp->hostn);
  277. if (ret < 0) {
  278. addrp->previoushost = rp;
  279. addrp->nexthost = rp->nexthost;
  280. if (rp->nexthost)
  281. rp->nexthost->previoushost = addrp;
  282. rp->nexthost = addrp;
  283. } else if (ret > 0) {
  284. addrp->previoushost = rp->previoushost;
  285. addrp->nexthost = rp;
  286. if (rp->previoushost)
  287. rp->previoushost->nexthost = addrp;
  288. rp->previoushost = addrp;
  289. } else /* Trying to add the same host! */
  290. return;
  291. } else
  292. addrp->nexthost = addrp->previoushost = NULL;
  293. hostbash[bashnum] = addrp;
  294. }
  295. /* Remove request structure rp from the host hash table.
  296. */
  297. static void unlinkresolvehost(struct resolve *rp)
  298. {
  299. u_32bit_t bashnum;
  300. bashnum = gethostbash(rp->hostn);
  301. if (hostbash[bashnum] == rp) {
  302. if (rp->previoushost)
  303. hostbash[bashnum] = rp->previoushost;
  304. else
  305. hostbash[bashnum] = rp->nexthost;
  306. }
  307. if (rp->nexthost)
  308. rp->nexthost->previoushost = rp->previoushost;
  309. if (rp->previoushost)
  310. rp->previoushost->nexthost = rp->nexthost;
  311. free(rp->hostn);
  312. }
  313. /* Insert request structure addrp into the ip hash table.
  314. */
  315. static void linkresolveip(struct resolve *addrp)
  316. {
  317. struct resolve *rp = NULL;
  318. u_32bit_t bashnum;
  319. bashnum = getipbash(addrp->ip);
  320. rp = ipbash[bashnum];
  321. if (rp) {
  322. while ((rp->nextip) && (addrp->ip > rp->nextip->ip))
  323. rp = rp->nextip;
  324. while ((rp->previousip) && (addrp->ip < rp->previousip->ip))
  325. rp = rp->previousip;
  326. if (rp->ip < addrp->ip) {
  327. addrp->previousip = rp;
  328. addrp->nextip = rp->nextip;
  329. if (rp->nextip)
  330. rp->nextip->previousip = addrp;
  331. rp->nextip = addrp;
  332. } else if (rp->ip > addrp->ip) {
  333. addrp->previousip = rp->previousip;
  334. addrp->nextip = rp;
  335. if (rp->previousip)
  336. rp->previousip->nextip = addrp;
  337. rp->previousip = addrp;
  338. } else /* Trying to add the same ip! */
  339. return;
  340. } else
  341. addrp->nextip = addrp->previousip = NULL;
  342. ipbash[bashnum] = addrp;
  343. }
  344. /* Remove request structure rp from the ip hash table.
  345. */
  346. static void unlinkresolveip(struct resolve *rp)
  347. {
  348. u_32bit_t bashnum;
  349. bashnum = getipbash(rp->ip);
  350. if (ipbash[bashnum] == rp) {
  351. if (rp->previousip)
  352. ipbash[bashnum] = rp->previousip;
  353. else
  354. ipbash[bashnum] = rp->nextip;
  355. }
  356. if (rp->nextip)
  357. rp->nextip->previousip = rp->previousip;
  358. if (rp->previousip)
  359. rp->previousip->nextip = rp->nextip;
  360. }
  361. /* Add request structure rp to the expireresolves list. Entries are sorted
  362. * by expire time.
  363. */
  364. static void linkresolve(struct resolve *rp)
  365. {
  366. struct resolve *irp = NULL;
  367. if (expireresolves) {
  368. irp = expireresolves;
  369. while ((irp->next) && (rp->expiretime >= irp->expiretime))
  370. irp = irp->next;
  371. if (rp->expiretime >= irp->expiretime) {
  372. rp->next = NULL;
  373. rp->previous = irp;
  374. irp->next = rp;
  375. } else {
  376. rp->previous = irp->previous;
  377. rp->next = irp;
  378. if (irp->previous)
  379. irp->previous->next = rp;
  380. else
  381. expireresolves = rp;
  382. irp->previous = rp;
  383. }
  384. } else {
  385. rp->next = NULL;
  386. rp->previous = NULL;
  387. expireresolves = rp;
  388. }
  389. }
  390. /* Remove reqeust structure rp from the expireresolves list.
  391. */
  392. static void untieresolve(struct resolve *rp)
  393. {
  394. if (rp->previous)
  395. rp->previous->next = rp->next;
  396. else
  397. expireresolves = rp->next;
  398. if (rp->next)
  399. rp->next->previous = rp->previous;
  400. }
  401. /* Remove request structure rp from all lists and hash tables and
  402. * then delete and free the structure
  403. */
  404. static void unlinkresolve(struct resolve *rp)
  405. {
  406. untieresolve(rp); /* Not really needed. Left in to be on the
  407. safe side. */
  408. unlinkresolveid(rp);
  409. unlinkresolveip(rp);
  410. if (rp->hostn)
  411. unlinkresolvehost(rp);
  412. free(rp);
  413. }
  414. /* Find request structure using the id.
  415. */
  416. static struct resolve *findid(u_16bit_t id)
  417. {
  418. struct resolve *rp = NULL;
  419. int bashnum;
  420. bashnum = getidbash(id);
  421. rp = idbash[bashnum];
  422. if (rp) {
  423. while ((rp->nextid) && (id >= rp->nextid->id))
  424. rp = rp->nextid;
  425. while ((rp->previousid) && (id <= rp->previousid->id))
  426. rp = rp->previousid;
  427. if (id == rp->id) {
  428. idbash[bashnum] = rp;
  429. return rp;
  430. } else
  431. return NULL;
  432. }
  433. return rp; /* NULL */
  434. }
  435. /* Find request structure using the host.
  436. */
  437. static struct resolve *findhost(char *hostn)
  438. {
  439. struct resolve *rp = NULL;
  440. int bashnum;
  441. bashnum = gethostbash(hostn);
  442. rp = hostbash[bashnum];
  443. if (rp) {
  444. while ((rp->nexthost)
  445. && (egg_strcasecmp(hostn, rp->nexthost->hostn) >= 0))
  446. rp = rp->nexthost;
  447. while ((rp->previoushost)
  448. && (egg_strcasecmp(hostn, rp->previoushost->hostn) <= 0))
  449. rp = rp->previoushost;
  450. if (egg_strcasecmp(hostn, rp->hostn))
  451. return NULL;
  452. else {
  453. hostbash[bashnum] = rp;
  454. return rp;
  455. }
  456. }
  457. return rp; /* NULL */
  458. }
  459. /* Find request structure using the ip.
  460. */
  461. static struct resolve *findip(IP ip)
  462. {
  463. struct resolve *rp = NULL;
  464. u_32bit_t bashnum;
  465. bashnum = getipbash(ip);
  466. rp = ipbash[bashnum];
  467. if (rp) {
  468. while ((rp->nextip) && (ip >= rp->nextip->ip))
  469. rp = rp->nextip;
  470. while ((rp->previousip) && (ip <= rp->previousip->ip))
  471. rp = rp->previousip;
  472. if (ip == rp->ip) {
  473. ipbash[bashnum] = rp;
  474. return rp;
  475. } else
  476. return NULL;
  477. }
  478. return rp; /* NULL */
  479. }
  480. /*
  481. * Network and resolver related functions
  482. */
  483. /* Create packet for the request and send it to all available nameservers.
  484. */
  485. static void dorequest(char *s, int type, u_16bit_t id)
  486. {
  487. packetheader *hp = NULL;
  488. int r, i;
  489. u_8bit_t buf[(MAX_PACKETSIZE / sizeof(char)) + 1];
  490. r = res_mkquery(QUERY, s, C_IN, type, NULL, 0, NULL, buf,
  491. MAX_PACKETSIZE);
  492. if (r == -1) {
  493. ddebug0(RES_ERR "Query too large.");
  494. return;
  495. }
  496. hp = (packetheader *) buf;
  497. hp->id = id; /* htons() deliberately left out (redundant) */
  498. for (i = 0; i < _res.nscount; i++)
  499. (void) sendto(resfd, buf, r, 0,
  500. (struct sockaddr *) &_res.nsaddr_list[i],
  501. sizeof(struct sockaddr));
  502. }
  503. /* (Re-)send request with existing id.
  504. */
  505. static void resendrequest(struct resolve *rp, int type)
  506. {
  507. rp->sends++;
  508. /* Update expire time */
  509. rp->expiretime = now + (RES_RETRYDELAY * rp->sends);
  510. /* Add (back) to expire list */
  511. linkresolve(rp);
  512. if (type == T_A) {
  513. dorequest(rp->hostn, type, rp->id);
  514. ddebug1(RES_MSG "Sent domain lookup request for \"%s\".",
  515. rp->hostn);
  516. } else if (type == T_PTR) {
  517. sprintf(tempstring, "%u.%u.%u.%u.in-addr.arpa",
  518. ((u_8bit_t *) & rp->ip)[3],
  519. ((u_8bit_t *) & rp->ip)[2],
  520. ((u_8bit_t *) & rp->ip)[1], ((u_8bit_t *) & rp->ip)[0]);
  521. dorequest(tempstring, type, rp->id);
  522. ddebug1(RES_MSG "Sent domain lookup request for \"%s\".",
  523. iptostr(rp->ip));
  524. }
  525. }
  526. /* Send request for the first time.
  527. */
  528. static void sendrequest(struct resolve *rp, int type)
  529. {
  530. /* Create unique id */
  531. do {
  532. idseed = (((idseed + idseed) | (long) now)
  533. + idseed - 0x54bad4a) ^ aseed;
  534. aseed ^= idseed;
  535. rp->id = (u_16bit_t) idseed;
  536. } while (findid(rp->id));
  537. linkresolveid(rp); /* Add id to id hash table */
  538. resendrequest(rp, type); /* Send request */
  539. }
  540. /* Gets called as soon as the request turns out to have failed. Calls
  541. * the eggdrop hook.
  542. */
  543. static void failrp(struct resolve *rp, int type)
  544. {
  545. if (rp->state == STATE_FINISHED)
  546. return;
  547. rp->expiretime = now + RES_FAILEDDELAY;
  548. rp->state = STATE_FAILED;
  549. /* Expire time was changed, reinsert entry to maintain order */
  550. untieresolve(rp);
  551. linkresolve(rp);
  552. ddebug0(RES_MSG "Lookup failed.");
  553. dns_event_failure(rp, type);
  554. }
  555. /* Gets called as soon as the request turns out to be successful. Calls
  556. * the eggdrop hook.
  557. */
  558. static void passrp(struct resolve *rp, long ttl, int type)
  559. {
  560. rp->state = STATE_FINISHED;
  561. /* Do not cache entries for too long. */
  562. if (ttl < RES_MAX_TTL)
  563. rp->expiretime = now + (time_t) ttl;
  564. else
  565. rp->expiretime = now + RES_MAX_TTL;
  566. /* Expire time was changed, reinsert entry to maintain order */
  567. untieresolve(rp);
  568. linkresolve(rp);
  569. ddebug1(RES_MSG "Lookup successful: %s", rp->hostn);
  570. dns_event_success(rp, type);
  571. }
  572. /* Parses the response packets received.
  573. */
  574. static void parserespacket(u_8bit_t *s, size_t l)
  575. {
  576. struct resolve *rp = NULL;
  577. packetheader *hp = NULL;
  578. u_8bit_t *eob = NULL;
  579. u_8bit_t *c = NULL;
  580. long ttl;
  581. int r, usefulanswer;
  582. u_16bit_t rr, datatype, myclass, qdatatype, qclass;
  583. u_8bit_t rdatalength;
  584. if (l < sizeof(packetheader)) {
  585. debug0(RES_ERR "Packet smaller than standard header size.");
  586. return;
  587. }
  588. if (l == sizeof(packetheader)) {
  589. debug0(RES_ERR "Packet has empty body.");
  590. return;
  591. }
  592. hp = (packetheader *) s;
  593. /* Convert data to host byte order
  594. *
  595. * hp->id does not need to be redundantly byte-order flipped, it
  596. * is only echoed by nameserver
  597. */
  598. rp = findid(hp->id);
  599. if (!rp)
  600. return;
  601. if ((rp->state == STATE_FINISHED) || (rp->state == STATE_FAILED))
  602. return;
  603. hp->qdcount = ntohs(hp->qdcount);
  604. hp->ancount = ntohs(hp->ancount);
  605. hp->nscount = ntohs(hp->nscount);
  606. hp->arcount = ntohs(hp->arcount);
  607. if (getheader_tc(hp)) { /* Packet truncated */
  608. ddebug0(RES_ERR "Nameserver packet truncated.");
  609. return;
  610. }
  611. if (!getheader_qr(hp)) { /* Not a reply */
  612. ddebug0(RES_ERR "Query packet received on nameserver communication socket.");
  613. return;
  614. }
  615. if (getheader_opcode(hp)) { /* Not opcode 0 (standard query) */
  616. ddebug0(RES_ERR "Invalid opcode in response packet.");
  617. return;
  618. }
  619. eob = s + l;
  620. c = s + HFIXEDSZ;
  621. switch (getheader_rcode(hp)) {
  622. case NOERROR:
  623. if (hp->ancount) {
  624. ddebug4(RES_MSG
  625. "Received nameserver reply. (qd:%u an:%u ns:%u ar:%u)",
  626. hp->qdcount, hp->ancount, hp->nscount, hp->arcount);
  627. if (hp->qdcount != 1) {
  628. ddebug0(RES_ERR "Reply does not contain one query.");
  629. return;
  630. }
  631. if (c > eob) {
  632. ddebug0(RES_ERR "Reply too short.");
  633. return;
  634. }
  635. switch (rp->state) { /* Construct expected query reply */
  636. case STATE_PTRREQ:
  637. sprintf(stackstring,
  638. "%u.%u.%u.%u.in-addr.arpa",
  639. ((u_8bit_t *) & rp->ip)[3],
  640. ((u_8bit_t *) & rp->ip)[2],
  641. ((u_8bit_t *) & rp->ip)[1], ((u_8bit_t *) & rp->ip)[0]);
  642. break;
  643. case STATE_AREQ:
  644. strncpy(stackstring, rp->hostn, 1024);
  645. }
  646. *namestring = '\0';
  647. r = dn_expand(s, s + l, c, namestring, MAXDNAME);
  648. if (r == -1) {
  649. ddebug0(RES_ERR "dn_expand() failed while expanding query domain.");
  650. return;
  651. }
  652. namestring[strlen(stackstring)] = '\0';
  653. if (egg_strcasecmp(stackstring, namestring)) {
  654. ddebug2(RES_MSG "Unknown query packet dropped. (\"%s\" does not match \"%s\")", stackstring, namestring);
  655. return;
  656. }
  657. ddebug1(RES_MSG "Queried domain name: \"%s\"", namestring);
  658. c += r;
  659. if (c + 4 > eob) {
  660. ddebug0(RES_ERR "Query resource record truncated.");
  661. return;
  662. }
  663. qdatatype = sucknetword(c);
  664. qclass = sucknetword(c);
  665. if (qclass != C_IN) {
  666. ddebug2(RES_ERR "Received unsupported query class: %u (%s)",
  667. qclass, qclass < CLASSTYPES_COUNT ?
  668. classtypes[qclass] :
  669. classtypes[CLASSTYPES_COUNT]);
  670. }
  671. switch (qdatatype) {
  672. case T_PTR:
  673. if (!IS_PTR(rp)) {
  674. ddebug0(RES_WRN "Ignoring response with unexpected query type \"PTR\".");
  675. return;
  676. }
  677. break;
  678. case T_A:
  679. if (!IS_A(rp)) {
  680. ddebug0(RES_WRN "Ignoring response with unexpected query type \"PTR\".");
  681. return;
  682. }
  683. break;
  684. default:
  685. ddebug2(RES_ERR "Received unimplemented query type: %u (%s)",
  686. qdatatype,
  687. qdatatype < RESOURCETYPES_COUNT ?
  688. resourcetypes[qdatatype] :
  689. resourcetypes[RESOURCETYPES_COUNT]);
  690. }
  691. for (rr = hp->ancount + hp->nscount + hp->arcount; rr; rr--) {
  692. if (c > eob) {
  693. ddebug0(RES_ERR "Packet does not contain all specified resouce records.");
  694. return;
  695. }
  696. *namestring = '\0';
  697. r = dn_expand(s, s + l, c, namestring, MAXDNAME);
  698. if (r == -1) {
  699. ddebug0(RES_ERR "dn_expand() failed while expanding answer domain.");
  700. return;
  701. }
  702. namestring[strlen(stackstring)] = '\0';
  703. if (egg_strcasecmp(stackstring, namestring))
  704. usefulanswer = 0;
  705. else
  706. usefulanswer = 1;
  707. ddebug1(RES_MSG "answered domain query: \"%s\"", namestring);
  708. c += r;
  709. if (c + 10 > eob) {
  710. ddebug0(RES_ERR "Resource record truncated.");
  711. return;
  712. }
  713. datatype = sucknetword(c);
  714. myclass = sucknetword(c);
  715. ttl = sucknetlong(c);
  716. rdatalength = sucknetword(c);
  717. if (myclass != qclass) {
  718. ddebug2(RES_MSG "query class: %u (%s)",
  719. qclass,
  720. qclass < CLASSTYPES_COUNT ?
  721. classtypes[qclass] :
  722. classtypes[CLASSTYPES_COUNT]);
  723. ddebug2(RES_MSG "rr class: %u (%s)", myclass,
  724. myclass < CLASSTYPES_COUNT ?
  725. classtypes[myclass] :
  726. classtypes[CLASSTYPES_COUNT]);
  727. ddebug0(RES_ERR "Answered class does not match queried class.");
  728. return;
  729. }
  730. if (!rdatalength) {
  731. ddebug0(RES_ERR "Zero size rdata.");
  732. return;
  733. }
  734. if (c + rdatalength > eob) {
  735. ddebug0(RES_ERR "Specified rdata length exceeds packet size.");
  736. return;
  737. }
  738. if (datatype == qdatatype) {
  739. ddebug1(RES_MSG "TTL: %s", strtdiff(sendstring, ttl));
  740. ddebug1(RES_MSG "TYPE: %s", datatype < RESOURCETYPES_COUNT ?
  741. resourcetypes[datatype] :
  742. resourcetypes[RESOURCETYPES_COUNT]);
  743. if (usefulanswer)
  744. switch (datatype) {
  745. case T_A:
  746. if (rdatalength != 4) {
  747. ddebug1(RES_ERR "Unsupported rdata format for \"A\" type. (%u bytes)", rdatalength);
  748. return;
  749. }
  750. egg_memcpy(&rp->ip, (IP *) c, sizeof(IP));
  751. linkresolveip(rp);
  752. passrp(rp, ttl, T_A);
  753. return;
  754. case T_PTR:
  755. *namestring = '\0';
  756. r = dn_expand(s, s + l, c, namestring, MAXDNAME);
  757. if (r == -1) {
  758. ddebug0(RES_ERR "dn_expand() failed while expanding domain in rdata.");
  759. return;
  760. }
  761. ddebug1(RES_MSG "Answered domain: \"%s\"",
  762. namestring);
  763. if (r > HOSTNAMELEN) {
  764. ddebug0(RES_ERR "Domain name too long.");
  765. failrp(rp, T_PTR);
  766. return;
  767. }
  768. if (!rp->hostn) {
  769. rp->hostn = strdup(namestring);
  770. linkresolvehost(rp);
  771. passrp(rp, ttl, T_PTR);
  772. return;
  773. }
  774. break;
  775. default:
  776. ddebug2(RES_ERR "Received unimplemented data type: %u (%s)",
  777. datatype,
  778. datatype < RESOURCETYPES_COUNT ?
  779. resourcetypes[datatype] :
  780. resourcetypes[RESOURCETYPES_COUNT]);
  781. }
  782. } else if (datatype == T_CNAME) {
  783. *namestring = '\0';
  784. r = dn_expand(s, s + l, c, namestring, MAXDNAME);
  785. if (r == -1) {
  786. ddebug0(RES_ERR "dn_expand() failed while expanding domain in rdata.");
  787. return;
  788. }
  789. ddebug1(RES_MSG "answered domain is CNAME for: %s",
  790. namestring);
  791. /* The next responses will be related to the domain
  792. * pointed to by CNAME, so we need to update which
  793. * respones we regard as important.
  794. */
  795. strncpy(stackstring, namestring, 1024);
  796. } else {
  797. ddebug2(RES_MSG "Ignoring resource type %u. (%s)",
  798. datatype, datatype < RESOURCETYPES_COUNT ?
  799. resourcetypes[datatype] :
  800. resourcetypes[RESOURCETYPES_COUNT]);
  801. }
  802. c += rdatalength;
  803. }
  804. } else {
  805. ddebug0(RES_ERR "No error returned but no answers given.");
  806. }
  807. break;
  808. case NXDOMAIN:
  809. ddebug0(RES_MSG "Host not found.");
  810. switch (rp->state) {
  811. case STATE_PTRREQ:
  812. failrp(rp, T_PTR);
  813. break;
  814. case STATE_AREQ:
  815. failrp(rp, T_A);
  816. break;
  817. default:
  818. failrp(rp, 0);
  819. break;
  820. }
  821. break;
  822. default:
  823. ddebug2(RES_MSG "Received error response %u. (%s)",
  824. getheader_rcode(hp),
  825. getheader_rcode(hp) < RESPONSECODES_COUNT ?
  826. responsecodes[getheader_rcode(hp)] :
  827. responsecodes[RESPONSECODES_COUNT]);
  828. }
  829. }
  830. /* Read data received on our dns socket. This function is called
  831. * as soon as traffic is detected.
  832. */
  833. static void dns_ack(void)
  834. {
  835. struct sockaddr_in from;
  836. unsigned int fromlen = sizeof(struct sockaddr_in);
  837. int r, i;
  838. r = recvfrom(resfd, (u_8bit_t *) resrecvbuf, MAX_PACKETSIZE, 0,
  839. (struct sockaddr *) &from, &fromlen);
  840. if (r <= 0) {
  841. ddebug1(RES_MSG "Socket error: %s", strerror(errno));
  842. return;
  843. }
  844. /* Check to see if this server is actually one we sent to */
  845. if (from.sin_addr.s_addr == localhost) {
  846. for (i = 0; i < _res.nscount; i++)
  847. /* 0.0.0.0 replies as 127.0.0.1 */
  848. if ((_res.nsaddr_list[i].sin_addr.s_addr == from.sin_addr.s_addr)
  849. || (!_res.nsaddr_list[i].sin_addr.s_addr))
  850. break;
  851. } else {
  852. for (i = 0; i < _res.nscount; i++)
  853. if (_res.nsaddr_list[i].sin_addr.s_addr == from.sin_addr.s_addr)
  854. break;
  855. }
  856. if (i == _res.nscount) {
  857. ddebug1(RES_ERR "Received reply from unknown source: %s",
  858. iptostr(from.sin_addr.s_addr));
  859. } else
  860. parserespacket((u_8bit_t *) resrecvbuf, (size_t) r);
  861. }
  862. /* Remove or resend expired requests. Called once a second.
  863. */
  864. static void dns_check_expires(void)
  865. {
  866. struct resolve *rp = NULL, *nextrp = NULL;
  867. /* Walk through sorted list ... */
  868. for (rp = expireresolves; (rp) && (now >= rp->expiretime);
  869. rp = nextrp) {
  870. nextrp = rp->next;
  871. untieresolve(rp);
  872. switch (rp->state) {
  873. case STATE_FINISHED: /* TTL has expired */
  874. case STATE_FAILED: /* Fake TTL has expired */
  875. ddebug4(RES_MSG "Cache record for \"%s\" (%s) has expired. (state: %u) Marked for expire at: %ld.",
  876. nonull(rp->hostn), iptostr(rp->ip), rp->state,
  877. rp->expiretime);
  878. unlinkresolve(rp);
  879. break;
  880. case STATE_PTRREQ: /* T_PTR send timed out */
  881. if (rp->sends <= RES_MAXSENDS) {
  882. ddebug1(RES_MSG "Resend #%d for \"PTR\" query...", rp->sends - 1);
  883. resendrequest(rp, T_PTR);
  884. } else {
  885. ddebug0(RES_MSG "\"PTR\" query timed out.");
  886. failrp(rp, T_PTR);
  887. }
  888. break;
  889. case STATE_AREQ: /* T_A send timed out */
  890. if (rp->sends <= RES_MAXSENDS) {
  891. ddebug1(RES_MSG "Resend #%d for \"A\" query...", rp->sends - 1);
  892. resendrequest(rp, T_A);
  893. } else {
  894. ddebug0(RES_MSG "\"A\" query timed out.");
  895. failrp(rp, T_A);
  896. }
  897. break;
  898. default: /* Unknown state, let it expire */
  899. ddebug1(RES_WRN "Unknown request state %d. Request expired.",
  900. rp->state);
  901. failrp(rp, 0);
  902. }
  903. }
  904. }
  905. /* Start searching for a host-name, using it's ip-address.
  906. */
  907. void dns_hostbyip(IP ip)
  908. {
  909. struct resolve *rp = NULL;
  910. ip = htonl(ip);
  911. if ((rp = findip(ip))) {
  912. if (rp->state == STATE_FINISHED || rp->state == STATE_FAILED) {
  913. if (rp->state == STATE_FINISHED && rp->hostn) {
  914. ddebug2(RES_MSG "Used cached record: %s == \"%s\".",
  915. iptostr(ip), rp->hostn);
  916. dns_event_success(rp, T_PTR);
  917. } else {
  918. ddebug1(RES_MSG "Used failed record: %s == ???", iptostr(ip));
  919. dns_event_failure(rp, T_PTR);
  920. }
  921. }
  922. return;
  923. }
  924. ddebug0(RES_MSG "Creating new record");
  925. rp = allocresolve();
  926. rp->state = STATE_PTRREQ;
  927. rp->sends = 1;
  928. rp->ip = ip;
  929. linkresolveip(rp);
  930. sendrequest(rp, T_PTR);
  931. }
  932. /* Start searching for an ip-address, using it's host-name.
  933. */
  934. void dns_ipbyhost(char *hostn)
  935. {
  936. struct resolve *rp = NULL;
  937. struct in_addr inaddr;
  938. /* Check if someone passed us an IP address as hostname
  939. * and return it straight away.
  940. */
  941. if (egg_inet_aton(hostn, &inaddr)) {
  942. call_ipbyhost(hostn, ntohl(inaddr.s_addr), 1);
  943. return;
  944. }
  945. if ((rp = findhost(hostn))) {
  946. if (rp->state == STATE_FINISHED || rp->state == STATE_FAILED) {
  947. if (rp->state == STATE_FINISHED && rp->ip) {
  948. ddebug2(RES_MSG "Used cached record: %s == \"%s\".", hostn,
  949. iptostr(rp->ip));
  950. dns_event_success(rp, T_A);
  951. } else {
  952. ddebug1(RES_MSG "Used failed record: %s == ???", hostn);
  953. dns_event_failure(rp, T_A);
  954. }
  955. }
  956. return;
  957. }
  958. ddebug0(RES_MSG "Creating new record");
  959. rp = allocresolve();
  960. rp->state = STATE_AREQ;
  961. rp->sends = 1;
  962. rp->hostn = strdup(hostn);
  963. linkresolvehost(rp);
  964. sendrequest(rp, T_A);
  965. }
  966. /* Initialise the network.
  967. */
  968. static int init_dns_network(void)
  969. {
  970. int option;
  971. struct in_addr inaddr;
  972. resfd = socket(AF_INET, SOCK_DGRAM, 0);
  973. if (resfd == -1) {
  974. putlog(LOG_MISC, "*",
  975. "Unable to allocate socket for nameserver communication: %s",
  976. strerror(errno));
  977. return 0;
  978. }
  979. (void) allocsock(resfd, SOCK_PASS);
  980. option = 1;
  981. if (setsockopt(resfd, SOL_SOCKET, SO_BROADCAST, (char *) &option,
  982. sizeof(option))) {
  983. putlog(LOG_MISC, "*",
  984. "Unable to setsockopt() on nameserver communication socket: %s",
  985. strerror(errno));
  986. killsock(resfd);
  987. return 0;
  988. }
  989. egg_inet_aton("127.0.0.1", &inaddr);
  990. localhost = inaddr.s_addr;
  991. return 1;
  992. }
  993. /* Initialise the core dns system, returns 1 if all goes well, 0 if not.
  994. */
  995. static int init_dns_core(void)
  996. {
  997. int i;
  998. /* Initialise the resolv library. */
  999. res_init();
  1000. if (!_res.nscount) {
  1001. putlog(LOG_MISC, "*", "No nameservers defined.");
  1002. return 0;
  1003. }
  1004. for (i = 0; i < _res.nscount; i++) {
  1005. char s[102] = "";
  1006. egg_inet_ntop(AF_INET, &_res.nsaddr_list[i].sin_addr, s, 101);
  1007. sdprintf("added ns: %s", s);
  1008. _res.nsaddr_list[i].sin_family = AF_INET;
  1009. }
  1010. if (!init_dns_network())
  1011. return 0;
  1012. /* Initialise the hash tables. */
  1013. aseed = time(NULL) ^ (time(NULL) << 3) ^ (u_32bit_t) getpid();
  1014. for (i = 0; i < BASH_SIZE; i++) {
  1015. idbash[i] = NULL;
  1016. ipbash[i] = NULL;
  1017. hostbash[i] = NULL;
  1018. }
  1019. expireresolves = NULL;
  1020. return 1;
  1021. }