resolv.c 19 KB

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