resolv.c 24 KB

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