resolv.c 19 KB

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