PageRenderTime 56ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/source/bionic/libc/netbsd/resolv/gethnamaddr.c

https://github.com/SherifEldeeb/meterpreter
C | 1211 lines | 1015 code | 99 blank | 97 comment | 290 complexity | 058166cffd79df568099ff66bb209c11 MD5 | raw file
Possible License(s): ISC
  1. /* $NetBSD: gethnamaddr.c,v 1.70 2006/03/22 00:03:51 christos Exp $ */
  2. /*
  3. * ++Copyright++ 1985, 1988, 1993
  4. * -
  5. * Copyright (c) 1985, 1988, 1993
  6. * The Regents of the University of California. All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. * 3. Neither the name of the University nor the names of its contributors
  17. * may be used to endorse or promote products derived from this software
  18. * without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  21. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  24. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. * -
  32. * Portions Copyright (c) 1993 by Digital Equipment Corporation.
  33. *
  34. * Permission to use, copy, modify, and distribute this software for any
  35. * purpose with or without fee is hereby granted, provided that the above
  36. * copyright notice and this permission notice appear in all copies, and that
  37. * the name of Digital Equipment Corporation not be used in advertising or
  38. * publicity pertaining to distribution of the document or software without
  39. * specific, written prior permission.
  40. *
  41. * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  42. * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
  43. * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
  44. * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  45. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  46. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  47. * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  48. * SOFTWARE.
  49. * -
  50. * --Copyright--
  51. */
  52. #include <sys/cdefs.h>
  53. #include <sys/types.h>
  54. #include <sys/param.h>
  55. #include <sys/socket.h>
  56. #include <netinet/in.h>
  57. #include <arpa/inet.h>
  58. #include "arpa_nameser.h"
  59. #include "resolv_private.h"
  60. #include "private/resolv_private.h"
  61. #include "resolv_cache.h"
  62. #include <assert.h>
  63. #include <ctype.h>
  64. #include <errno.h>
  65. #include <netdb.h>
  66. #include <stdarg.h>
  67. #include <stdio.h>
  68. #include <syslog.h>
  69. #ifndef LOG_AUTH
  70. # define LOG_AUTH 0
  71. #endif
  72. #define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
  73. #include "nsswitch.h"
  74. #include <stdlib.h>
  75. #include <string.h>
  76. static const char const AskedForGot[] =
  77. "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
  78. #define MAXPACKET (64*1024)
  79. typedef union {
  80. HEADER hdr;
  81. u_char buf[MAXPACKET];
  82. } querybuf;
  83. typedef union {
  84. int32_t al;
  85. char ac;
  86. } align;
  87. #ifdef DEBUG
  88. static void dprintf(const char *, res_state, ...)
  89. __attribute__((__format__(__printf__, 1, 3)));
  90. #endif
  91. static struct hostent *getanswer(const querybuf *, int, const char *, int,
  92. res_state);
  93. static void map_v4v6_address(const char *, char *);
  94. static void map_v4v6_hostent(struct hostent *, char **, char *);
  95. static void addrsort(char **, int, res_state);
  96. void _sethtent(int);
  97. void _endhtent(void);
  98. struct hostent *_gethtent(void);
  99. void ht_sethostent(int);
  100. void ht_endhostent(void);
  101. struct hostent *ht_gethostbyname(char *);
  102. struct hostent *ht_gethostbyaddr(const char *, int, int);
  103. void dns_service(void);
  104. #undef dn_skipname
  105. int dn_skipname(const u_char *, const u_char *);
  106. int _gethtbyaddr(void *, void *, va_list);
  107. int _gethtbyname(void *, void *, va_list);
  108. struct hostent *_gethtbyname2(const char *, int);
  109. int _dns_gethtbyaddr(void *, void *, va_list);
  110. int _dns_gethtbyname(void *, void *, va_list);
  111. static struct hostent *gethostbyname_internal(const char *, int, res_state);
  112. static const ns_src default_dns_files[] = {
  113. { NSSRC_FILES, NS_SUCCESS },
  114. { NSSRC_DNS, NS_SUCCESS },
  115. { 0, 0 }
  116. };
  117. #ifdef DEBUG
  118. static void
  119. dprintf(const char *msg, res_state res, ...)
  120. {
  121. assert(msg != NULL);
  122. if (res->options & RES_DEBUG) {
  123. int save = errno;
  124. va_list ap;
  125. va_start (ap, res);
  126. vprintf(msg, ap);
  127. va_end (ap);
  128. errno = save;
  129. }
  130. }
  131. #else
  132. # define dprintf(msg, res, num) ((void)0) /*nada*/
  133. #endif
  134. #define BOUNDED_INCR(x) \
  135. do { \
  136. cp += (x); \
  137. if (cp > eom) { \
  138. h_errno = NO_RECOVERY; \
  139. return NULL; \
  140. } \
  141. } while (/*CONSTCOND*/0)
  142. #define BOUNDS_CHECK(ptr, count) \
  143. do { \
  144. if ((ptr) + (count) > eom) { \
  145. h_errno = NO_RECOVERY; \
  146. return NULL; \
  147. } \
  148. } while (/*CONSTCOND*/0)
  149. static struct hostent *
  150. getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
  151. res_state res)
  152. {
  153. const HEADER *hp;
  154. const u_char *cp;
  155. int n;
  156. const u_char *eom, *erdata;
  157. char *bp, **ap, **hap, *ep;
  158. int type, class, ancount, qdcount;
  159. int haveanswer, had_error;
  160. int toobig = 0;
  161. char tbuf[MAXDNAME];
  162. const char *tname;
  163. int (*name_ok)(const char *);
  164. res_static rs = __res_get_static();
  165. assert(answer != NULL);
  166. assert(qname != NULL);
  167. tname = qname;
  168. rs->host.h_name = NULL;
  169. eom = answer->buf + anslen;
  170. switch (qtype) {
  171. case T_A:
  172. case T_AAAA:
  173. name_ok = res_hnok;
  174. break;
  175. case T_PTR:
  176. name_ok = res_dnok;
  177. break;
  178. default:
  179. return NULL; /* XXX should be abort(); */
  180. }
  181. /*
  182. * find first satisfactory answer
  183. */
  184. hp = &answer->hdr;
  185. ancount = ntohs(hp->ancount);
  186. qdcount = ntohs(hp->qdcount);
  187. bp = rs->hostbuf;
  188. ep = rs->hostbuf + sizeof rs->hostbuf;
  189. cp = answer->buf;
  190. BOUNDED_INCR(HFIXEDSZ);
  191. if (qdcount != 1) {
  192. h_errno = NO_RECOVERY;
  193. return NULL;
  194. }
  195. n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
  196. if ((n < 0) || !(*name_ok)(bp)) {
  197. h_errno = NO_RECOVERY;
  198. return NULL;
  199. }
  200. BOUNDED_INCR(n + QFIXEDSZ);
  201. if (qtype == T_A || qtype == T_AAAA) {
  202. /* res_send() has already verified that the query name is the
  203. * same as the one we sent; this just gets the expanded name
  204. * (i.e., with the succeeding search-domain tacked on).
  205. */
  206. n = strlen(bp) + 1; /* for the \0 */
  207. if (n >= MAXHOSTNAMELEN) {
  208. h_errno = NO_RECOVERY;
  209. return NULL;
  210. }
  211. rs->host.h_name = bp;
  212. bp += n;
  213. /* The qname can be abbreviated, but h_name is now absolute. */
  214. qname = rs->host.h_name;
  215. }
  216. ap = rs->host_aliases;
  217. *ap = NULL;
  218. rs->host.h_aliases = rs->host_aliases;
  219. hap = rs->h_addr_ptrs;
  220. *hap = NULL;
  221. rs->host.h_addr_list = rs->h_addr_ptrs;
  222. haveanswer = 0;
  223. had_error = 0;
  224. while (ancount-- > 0 && cp < eom && !had_error) {
  225. n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
  226. if ((n < 0) || !(*name_ok)(bp)) {
  227. had_error++;
  228. continue;
  229. }
  230. cp += n; /* name */
  231. BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
  232. type = _getshort(cp);
  233. cp += INT16SZ; /* type */
  234. class = _getshort(cp);
  235. cp += INT16SZ + INT32SZ; /* class, TTL */
  236. n = _getshort(cp);
  237. cp += INT16SZ; /* len */
  238. BOUNDS_CHECK(cp, n);
  239. erdata = cp + n;
  240. if (class != C_IN) {
  241. /* XXX - debug? syslog? */
  242. cp += n;
  243. continue; /* XXX - had_error++ ? */
  244. }
  245. if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
  246. if (ap >= &rs->host_aliases[MAXALIASES-1])
  247. continue;
  248. n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
  249. if ((n < 0) || !(*name_ok)(tbuf)) {
  250. had_error++;
  251. continue;
  252. }
  253. cp += n;
  254. if (cp != erdata) {
  255. h_errno = NO_RECOVERY;
  256. return NULL;
  257. }
  258. /* Store alias. */
  259. *ap++ = bp;
  260. n = strlen(bp) + 1; /* for the \0 */
  261. if (n >= MAXHOSTNAMELEN) {
  262. had_error++;
  263. continue;
  264. }
  265. bp += n;
  266. /* Get canonical name. */
  267. n = strlen(tbuf) + 1; /* for the \0 */
  268. if (n > ep - bp || n >= MAXHOSTNAMELEN) {
  269. had_error++;
  270. continue;
  271. }
  272. strlcpy(bp, tbuf, (size_t)(ep - bp));
  273. rs->host.h_name = bp;
  274. bp += n;
  275. continue;
  276. }
  277. if (qtype == T_PTR && type == T_CNAME) {
  278. n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
  279. if (n < 0 || !res_dnok(tbuf)) {
  280. had_error++;
  281. continue;
  282. }
  283. cp += n;
  284. if (cp != erdata) {
  285. h_errno = NO_RECOVERY;
  286. return NULL;
  287. }
  288. /* Get canonical name. */
  289. n = strlen(tbuf) + 1; /* for the \0 */
  290. if (n > ep - bp || n >= MAXHOSTNAMELEN) {
  291. had_error++;
  292. continue;
  293. }
  294. strlcpy(bp, tbuf, (size_t)(ep - bp));
  295. tname = bp;
  296. bp += n;
  297. continue;
  298. }
  299. if (type != qtype) {
  300. if (type != T_KEY && type != T_SIG)
  301. syslog(LOG_NOTICE|LOG_AUTH,
  302. "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
  303. qname, p_class(C_IN), p_type(qtype),
  304. p_type(type));
  305. cp += n;
  306. continue; /* XXX - had_error++ ? */
  307. }
  308. switch (type) {
  309. case T_PTR:
  310. if (strcasecmp(tname, bp) != 0) {
  311. syslog(LOG_NOTICE|LOG_AUTH,
  312. AskedForGot, qname, bp);
  313. cp += n;
  314. continue; /* XXX - had_error++ ? */
  315. }
  316. n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
  317. if ((n < 0) || !res_hnok(bp)) {
  318. had_error++;
  319. break;
  320. }
  321. #if MULTI_PTRS_ARE_ALIASES
  322. cp += n;
  323. if (cp != erdata) {
  324. h_errno = NO_RECOVERY;
  325. return NULL;
  326. }
  327. if (!haveanswer)
  328. rs->host.h_name = bp;
  329. else if (ap < &rs->host_aliases[MAXALIASES-1])
  330. *ap++ = bp;
  331. else
  332. n = -1;
  333. if (n != -1) {
  334. n = strlen(bp) + 1; /* for the \0 */
  335. if (n >= MAXHOSTNAMELEN) {
  336. had_error++;
  337. break;
  338. }
  339. bp += n;
  340. }
  341. break;
  342. #else
  343. rs->host.h_name = bp;
  344. if (res->options & RES_USE_INET6) {
  345. n = strlen(bp) + 1; /* for the \0 */
  346. if (n >= MAXHOSTNAMELEN) {
  347. had_error++;
  348. break;
  349. }
  350. bp += n;
  351. map_v4v6_hostent(&rs->host, &bp, ep);
  352. }
  353. h_errno = NETDB_SUCCESS;
  354. return &rs->host;
  355. #endif
  356. case T_A:
  357. case T_AAAA:
  358. if (strcasecmp(rs->host.h_name, bp) != 0) {
  359. syslog(LOG_NOTICE|LOG_AUTH,
  360. AskedForGot, rs->host.h_name, bp);
  361. cp += n;
  362. continue; /* XXX - had_error++ ? */
  363. }
  364. if (n != rs->host.h_length) {
  365. cp += n;
  366. continue;
  367. }
  368. if (type == T_AAAA) {
  369. struct in6_addr in6;
  370. memcpy(&in6, cp, IN6ADDRSZ);
  371. if (IN6_IS_ADDR_V4MAPPED(&in6)) {
  372. cp += n;
  373. continue;
  374. }
  375. }
  376. if (!haveanswer) {
  377. int nn;
  378. rs->host.h_name = bp;
  379. nn = strlen(bp) + 1; /* for the \0 */
  380. bp += nn;
  381. }
  382. bp += sizeof(align) -
  383. (size_t)((u_long)bp % sizeof(align));
  384. if (bp + n >= &rs->hostbuf[sizeof rs->hostbuf]) {
  385. dprintf("size (%d) too big\n", res, n);
  386. had_error++;
  387. continue;
  388. }
  389. if (hap >= &rs->h_addr_ptrs[MAXADDRS-1]) {
  390. if (!toobig++)
  391. dprintf("Too many addresses (%d)\n",
  392. res, MAXADDRS);
  393. cp += n;
  394. continue;
  395. }
  396. (void)memcpy(*hap++ = bp, cp, (size_t)n);
  397. bp += n;
  398. cp += n;
  399. if (cp != erdata) {
  400. h_errno = NO_RECOVERY;
  401. return NULL;
  402. }
  403. break;
  404. default:
  405. abort();
  406. }
  407. if (!had_error)
  408. haveanswer++;
  409. }
  410. if (haveanswer) {
  411. *ap = NULL;
  412. *hap = NULL;
  413. /*
  414. * Note: we sort even if host can take only one address
  415. * in its return structures - should give it the "best"
  416. * address in that case, not some random one
  417. */
  418. if (res->nsort && haveanswer > 1 && qtype == T_A)
  419. addrsort(rs->h_addr_ptrs, haveanswer, res);
  420. if (!rs->host.h_name) {
  421. n = strlen(qname) + 1; /* for the \0 */
  422. if (n > ep - bp || n >= MAXHOSTNAMELEN)
  423. goto no_recovery;
  424. strlcpy(bp, qname, (size_t)(ep - bp));
  425. rs->host.h_name = bp;
  426. bp += n;
  427. }
  428. if (res->options & RES_USE_INET6)
  429. map_v4v6_hostent(&rs->host, &bp, ep);
  430. h_errno = NETDB_SUCCESS;
  431. return &rs->host;
  432. }
  433. no_recovery:
  434. h_errno = NO_RECOVERY;
  435. return NULL;
  436. }
  437. int
  438. gethostbyname_r(const char *name, struct hostent *hp, char *buf, size_t buflen,
  439. struct hostent**result, int *errorp)
  440. {
  441. struct hostent *res;
  442. res = gethostbyname(name);
  443. *errorp = h_errno;
  444. if (res == NULL) {
  445. *result = NULL;
  446. return -1;
  447. }
  448. memcpy(hp, res, sizeof *hp);
  449. *result = hp;
  450. return 0;
  451. }
  452. struct hostent *
  453. gethostbyname(const char *name)
  454. {
  455. struct hostent *hp;
  456. res_state res = __res_get_state();
  457. if (res == NULL)
  458. return NULL;
  459. assert(name != NULL);
  460. if (res->options & RES_USE_INET6) {
  461. hp = gethostbyname_internal(name, AF_INET6, res);
  462. if (hp) {
  463. __res_put_state(res);
  464. return hp;
  465. }
  466. }
  467. hp = gethostbyname_internal(name, AF_INET, res);
  468. __res_put_state(res);
  469. return hp;
  470. }
  471. struct hostent *
  472. gethostbyname2(const char *name, int af)
  473. {
  474. struct hostent *hp;
  475. res_state res = __res_get_state();
  476. if (res == NULL)
  477. return NULL;
  478. hp = gethostbyname_internal(name, af, res);
  479. __res_put_state(res);
  480. return hp;
  481. }
  482. static struct hostent *
  483. gethostbyname_internal(const char *name, int af, res_state res)
  484. {
  485. const char *cp;
  486. char *bp, *ep;
  487. int size;
  488. struct hostent *hp;
  489. struct resolv_cache* cache;
  490. res_static rs = __res_get_static();
  491. static const ns_dtab dtab[] = {
  492. NS_FILES_CB(_gethtbyname, NULL)
  493. { NSSRC_DNS, _dns_gethtbyname, NULL }, /* force -DHESIOD */
  494. { 0, 0, 0 }
  495. };
  496. assert(name != NULL);
  497. switch (af) {
  498. case AF_INET:
  499. size = INADDRSZ;
  500. break;
  501. case AF_INET6:
  502. size = IN6ADDRSZ;
  503. break;
  504. default:
  505. h_errno = NETDB_INTERNAL;
  506. errno = EAFNOSUPPORT;
  507. return NULL;
  508. }
  509. rs->host.h_addrtype = af;
  510. rs->host.h_length = size;
  511. /*
  512. * if there aren't any dots, it could be a user-level alias.
  513. * this is also done in res_nquery() since we are not the only
  514. * function that looks up host names.
  515. */
  516. if (!strchr(name, '.') && (cp = __hostalias(name)))
  517. name = cp;
  518. /*
  519. * disallow names consisting only of digits/dots, unless
  520. * they end in a dot.
  521. */
  522. if (isdigit((u_char) name[0]))
  523. for (cp = name;; ++cp) {
  524. if (!*cp) {
  525. if (*--cp == '.')
  526. break;
  527. /*
  528. * All-numeric, no dot at the end.
  529. * Fake up a hostent as if we'd actually
  530. * done a lookup.
  531. */
  532. if (inet_pton(af, name,
  533. (char *)(void *)rs->host_addr) <= 0) {
  534. h_errno = HOST_NOT_FOUND;
  535. return NULL;
  536. }
  537. strncpy(rs->hostbuf, name, MAXDNAME);
  538. rs->hostbuf[MAXDNAME] = '\0';
  539. bp = rs->hostbuf + MAXDNAME;
  540. ep = rs->hostbuf + sizeof rs->hostbuf;
  541. rs->host.h_name = rs->hostbuf;
  542. rs->host.h_aliases = rs->host_aliases;
  543. rs->host_aliases[0] = NULL;
  544. rs->h_addr_ptrs[0] = (char *)(void *)rs->host_addr;
  545. rs->h_addr_ptrs[1] = NULL;
  546. rs->host.h_addr_list = rs->h_addr_ptrs;
  547. if (res->options & RES_USE_INET6)
  548. map_v4v6_hostent(&rs->host, &bp, ep);
  549. h_errno = NETDB_SUCCESS;
  550. return &rs->host;
  551. }
  552. if (!isdigit((u_char) *cp) && *cp != '.')
  553. break;
  554. }
  555. if ((isxdigit((u_char) name[0]) && strchr(name, ':') != NULL) ||
  556. name[0] == ':')
  557. for (cp = name;; ++cp) {
  558. if (!*cp) {
  559. if (*--cp == '.')
  560. break;
  561. /*
  562. * All-IPv6-legal, no dot at the end.
  563. * Fake up a hostent as if we'd actually
  564. * done a lookup.
  565. */
  566. if (inet_pton(af, name,
  567. (char *)(void *)rs->host_addr) <= 0) {
  568. h_errno = HOST_NOT_FOUND;
  569. return NULL;
  570. }
  571. strncpy(rs->hostbuf, name, MAXDNAME);
  572. rs->hostbuf[MAXDNAME] = '\0';
  573. bp = rs->hostbuf + MAXDNAME;
  574. ep = rs->hostbuf + sizeof rs->hostbuf;
  575. rs->host.h_name = rs->hostbuf;
  576. rs->host.h_aliases = rs->host_aliases;
  577. rs->host_aliases[0] = NULL;
  578. rs->h_addr_ptrs[0] = (char *)(void *)rs->host_addr;
  579. rs->h_addr_ptrs[1] = NULL;
  580. rs->host.h_addr_list = rs->h_addr_ptrs;
  581. h_errno = NETDB_SUCCESS;
  582. return &rs->host;
  583. }
  584. if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.')
  585. break;
  586. }
  587. hp = NULL;
  588. h_errno = NETDB_INTERNAL;
  589. if (nsdispatch(&hp, dtab, NSDB_HOSTS, "gethostbyname",
  590. default_dns_files, name, strlen(name), af) != NS_SUCCESS) {
  591. return NULL;
  592. }
  593. h_errno = NETDB_SUCCESS;
  594. return hp;
  595. }
  596. struct hostent *
  597. gethostbyaddr(const char *addr, /* XXX should have been def'd as u_char! */
  598. socklen_t len, int af)
  599. {
  600. const u_char *uaddr = (const u_char *)addr;
  601. socklen_t size;
  602. struct hostent *hp;
  603. static const ns_dtab dtab[] = {
  604. NS_FILES_CB(_gethtbyaddr, NULL)
  605. { NSSRC_DNS, _dns_gethtbyaddr, NULL }, /* force -DHESIOD */
  606. { 0, 0, 0 }
  607. };
  608. assert(addr != NULL);
  609. if (af == AF_INET6 && len == IN6ADDRSZ &&
  610. (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)(const void *)uaddr) ||
  611. IN6_IS_ADDR_SITELOCAL((const struct in6_addr *)(const void *)uaddr))) {
  612. h_errno = HOST_NOT_FOUND;
  613. return NULL;
  614. }
  615. if (af == AF_INET6 && len == IN6ADDRSZ &&
  616. (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)(const void *)uaddr) ||
  617. IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)(const void *)uaddr))) {
  618. /* Unmap. */
  619. addr += IN6ADDRSZ - INADDRSZ;
  620. uaddr += IN6ADDRSZ - INADDRSZ;
  621. af = AF_INET;
  622. len = INADDRSZ;
  623. }
  624. switch (af) {
  625. case AF_INET:
  626. size = INADDRSZ;
  627. break;
  628. case AF_INET6:
  629. size = IN6ADDRSZ;
  630. break;
  631. default:
  632. errno = EAFNOSUPPORT;
  633. h_errno = NETDB_INTERNAL;
  634. return NULL;
  635. }
  636. if (size != len) {
  637. errno = EINVAL;
  638. h_errno = NETDB_INTERNAL;
  639. return NULL;
  640. }
  641. hp = NULL;
  642. h_errno = NETDB_INTERNAL;
  643. if (nsdispatch(&hp, dtab, NSDB_HOSTS, "gethostbyaddr",
  644. default_dns_files, uaddr, len, af) != NS_SUCCESS)
  645. return NULL;
  646. h_errno = NETDB_SUCCESS;
  647. return hp;
  648. }
  649. void
  650. _sethtent(int f)
  651. {
  652. res_static rs = __res_get_static();
  653. if (rs == NULL) return;
  654. if (!rs->hostf)
  655. rs->hostf = fopen(_PATH_HOSTS, "r" );
  656. else
  657. rewind(rs->hostf);
  658. rs->stayopen = f;
  659. }
  660. void
  661. _endhtent(void)
  662. {
  663. res_static rs = __res_get_static();
  664. if (rs == NULL) return;
  665. if (rs->hostf && !rs->stayopen) {
  666. (void) fclose(rs->hostf);
  667. rs->hostf = NULL;
  668. }
  669. }
  670. struct hostent *
  671. _gethtent(void)
  672. {
  673. char *p;
  674. char *cp, **q;
  675. int af, len;
  676. res_static rs = __res_get_static();
  677. if (!rs->hostf && !(rs->hostf = fopen(_PATH_HOSTS, "r" ))) {
  678. h_errno = NETDB_INTERNAL;
  679. return NULL;
  680. }
  681. again:
  682. if (!(p = fgets(rs->hostbuf, sizeof rs->hostbuf, rs->hostf))) {
  683. h_errno = HOST_NOT_FOUND;
  684. return NULL;
  685. }
  686. if (*p == '#')
  687. goto again;
  688. if (!(cp = strpbrk(p, "#\n")))
  689. goto again;
  690. *cp = '\0';
  691. if (!(cp = strpbrk(p, " \t")))
  692. goto again;
  693. *cp++ = '\0';
  694. if (inet_pton(AF_INET6, p, (char *)(void *)rs->host_addr) > 0) {
  695. af = AF_INET6;
  696. len = IN6ADDRSZ;
  697. } else if (inet_pton(AF_INET, p, (char *)(void *)rs->host_addr) > 0) {
  698. res_state res = __res_get_state();
  699. if (res == NULL)
  700. return NULL;
  701. if (res->options & RES_USE_INET6) {
  702. map_v4v6_address((char *)(void *)rs->host_addr,
  703. (char *)(void *)rs->host_addr);
  704. af = AF_INET6;
  705. len = IN6ADDRSZ;
  706. } else {
  707. af = AF_INET;
  708. len = INADDRSZ;
  709. }
  710. __res_put_state(res);
  711. } else {
  712. goto again;
  713. }
  714. /* if this is not something we're looking for, skip it. */
  715. if (rs->host.h_addrtype != 0 && rs->host.h_addrtype != af)
  716. goto again;
  717. if (rs->host.h_length != 0 && rs->host.h_length != len)
  718. goto again;
  719. rs->h_addr_ptrs[0] = (char *)(void *)rs->host_addr;
  720. rs->h_addr_ptrs[1] = NULL;
  721. rs->host.h_addr_list = rs->h_addr_ptrs;
  722. rs->host.h_length = len;
  723. rs->host.h_addrtype = af;
  724. while (*cp == ' ' || *cp == '\t')
  725. cp++;
  726. rs->host.h_name = cp;
  727. q = rs->host.h_aliases = rs->host_aliases;
  728. if ((cp = strpbrk(cp, " \t")) != NULL)
  729. *cp++ = '\0';
  730. while (cp && *cp) {
  731. if (*cp == ' ' || *cp == '\t') {
  732. cp++;
  733. continue;
  734. }
  735. if (q < &rs->host_aliases[MAXALIASES - 1])
  736. *q++ = cp;
  737. if ((cp = strpbrk(cp, " \t")) != NULL)
  738. *cp++ = '\0';
  739. }
  740. *q = NULL;
  741. h_errno = NETDB_SUCCESS;
  742. return &rs->host;
  743. }
  744. /*ARGSUSED*/
  745. int
  746. _gethtbyname(void *rv, void *cb_data, va_list ap)
  747. {
  748. struct hostent *hp;
  749. const char *name;
  750. int af;
  751. assert(rv != NULL);
  752. name = va_arg(ap, char *);
  753. /* NOSTRICT skip len */(void)va_arg(ap, int);
  754. af = va_arg(ap, int);
  755. hp = NULL;
  756. #if 0
  757. {
  758. res_state res = __res_get_state();
  759. if (res == NULL)
  760. return NS_NOTFOUND;
  761. if (res->options & RES_USE_INET6)
  762. hp = _gethtbyname2(name, AF_INET6);
  763. if (hp==NULL)
  764. hp = _gethtbyname2(name, AF_INET);
  765. __res_put_state(res);
  766. }
  767. #else
  768. hp = _gethtbyname2(name, af);
  769. #endif
  770. *((struct hostent **)rv) = hp;
  771. if (hp == NULL) {
  772. h_errno = HOST_NOT_FOUND;
  773. return NS_NOTFOUND;
  774. }
  775. return NS_SUCCESS;
  776. }
  777. struct hostent *
  778. _gethtbyname2(const char *name, int af)
  779. {
  780. struct hostent *p;
  781. char *tmpbuf, *ptr, **cp;
  782. int num;
  783. size_t len;
  784. res_static rs = __res_get_static();
  785. assert(name != NULL);
  786. _sethtent(rs->stayopen);
  787. ptr = tmpbuf = NULL;
  788. num = 0;
  789. while ((p = _gethtent()) != NULL && num < MAXADDRS) {
  790. if (p->h_addrtype != af)
  791. continue;
  792. if (strcasecmp(p->h_name, name) != 0) {
  793. for (cp = p->h_aliases; *cp != NULL; cp++)
  794. if (strcasecmp(*cp, name) == 0)
  795. break;
  796. if (*cp == NULL) continue;
  797. }
  798. if (num == 0) {
  799. size_t bufsize;
  800. char *src;
  801. bufsize = strlen(p->h_name) + 2 +
  802. MAXADDRS * p->h_length +
  803. ALIGNBYTES;
  804. for (cp = p->h_aliases; *cp != NULL; cp++)
  805. bufsize += strlen(*cp) + 1;
  806. if ((tmpbuf = malloc(bufsize)) == NULL) {
  807. h_errno = NETDB_INTERNAL;
  808. return NULL;
  809. }
  810. ptr = tmpbuf;
  811. src = p->h_name;
  812. while ((*ptr++ = *src++) != '\0');
  813. for (cp = p->h_aliases; *cp != NULL; cp++) {
  814. src = *cp;
  815. while ((*ptr++ = *src++) != '\0');
  816. }
  817. *ptr++ = '\0';
  818. ptr = (char *)(void *)ALIGN(ptr);
  819. }
  820. (void)memcpy(ptr, p->h_addr_list[0], (size_t)p->h_length);
  821. ptr += p->h_length;
  822. num++;
  823. }
  824. _endhtent();
  825. if (num == 0) return NULL;
  826. len = ptr - tmpbuf;
  827. if (len > (sizeof(rs->hostbuf) - ALIGNBYTES)) {
  828. free(tmpbuf);
  829. errno = ENOSPC;
  830. h_errno = NETDB_INTERNAL;
  831. return NULL;
  832. }
  833. ptr = memcpy((void *)ALIGN(rs->hostbuf), tmpbuf, len);
  834. free(tmpbuf);
  835. rs->host.h_name = ptr;
  836. while (*ptr++);
  837. cp = rs->host_aliases;
  838. while (*ptr) {
  839. *cp++ = ptr;
  840. while (*ptr++);
  841. }
  842. ptr++;
  843. *cp = NULL;
  844. ptr = (char *)(void *)ALIGN(ptr);
  845. cp = rs->h_addr_ptrs;
  846. while (num--) {
  847. *cp++ = ptr;
  848. ptr += rs->host.h_length;
  849. }
  850. *cp = NULL;
  851. return &rs->host;
  852. }
  853. /*ARGSUSED*/
  854. int
  855. _gethtbyaddr(void *rv, void *cb_data, va_list ap)
  856. {
  857. struct hostent *p;
  858. const unsigned char *addr;
  859. int len, af;
  860. res_static rs = __res_get_static();
  861. assert(rv != NULL);
  862. addr = va_arg(ap, unsigned char *);
  863. len = va_arg(ap, int);
  864. af = va_arg(ap, int);
  865. rs->host.h_length = len;
  866. rs->host.h_addrtype = af;
  867. _sethtent(rs->stayopen);
  868. while ((p = _gethtent()) != NULL)
  869. if (p->h_addrtype == af && !memcmp(p->h_addr, addr,
  870. (size_t)len))
  871. break;
  872. _endhtent();
  873. *((struct hostent **)rv) = p;
  874. if (p==NULL) {
  875. h_errno = HOST_NOT_FOUND;
  876. return NS_NOTFOUND;
  877. }
  878. return NS_SUCCESS;
  879. }
  880. static void
  881. map_v4v6_address(const char *src, char *dst)
  882. {
  883. u_char *p = (u_char *)dst;
  884. char tmp[INADDRSZ];
  885. int i;
  886. assert(src != NULL);
  887. assert(dst != NULL);
  888. /* Stash a temporary copy so our caller can update in place. */
  889. (void)memcpy(tmp, src, INADDRSZ);
  890. /* Mark this ipv6 addr as a mapped ipv4. */
  891. for (i = 0; i < 10; i++)
  892. *p++ = 0x00;
  893. *p++ = 0xff;
  894. *p++ = 0xff;
  895. /* Retrieve the saved copy and we're done. */
  896. (void)memcpy((void *)p, tmp, INADDRSZ);
  897. }
  898. static void
  899. map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep)
  900. {
  901. char **ap;
  902. assert(hp != NULL);
  903. assert(bpp != NULL);
  904. assert(ep != NULL);
  905. if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
  906. return;
  907. hp->h_addrtype = AF_INET6;
  908. hp->h_length = IN6ADDRSZ;
  909. for (ap = hp->h_addr_list; *ap; ap++) {
  910. int i = sizeof(align) - (size_t)((u_long)*bpp % sizeof(align));
  911. if (ep - *bpp < (i + IN6ADDRSZ)) {
  912. /* Out of memory. Truncate address list here. XXX */
  913. *ap = NULL;
  914. return;
  915. }
  916. *bpp += i;
  917. map_v4v6_address(*ap, *bpp);
  918. *ap = *bpp;
  919. *bpp += IN6ADDRSZ;
  920. }
  921. }
  922. static void
  923. addrsort(char **ap, int num, res_state res)
  924. {
  925. int i, j;
  926. char **p;
  927. short aval[MAXADDRS];
  928. int needsort = 0;
  929. assert(ap != NULL);
  930. p = ap;
  931. for (i = 0; i < num; i++, p++) {
  932. for (j = 0 ; (unsigned)j < res->nsort; j++)
  933. if (res->sort_list[j].addr.s_addr ==
  934. (((struct in_addr *)(void *)(*p))->s_addr &
  935. res->sort_list[j].mask))
  936. break;
  937. aval[i] = j;
  938. if (needsort == 0 && i > 0 && j < aval[i-1])
  939. needsort = i;
  940. }
  941. if (!needsort)
  942. return;
  943. while (needsort < num) {
  944. for (j = needsort - 1; j >= 0; j--) {
  945. if (aval[j] > aval[j+1]) {
  946. char *hp;
  947. i = aval[j];
  948. aval[j] = aval[j+1];
  949. aval[j+1] = i;
  950. hp = ap[j];
  951. ap[j] = ap[j+1];
  952. ap[j+1] = hp;
  953. } else
  954. break;
  955. }
  956. needsort++;
  957. }
  958. }
  959. struct hostent *
  960. gethostent(void)
  961. {
  962. res_static rs = __res_get_static();
  963. rs->host.h_addrtype = 0;
  964. rs->host.h_length = 0;
  965. return _gethtent();
  966. }
  967. /*ARGSUSED*/
  968. int
  969. _dns_gethtbyname(void *rv, void *cb_data, va_list ap)
  970. {
  971. querybuf *buf;
  972. int n, type;
  973. struct hostent *hp;
  974. const char *name;
  975. int af;
  976. res_state res;
  977. assert(rv != NULL);
  978. name = va_arg(ap, char *);
  979. /* NOSTRICT skip len */(void)va_arg(ap, int);
  980. af = va_arg(ap, int);
  981. switch (af) {
  982. case AF_INET:
  983. type = T_A;
  984. break;
  985. case AF_INET6:
  986. type = T_AAAA;
  987. break;
  988. default:
  989. return NS_UNAVAIL;
  990. }
  991. buf = malloc(sizeof(*buf));
  992. if (buf == NULL) {
  993. h_errno = NETDB_INTERNAL;
  994. return NS_NOTFOUND;
  995. }
  996. res = __res_get_state();
  997. if (res == NULL) {
  998. free(buf);
  999. return NS_NOTFOUND;
  1000. }
  1001. n = res_nsearch(res, name, C_IN, type, buf->buf, sizeof(buf->buf));
  1002. if (n < 0) {
  1003. free(buf);
  1004. dprintf("res_nsearch failed (%d)\n", res, n);
  1005. __res_put_state(res);
  1006. return NS_NOTFOUND;
  1007. }
  1008. hp = getanswer(buf, n, name, type, res);
  1009. free(buf);
  1010. __res_put_state(res);
  1011. if (hp == NULL)
  1012. switch (h_errno) {
  1013. case HOST_NOT_FOUND:
  1014. return NS_NOTFOUND;
  1015. case TRY_AGAIN:
  1016. return NS_TRYAGAIN;
  1017. default:
  1018. return NS_UNAVAIL;
  1019. }
  1020. *((struct hostent **)rv) = hp;
  1021. return NS_SUCCESS;
  1022. }
  1023. /*ARGSUSED*/
  1024. int
  1025. _dns_gethtbyaddr(void *rv, void *cb_data, va_list ap)
  1026. {
  1027. char qbuf[MAXDNAME + 1], *qp, *ep;
  1028. int n;
  1029. querybuf *buf;
  1030. struct hostent *hp;
  1031. const unsigned char *uaddr;
  1032. int len, af, advance;
  1033. res_state res;
  1034. res_static rs = __res_get_static();
  1035. assert(rv != NULL);
  1036. uaddr = va_arg(ap, unsigned char *);
  1037. len = va_arg(ap, int);
  1038. af = va_arg(ap, int);
  1039. switch (af) {
  1040. case AF_INET:
  1041. (void)snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa",
  1042. (uaddr[3] & 0xff), (uaddr[2] & 0xff),
  1043. (uaddr[1] & 0xff), (uaddr[0] & 0xff));
  1044. break;
  1045. case AF_INET6:
  1046. qp = qbuf;
  1047. ep = qbuf + sizeof(qbuf) - 1;
  1048. for (n = IN6ADDRSZ - 1; n >= 0; n--) {
  1049. advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.",
  1050. uaddr[n] & 0xf,
  1051. ((unsigned int)uaddr[n] >> 4) & 0xf);
  1052. if (advance > 0 && qp + advance < ep)
  1053. qp += advance;
  1054. else {
  1055. h_errno = NETDB_INTERNAL;
  1056. return NS_NOTFOUND;
  1057. }
  1058. }
  1059. if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf)) {
  1060. h_errno = NETDB_INTERNAL;
  1061. return NS_NOTFOUND;
  1062. }
  1063. break;
  1064. default:
  1065. abort();
  1066. }
  1067. buf = malloc(sizeof(*buf));
  1068. if (buf == NULL) {
  1069. h_errno = NETDB_INTERNAL;
  1070. return NS_NOTFOUND;
  1071. }
  1072. res = __res_get_state();
  1073. if (res == NULL) {
  1074. free(buf);
  1075. return NS_NOTFOUND;
  1076. }
  1077. n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, sizeof(buf->buf));
  1078. if (n < 0) {
  1079. free(buf);
  1080. dprintf("res_nquery failed (%d)\n", res, n);
  1081. __res_put_state(res);
  1082. return NS_NOTFOUND;
  1083. }
  1084. hp = getanswer(buf, n, qbuf, T_PTR, res);
  1085. free(buf);
  1086. if (hp == NULL) {
  1087. __res_put_state(res);
  1088. switch (h_errno) {
  1089. case HOST_NOT_FOUND:
  1090. return NS_NOTFOUND;
  1091. case TRY_AGAIN:
  1092. return NS_TRYAGAIN;
  1093. default:
  1094. return NS_UNAVAIL;
  1095. }
  1096. }
  1097. hp->h_addrtype = af;
  1098. hp->h_length = len;
  1099. (void)memcpy(rs->host_addr, uaddr, (size_t)len);
  1100. rs->h_addr_ptrs[0] = (char *)(void *)rs->host_addr;
  1101. rs->h_addr_ptrs[1] = NULL;
  1102. if (af == AF_INET && (res->options & RES_USE_INET6)) {
  1103. map_v4v6_address((char *)(void *)rs->host_addr,
  1104. (char *)(void *)rs->host_addr);
  1105. hp->h_addrtype = AF_INET6;
  1106. hp->h_length = IN6ADDRSZ;
  1107. }
  1108. __res_put_state(res);
  1109. *((struct hostent **)rv) = hp;
  1110. h_errno = NETDB_SUCCESS;
  1111. return NS_SUCCESS;
  1112. }