resolv.c 16 KB

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