resolv.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966
  1. /* resolv.c: DNS Resolver
  2. *
  3. * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>,
  4. * The Silver Hammer Group, Ltd.
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Library General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2 of the License, or (at your option) any later version.
  10. *
  11. * 5-Oct-2000 W. Greathouse wgreathouse@smva.com
  12. * Fix memory leak and memory corruption.
  13. * -- Every name resolution resulted in
  14. * a new parse of resolv.conf and new
  15. * copy of nameservers allocated by
  16. * strdup.
  17. * -- Every name resolution resulted in
  18. * a new read of resolv.conf without
  19. * resetting index from prior read...
  20. * resulting in exceeding array bounds.
  21. *
  22. * Limit nameservers read from resolv.conf
  23. *
  24. * Add "search" domains from resolv.conf
  25. *
  26. * Some systems will return a security
  27. * signature along with query answer for
  28. * dynamic DNS entries.
  29. * -- skip/ignore this answer
  30. *
  31. * Include arpa/nameser.h for defines.
  32. *
  33. * General cleanup
  34. *
  35. */
  36. #define __FORCE_GLIBC__
  37. #include <features.h>
  38. #include <string.h>
  39. #include <stdio.h>
  40. #include <signal.h>
  41. #include <errno.h>
  42. #include <sys/socket.h>
  43. #include <sys/types.h>
  44. #include <netinet/in.h>
  45. #include <arpa/inet.h>
  46. #include <stdlib.h>
  47. #include <unistd.h>
  48. #include <cfgfile.h>
  49. #include <resolv.h>
  50. #include <netdb.h>
  51. #include <arpa/nameser.h>
  52. #define MAX_RECURSE 5
  53. #define REPLY_TIMEOUT 10
  54. #define MAX_RETRIES 15
  55. #define MAX_SERVERS 3
  56. #define MAX_SEARCH 4
  57. #undef DEBUG
  58. #ifdef DEBUG
  59. static inline void DPRINTF(const char *format, ...)
  60. {
  61. va_list args;
  62. va_start(args, format);
  63. vfprintf(stderr, format, args);
  64. va_end(args);
  65. }
  66. #else
  67. static inline void DPRINTF(const char *format, ...) { }
  68. #endif
  69. #ifdef L_encodeh
  70. int encode_header(struct resolv_header *h, unsigned char *dest, int maxlen)
  71. {
  72. if (maxlen < HFIXEDSZ)
  73. return -1;
  74. dest[0] = (h->id & 0xff00) >> 8;
  75. dest[1] = (h->id & 0x00ff) >> 0;
  76. dest[2] = (h->qr ? 0x80 : 0) |
  77. ((h->opcode & 0x0f) << 3) |
  78. (h->aa ? 0x04 : 0) | (h->tc ? 0x02 : 0) | (h->rd ? 0x01 : 0);
  79. dest[3] = (h->ra ? 0x80 : 0) | (h->rcode & 0x0f);
  80. dest[4] = (h->qdcount & 0xff00) >> 8;
  81. dest[5] = (h->qdcount & 0x00ff) >> 0;
  82. dest[6] = (h->ancount & 0xff00) >> 8;
  83. dest[7] = (h->ancount & 0x00ff) >> 0;
  84. dest[8] = (h->nscount & 0xff00) >> 8;
  85. dest[9] = (h->nscount & 0x00ff) >> 0;
  86. dest[10] = (h->arcount & 0xff00) >> 8;
  87. dest[11] = (h->arcount & 0x00ff) >> 0;
  88. return HFIXEDSZ;
  89. }
  90. #endif
  91. #ifdef L_decodeh
  92. int decode_header(unsigned char *data, struct resolv_header *h)
  93. {
  94. h->id = (data[0] << 8) | data[1];
  95. h->qr = (data[2] & 0x80) ? 1 : 0;
  96. h->opcode = (data[2] >> 3) & 0x0f;
  97. h->aa = (data[2] & 0x04) ? 1 : 0;
  98. h->tc = (data[2] & 0x02) ? 1 : 0;
  99. h->rd = (data[2] & 0x01) ? 1 : 0;
  100. h->ra = (data[3] & 0x80) ? 1 : 0;
  101. h->rcode = data[3] & 0x0f;
  102. h->qdcount = (data[4] << 8) | data[5];
  103. h->ancount = (data[6] << 8) | data[7];
  104. h->nscount = (data[8] << 8) | data[9];
  105. h->arcount = (data[10] << 8) | data[11];
  106. return HFIXEDSZ;
  107. }
  108. #endif
  109. #ifdef L_encoded
  110. /* Encode a dotted string into nameserver transport-level encoding.
  111. This routine is fairly dumb, and doesn't attempt to compress
  112. the data */
  113. int encode_dotted(const char *dotted, unsigned char *dest, int maxlen)
  114. {
  115. int used = 0;
  116. while (dotted && *dotted) {
  117. char *c = strchr(dotted, '.');
  118. int l = c ? c - dotted : strlen(dotted);
  119. if (l >= (maxlen - used - 1))
  120. return -1;
  121. dest[used++] = l;
  122. memcpy(dest + used, dotted, l);
  123. used += l;
  124. if (c)
  125. dotted = c + 1;
  126. else
  127. break;
  128. }
  129. if (maxlen < 1)
  130. return -1;
  131. dest[used++] = 0;
  132. return used;
  133. }
  134. #endif
  135. #ifdef L_decoded
  136. /* Decode a dotted string from nameserver transport-level encoding.
  137. This routine understands compressed data. */
  138. int decode_dotted(const unsigned char *data, int offset,
  139. char *dest, int maxlen)
  140. {
  141. int l;
  142. int measure = 1;
  143. int total = 0;
  144. int used = 0;
  145. if (!data)
  146. return -1;
  147. while ((l = data[offset++])) {
  148. if (measure && total++)
  149. break;
  150. if ((l & 0xc0) == (0xc0)) {
  151. if (measure)
  152. total++;
  153. /* compressed item, redirect */
  154. offset = ((l & 0x3f) << 8) | data[offset];
  155. measure = 0;
  156. continue;
  157. }
  158. if ((used + l + 1) >= maxlen)
  159. return -1;
  160. memcpy(dest + used, data + offset, l);
  161. offset += l;
  162. used += l;
  163. if (measure)
  164. total += l;
  165. if (data[offset] != 0)
  166. dest[used++] = '.';
  167. else
  168. dest[used++] = '\0';
  169. }
  170. DPRINTF("Total decode len = %d\n", total);
  171. return total;
  172. }
  173. #endif
  174. #ifdef L_lengthd
  175. int length_dotted(const unsigned char *data, int offset)
  176. {
  177. int orig_offset = offset;
  178. int l;
  179. if (!data)
  180. return -1;
  181. while ((l = data[offset++])) {
  182. if ((l & 0xc0) == (0xc0)) {
  183. offset++;
  184. break;
  185. }
  186. offset += l;
  187. }
  188. return offset - orig_offset;
  189. }
  190. #endif
  191. #ifdef L_encodeq
  192. int encode_question(struct resolv_question *q,
  193. unsigned char *dest, int maxlen)
  194. {
  195. int i;
  196. i = encode_dotted(q->dotted, dest, maxlen);
  197. if (i < 0)
  198. return i;
  199. dest += i;
  200. maxlen -= i;
  201. if (maxlen < 4)
  202. return -1;
  203. dest[0] = (q->qtype & 0xff00) >> 8;
  204. dest[1] = (q->qtype & 0x00ff) >> 0;
  205. dest[2] = (q->qclass & 0xff00) >> 8;
  206. dest[3] = (q->qclass & 0x00ff) >> 0;
  207. return i + 4;
  208. }
  209. #endif
  210. #ifdef L_decodeq
  211. int decode_question(unsigned char *message, int offset,
  212. struct resolv_question *q)
  213. {
  214. char temp[256];
  215. int i;
  216. i = decode_dotted(message, offset, temp, sizeof(temp));
  217. if (i < 0)
  218. return i;
  219. offset += i;
  220. q->dotted = strdup(temp);
  221. q->qtype = (message[offset + 0] << 8) | message[offset + 1];
  222. q->qclass = (message[offset + 2] << 8) | message[offset + 3];
  223. return i + 4;
  224. }
  225. #endif
  226. #ifdef L_lengthq
  227. int length_question(unsigned char *message, int offset)
  228. {
  229. int i;
  230. i = length_dotted(message, offset);
  231. if (i < 0)
  232. return i;
  233. return i + 4;
  234. }
  235. #endif
  236. #ifdef L_encodea
  237. int encode_answer(struct resolv_answer *a, unsigned char *dest, int maxlen)
  238. {
  239. int i;
  240. i = encode_dotted(a->dotted, dest, maxlen);
  241. if (i < 0)
  242. return i;
  243. dest += i;
  244. maxlen -= i;
  245. if (maxlen < (RRFIXEDSZ+a->rdlength))
  246. return -1;
  247. *dest++ = (a->atype & 0xff00) >> 8;
  248. *dest++ = (a->atype & 0x00ff) >> 0;
  249. *dest++ = (a->aclass & 0xff00) >> 8;
  250. *dest++ = (a->aclass & 0x00ff) >> 0;
  251. *dest++ = (a->ttl & 0xff000000) >> 24;
  252. *dest++ = (a->ttl & 0x00ff0000) >> 16;
  253. *dest++ = (a->ttl & 0x0000ff00) >> 8;
  254. *dest++ = (a->ttl & 0x000000ff) >> 0;
  255. *dest++ = (a->rdlength & 0xff00) >> 8;
  256. *dest++ = (a->rdlength & 0x00ff) >> 0;
  257. memcpy(dest, a->rdata, a->rdlength);
  258. return i + RRFIXEDSZ + a->rdlength;
  259. }
  260. #endif
  261. #ifdef L_decodea
  262. int decode_answer(unsigned char *message, int offset,
  263. struct resolv_answer *a)
  264. {
  265. char temp[256];
  266. int i;
  267. i = decode_dotted(message, offset, temp, sizeof(temp));
  268. if (i < 0)
  269. return i;
  270. message += offset + i;
  271. a->dotted = strdup(temp);
  272. a->atype = (message[0] << 8) | message[1];
  273. message += 2;
  274. a->aclass = (message[0] << 8) | message[1];
  275. message += 2;
  276. a->ttl = (message[0] << 24) |
  277. (message[1] << 16) | (message[2] << 8) | (message[3] << 0);
  278. message += 4;
  279. a->rdlength = (message[0] << 8) | message[1];
  280. message += 2;
  281. a->rdata = message;
  282. a->rdoffset = offset + i + RRFIXEDSZ;
  283. DPRINTF("i=%d,rdlength=%d\n", i, a->rdlength);
  284. return i + RRFIXEDSZ + a->rdlength;
  285. }
  286. #endif
  287. #ifdef L_encodep
  288. int encode_packet(struct resolv_header *h,
  289. struct resolv_question **q,
  290. struct resolv_answer **an,
  291. struct resolv_answer **ns,
  292. struct resolv_answer **ar,
  293. unsigned char *dest, int maxlen)
  294. {
  295. int i, total = 0;
  296. int j;
  297. i = encode_header(h, dest, maxlen);
  298. if (i < 0)
  299. return i;
  300. dest += i;
  301. maxlen -= i;
  302. total += i;
  303. for (j = 0; j < h->qdcount; j++) {
  304. i = encode_question(q[j], dest, maxlen);
  305. if (i < 0)
  306. return i;
  307. dest += i;
  308. maxlen -= i;
  309. total += i;
  310. }
  311. for (j = 0; j < h->ancount; j++) {
  312. i = encode_answer(an[j], dest, maxlen);
  313. if (i < 0)
  314. return i;
  315. dest += i;
  316. maxlen -= i;
  317. total += i;
  318. }
  319. for (j = 0; j < h->nscount; j++) {
  320. i = encode_answer(ns[j], dest, maxlen);
  321. if (i < 0)
  322. return i;
  323. dest += i;
  324. maxlen -= i;
  325. total += i;
  326. }
  327. for (j = 0; j < h->arcount; j++) {
  328. i = encode_answer(ar[j], dest, maxlen);
  329. if (i < 0)
  330. return i;
  331. dest += i;
  332. maxlen -= i;
  333. total += i;
  334. }
  335. return total;
  336. }
  337. #endif
  338. #ifdef L_decodep
  339. int decode_packet(unsigned char *data, struct resolv_header *h)
  340. {
  341. return decode_header(data, h);
  342. }
  343. #endif
  344. #ifdef L_formquery
  345. int form_query(int id, const char *name, int type, unsigned char *packet,
  346. int maxlen)
  347. {
  348. struct resolv_header h;
  349. struct resolv_question q;
  350. int i, j;
  351. memset(&h, 0, sizeof(h));
  352. h.id = id;
  353. h.qdcount = 1;
  354. q.dotted = (char *) name;
  355. q.qtype = type;
  356. q.qclass = C_IN; /* CLASS_IN */
  357. i = encode_header(&h, packet, maxlen);
  358. if (i < 0)
  359. return i;
  360. j = encode_question(&q, packet + i, maxlen - i);
  361. if (j < 0)
  362. return j;
  363. return i + j;
  364. }
  365. #endif
  366. #ifdef L_dnslookup
  367. int dns_caught_signal = 0;
  368. void dns_catch_signal(int signo)
  369. {
  370. dns_caught_signal = 1;
  371. }
  372. int dns_lookup(const char *name, int type, int nscount, const char **nsip,
  373. unsigned char **outpacket, struct resolv_answer *a)
  374. {
  375. static int id = 1;
  376. int i, j, len, fd, pos;
  377. static int ns = 0;
  378. struct sockaddr_in sa;
  379. int oldalarm;
  380. __sighandler_t oldhandler;
  381. struct resolv_header h;
  382. struct resolv_question q;
  383. int retries = 0;
  384. unsigned char * packet = malloc(PACKETSZ);
  385. unsigned char * lookup = malloc(MAXDNAME);
  386. int variant = 0;
  387. extern int searchdomains;
  388. extern const char * searchdomain[MAX_SEARCH];
  389. fd = -1;
  390. if (!packet || !lookup || !nscount)
  391. goto fail;
  392. DPRINTF("Looking up type %d answer for '%s'\n", type, name);
  393. ns %= nscount;
  394. while (retries++ < MAX_RETRIES) {
  395. if (fd != -1)
  396. close(fd);
  397. fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  398. if (fd == -1)
  399. goto fail;
  400. memset(packet, 0, PACKETSZ);
  401. memset(&h, 0, sizeof(h));
  402. h.id = ++id;
  403. h.qdcount = 1;
  404. h.rd = 1;
  405. DPRINTF("encoding header\n", h.rd);
  406. i = encode_header(&h, packet, PACKETSZ);
  407. if (i < 0)
  408. goto fail;
  409. strncpy(lookup,name,MAXDNAME);
  410. if (variant < searchdomains)
  411. {
  412. strncat(lookup,".", MAXDNAME);
  413. strncat(lookup,searchdomain[variant], MAXDNAME);
  414. }
  415. DPRINTF("lookup name: %s\n", lookup);
  416. q.dotted = (char *)lookup;
  417. q.qtype = type;
  418. q.qclass = C_IN; /* CLASS_IN */
  419. j = encode_question(&q, packet+i, PACKETSZ-i);
  420. if (j < 0)
  421. goto fail;
  422. len = i + j;
  423. DPRINTF("On try %d, sending query to port %d of machine %s\n",
  424. retries, NAMESERVER_PORT, nsip[ns]);
  425. sa.sin_family = AF_INET;
  426. sa.sin_port = htons(NAMESERVER_PORT);
  427. sa.sin_addr.s_addr = inet_addr(nsip[ns]);
  428. if (connect(fd, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
  429. if (errno == ENETUNREACH) {
  430. /* routing error, presume not transient */
  431. goto tryall;
  432. } else
  433. /* retry */
  434. continue;
  435. }
  436. DPRINTF("Transmitting packet of length %d, id=%d, qr=%d\n",
  437. len, h.id, h.qr);
  438. send(fd, packet, len, 0);
  439. dns_caught_signal = 0;
  440. oldalarm = alarm(REPLY_TIMEOUT);
  441. oldhandler = signal(SIGALRM, dns_catch_signal);
  442. i = recv(fd, packet, PACKETSZ, 0);
  443. alarm(0);
  444. signal(SIGALRM, oldhandler);
  445. alarm(oldalarm);
  446. DPRINTF("Timeout=%d, len=%d\n", dns_caught_signal, i);
  447. if (dns_caught_signal)
  448. /* timed out, so retry send and receive,
  449. to next nameserver on queue */
  450. goto again;
  451. if (i < HFIXEDSZ)
  452. /* too short ! */
  453. goto again;
  454. decode_header(packet, &h);
  455. DPRINTF("id = %d, qr = %d\n", h.id, h.qr);
  456. if ((h.id != id) || (!h.qr))
  457. /* unsolicited */
  458. goto again;
  459. DPRINTF("Got response %s\n", "(i think)!");
  460. DPRINTF("qrcount=%d,ancount=%d,nscount=%d,arcount=%d\n",
  461. h.qdcount, h.ancount, h.nscount, h.arcount);
  462. DPRINTF("opcode=%d,aa=%d,tc=%d,rd=%d,ra=%d,rcode=%d\n",
  463. h.opcode, h.aa, h.tc, h.rd, h.ra, h.rcode);
  464. if ((h.rcode) || (h.ancount < 1)) {
  465. /* negative result, not present */
  466. goto again;
  467. }
  468. pos = HFIXEDSZ;
  469. for (j = 0; j < h.qdcount; j++) {
  470. DPRINTF("Skipping question %d at %d\n", j, pos);
  471. i = length_question(packet, pos);
  472. DPRINTF("Length of question %d is %d\n", j, i);
  473. if (i < 0)
  474. goto again;
  475. pos += i;
  476. }
  477. DPRINTF("Decoding answer at pos %d\n", pos);
  478. for (j=0;j<h.ancount;j++)
  479. {
  480. i = decode_answer(packet, pos, a);
  481. if (i<0) {
  482. DPRINTF("failed decode %d\n", i);
  483. goto again;
  484. }
  485. /* For all but T_SIG, accept first answer */
  486. if (a->atype != T_SIG)
  487. break;
  488. DPRINTF("skipping T_SIG %d\n", i);
  489. free(a->dotted);
  490. pos += i;
  491. }
  492. DPRINTF("Answer name = |%s|\n", a->dotted);
  493. DPRINTF("Answer type = |%d|\n", a->atype);
  494. close(fd);
  495. if (outpacket)
  496. *outpacket = packet;
  497. else
  498. free(packet);
  499. return (0); /* success! */
  500. tryall:
  501. /* if there are other nameservers, give them a go,
  502. otherwise return with error */
  503. variant = 0;
  504. if (retries >= nscount*(searchdomains+1))
  505. goto fail;
  506. again:
  507. /* if there are searchdomains, try them or fallback as passed */
  508. if (variant < searchdomains) {
  509. /* next search */
  510. variant++;
  511. } else {
  512. /* next server, first search */
  513. ns = (ns + 1) % nscount;
  514. variant = 0;
  515. }
  516. }
  517. fail:
  518. if (fd != -1)
  519. close(fd);
  520. if (lookup)
  521. free(lookup);
  522. if (packet)
  523. free(packet);
  524. return -1;
  525. }
  526. #endif
  527. #ifdef L_resolveaddress
  528. int resolve_address(const char *address, int nscount,
  529. const char **nsip, struct in_addr *in)
  530. {
  531. unsigned char *packet;
  532. struct resolv_answer a;
  533. char temp[256];
  534. int i;
  535. int nest = 0;
  536. if (!address || !in)
  537. return -1;
  538. strncpy(temp, address, sizeof(temp));
  539. for (;;) {
  540. i = dns_lookup(temp, T_A, nscount, nsip, &packet, &a);
  541. if (i < 0)
  542. return -1;
  543. free(a.dotted);
  544. if (a.atype == T_CNAME) { /* CNAME */
  545. i = decode_dotted(packet, a.rdoffset, temp, sizeof(temp));
  546. free(packet);
  547. if (i < 0)
  548. return -1;
  549. if (++nest > MAX_RECURSE)
  550. return -1;
  551. continue;
  552. } else if (a.atype == T_A) { /* ADDRESS */
  553. free(packet);
  554. break;
  555. } else {
  556. free(packet);
  557. return -1;
  558. }
  559. }
  560. if (in)
  561. memcpy(in, a.rdata, INADDRSZ); /* IPv4 T_A */
  562. return 0;
  563. }
  564. #endif
  565. #ifdef L_resolvemailbox
  566. int resolve_mailbox(const char *address,
  567. int nscount, const char **nsip, struct in_addr *in)
  568. {
  569. struct resolv_answer a;
  570. unsigned char *packet;
  571. char temp[256];
  572. int nest = 0;
  573. int i;
  574. if (!address || !in)
  575. return -1;
  576. /* look up mail exchange */
  577. i = dns_lookup(address, T_MX, nscount, nsip, &packet, &a);
  578. strncpy(temp, address, sizeof(temp));
  579. if (i >= 0) {
  580. i = decode_dotted(packet, a.rdoffset+2, temp, sizeof(temp));
  581. free(packet);
  582. }
  583. for (;;) {
  584. i = dns_lookup(temp, T_A, nscount, nsip, &packet, &a);
  585. if (i < 0)
  586. return -1;
  587. free(a.dotted);
  588. if (a.atype == T_CNAME) { /* CNAME */
  589. i = decode_dotted(packet, a.rdoffset, temp, sizeof(temp));
  590. free(packet);
  591. if (i < 0)
  592. return i;
  593. if (++nest > MAX_RECURSE)
  594. return -1;
  595. continue;
  596. } else if (a.atype == T_A) { /* ADDRESS */
  597. free(packet);
  598. break;
  599. } else {
  600. free(packet);
  601. return -1;
  602. }
  603. }
  604. if (in)
  605. memcpy(in, a.rdata, INADDRSZ); /* IPv4 */
  606. return 0;
  607. }
  608. #endif
  609. extern int nameservers;
  610. extern const char * nameserver[MAX_SERVERS];
  611. extern int searchdomains;
  612. extern const char * searchdomain[MAX_SEARCH];
  613. #ifdef L_opennameservers
  614. int nameservers;
  615. const char * nameserver[MAX_SERVERS];
  616. int searchdomains;
  617. const char * searchdomain[MAX_SEARCH];
  618. int open_nameservers()
  619. {
  620. FILE *fp;
  621. char **arg;
  622. int i;
  623. if (nameservers > 0)
  624. return 0;
  625. if ((fp = fopen("/etc/resolv.conf", "r"))) {
  626. if (0 != (arg = cfgfind(fp, "nameserver"))) {
  627. for (i=1; arg[i] && nameservers <= MAX_SERVERS; i++) {
  628. nameserver[nameservers++] = strdup(arg[i]);
  629. DPRINTF("adding nameserver %s\n",arg[i]);
  630. }
  631. }
  632. if (0 != (arg = cfgfind(fp, "search"))) {
  633. for (i=1; arg[i] && searchdomains <= MAX_SEARCH; i++) {
  634. searchdomain[searchdomains++] = strdup(arg[i]);
  635. DPRINTF("adding search %s\n",arg[i]);
  636. }
  637. }
  638. fclose(fp);
  639. } else {
  640. DPRINTF("failed to open %s\n", "resolv.conf");
  641. }
  642. DPRINTF("nameservers = %d\n", nameservers);
  643. return 0;
  644. }
  645. #endif
  646. #ifdef L_closenameservers
  647. void close_nameservers(void)
  648. {
  649. while (nameservers > 0)
  650. free((void*)nameserver[--nameservers]);
  651. }
  652. #endif
  653. #ifdef L_resolvename
  654. const char *resolve_name(const char *name, int mailbox)
  655. {
  656. struct in_addr in;
  657. int i;
  658. /* shortcut: is it a valid IP address to begin with? */
  659. if (inet_aton(name, &in))
  660. return name;
  661. open_nameservers();
  662. DPRINTF("looking up '%s', mailbox=%d, nameservers=%d\n",
  663. name, mailbox, nameservers);
  664. if (mailbox)
  665. i = resolve_mailbox(name, nameservers, nameserver, &in);
  666. else
  667. i = resolve_address(name, nameservers, nameserver, &in);
  668. if (i < 0)
  669. return 0;
  670. DPRINTF("success = '%s'\n", inet_ntoa(in));
  671. return inet_ntoa(in);
  672. }
  673. #endif
  674. #ifdef L_gethostbyname
  675. struct hostent *gethostbyname(const char *name)
  676. {
  677. static struct hostent h;
  678. static char namebuf[256];
  679. static struct in_addr in;
  680. static struct in_addr *addr_list[2];
  681. unsigned char *packet;
  682. struct resolv_answer a;
  683. int i;
  684. int nest = 0;
  685. open_nameservers();
  686. if (!name)
  687. return 0;
  688. memset(&h, 0, sizeof(h));
  689. addr_list[0] = &in;
  690. addr_list[1] = 0;
  691. strcpy(namebuf, name);
  692. for (;;) {
  693. i = dns_lookup(namebuf, 1, nameservers, nameserver, &packet, &a);
  694. if (i < 0)
  695. return 0;
  696. strncpy(namebuf, a.dotted, sizeof(namebuf));
  697. free(a.dotted);
  698. if (a.atype == T_CNAME) { /* CNAME */
  699. i = decode_dotted(packet, a.rdoffset, namebuf, sizeof(namebuf));
  700. free(packet);
  701. if (i < 0)
  702. return 0;
  703. if (++nest > MAX_RECURSE)
  704. return 0;
  705. continue;
  706. } else if (a.atype == T_A) { /* ADDRESS */
  707. memcpy(&in, a.rdata, sizeof(in));
  708. h.h_name = namebuf;
  709. h.h_addrtype = AF_INET;
  710. h.h_length = sizeof(in);
  711. h.h_addr_list = (char **) addr_list;
  712. free(packet);
  713. break;
  714. } else {
  715. free(packet);
  716. return 0;
  717. }
  718. }
  719. return &h;
  720. }
  721. #endif
  722. #ifdef L_gethostbyaddr
  723. struct hostent *gethostbyaddr(const char *addr, int len, int type)
  724. {
  725. static struct hostent h;
  726. static char namebuf[256];
  727. static struct in_addr in;
  728. static struct in_addr *addr_list[2];
  729. unsigned char *packet;
  730. struct resolv_answer a;
  731. int i;
  732. int nest = 0;
  733. if (!addr || (len != sizeof(in)) || (type != AF_INET))
  734. return 0;
  735. memcpy(&in.s_addr, addr, len);
  736. open_nameservers();
  737. memset(&h, 0, sizeof(h));
  738. addr_list[0] = &in;
  739. addr_list[1] = 0;
  740. sprintf(namebuf, "%d.%d.%d.%d.in-addr.arpa",
  741. (in.s_addr >> 24) & 0xff,
  742. (in.s_addr >> 16) & 0xff,
  743. (in.s_addr >> 8) & 0xff, (in.s_addr >> 0) & 0xff);
  744. for (;;) {
  745. i = dns_lookup(namebuf, T_PTR, nameservers, nameserver, &packet, &a);
  746. if (i < 0)
  747. return 0;
  748. strncpy(namebuf, a.dotted, sizeof(namebuf));
  749. free(a.dotted);
  750. if (a.atype == T_CNAME) { /* CNAME */
  751. i = decode_dotted(packet, a.rdoffset, namebuf, sizeof(namebuf));
  752. free(packet);
  753. if (i < 0)
  754. return 0;
  755. if (++nest > MAX_RECURSE)
  756. return 0;
  757. continue;
  758. } else if (a.atype == T_PTR) { /* ADDRESS */
  759. i = decode_dotted(packet, a.rdoffset, namebuf, sizeof(namebuf));
  760. free(packet);
  761. h.h_name = namebuf;
  762. h.h_addrtype = AF_INET;
  763. h.h_length = sizeof(in);
  764. h.h_addr_list = (char **) addr_list;
  765. break;
  766. } else {
  767. free(packet);
  768. return 0;
  769. }
  770. }
  771. return &h;
  772. }
  773. #endif