resolv.c 16 KB

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