PageRenderTime 55ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/libc/netbsd/gethnamaddr.c

https://github.com/AndroDevLinux/android_bionic
C | 1408 lines | 1168 code | 136 blank | 104 comment | 351 complexity | 7ffee492293201c54d03e58d5a729ee8 MD5 | raw file
  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 <sys/un.h>
  57. #include <netinet/in.h>
  58. #include <arpa/inet.h>
  59. #include "arpa_nameser.h"
  60. #include "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 <strings.h>
  69. #include <syslog.h>
  70. #include <unistd.h>
  71. #ifndef LOG_AUTH
  72. # define LOG_AUTH 0
  73. #endif
  74. #define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
  75. #include "nsswitch.h"
  76. #include <stdlib.h>
  77. #include <string.h>
  78. // This should be synchronized to ResponseCode.h
  79. static const int DnsProxyQueryResult = 222;
  80. static const char const AskedForGot[] =
  81. "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
  82. #define MAXPACKET (64*1024)
  83. typedef union {
  84. HEADER hdr;
  85. u_char buf[MAXPACKET];
  86. } querybuf;
  87. typedef union {
  88. int32_t al;
  89. char ac;
  90. } align;
  91. #ifdef DEBUG
  92. static void dprintf(const char *, res_state, ...)
  93. __attribute__((__format__(__printf__, 1, 3)));
  94. #endif
  95. static struct hostent *getanswer(const querybuf *, int, const char *, int,
  96. res_state);
  97. static void map_v4v6_address(const char *, char *);
  98. static void map_v4v6_hostent(struct hostent *, char **, char *);
  99. static void addrsort(char **, int, res_state);
  100. static void _sethtent(int);
  101. static void _endhtent(void);
  102. static struct hostent *_gethtent(void);
  103. void ht_sethostent(int);
  104. void ht_endhostent(void);
  105. struct hostent *ht_gethostbyname(char *);
  106. struct hostent *ht_gethostbyaddr(const char *, int, int);
  107. void dns_service(void);
  108. #undef dn_skipname
  109. int dn_skipname(const u_char *, const u_char *);
  110. static int _gethtbyaddr(void *, void *, va_list);
  111. static int _gethtbyname(void *, void *, va_list);
  112. static struct hostent *_gethtbyname2(const char *, int);
  113. static int _dns_gethtbyaddr(void *, void *, va_list);
  114. static int _dns_gethtbyname(void *, void *, va_list);
  115. static struct hostent *gethostbyname_internal(const char *, int, res_state, const char *, int);
  116. static const ns_src default_dns_files[] = {
  117. { NSSRC_FILES, NS_SUCCESS },
  118. { NSSRC_DNS, NS_SUCCESS },
  119. { 0, 0 }
  120. };
  121. #ifdef DEBUG
  122. static void
  123. dprintf(const char *msg, res_state res, ...)
  124. {
  125. assert(msg != NULL);
  126. if (res->options & RES_DEBUG) {
  127. int save = errno;
  128. va_list ap;
  129. va_start (ap, res);
  130. vprintf(msg, ap);
  131. va_end (ap);
  132. errno = save;
  133. }
  134. }
  135. #else
  136. # define dprintf(msg, res, num) ((void)0) /*nada*/
  137. #endif
  138. #define BOUNDED_INCR(x) \
  139. do { \
  140. cp += (x); \
  141. if (cp > eom) { \
  142. h_errno = NO_RECOVERY; \
  143. return NULL; \
  144. } \
  145. } while (/*CONSTCOND*/0)
  146. #define BOUNDS_CHECK(ptr, count) \
  147. do { \
  148. if ((ptr) + (count) > eom) { \
  149. h_errno = NO_RECOVERY; \
  150. return NULL; \
  151. } \
  152. } while (/*CONSTCOND*/0)
  153. static struct hostent *
  154. getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
  155. res_state res)
  156. {
  157. const HEADER *hp;
  158. const u_char *cp;
  159. int n;
  160. const u_char *eom, *erdata;
  161. char *bp, **ap, **hap, *ep;
  162. int type, class, ancount, qdcount;
  163. int haveanswer, had_error;
  164. int toobig = 0;
  165. char tbuf[MAXDNAME];
  166. const char *tname;
  167. int (*name_ok)(const char *);
  168. res_static rs = __res_get_static();
  169. assert(answer != NULL);
  170. assert(qname != NULL);
  171. tname = qname;
  172. rs->host.h_name = NULL;
  173. eom = answer->buf + anslen;
  174. switch (qtype) {
  175. case T_A:
  176. case T_AAAA:
  177. name_ok = res_hnok;
  178. break;
  179. case T_PTR:
  180. name_ok = res_dnok;
  181. break;
  182. default:
  183. return NULL; /* XXX should be abort(); */
  184. }
  185. /*
  186. * find first satisfactory answer
  187. */
  188. hp = &answer->hdr;
  189. ancount = ntohs(hp->ancount);
  190. qdcount = ntohs(hp->qdcount);
  191. bp = rs->hostbuf;
  192. ep = rs->hostbuf + sizeof rs->hostbuf;
  193. cp = answer->buf;
  194. BOUNDED_INCR(HFIXEDSZ);
  195. if (qdcount != 1) {
  196. h_errno = NO_RECOVERY;
  197. return NULL;
  198. }
  199. n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
  200. if ((n < 0) || !(*name_ok)(bp)) {
  201. h_errno = NO_RECOVERY;
  202. return NULL;
  203. }
  204. BOUNDED_INCR(n + QFIXEDSZ);
  205. if (qtype == T_A || qtype == T_AAAA) {
  206. /* res_send() has already verified that the query name is the
  207. * same as the one we sent; this just gets the expanded name
  208. * (i.e., with the succeeding search-domain tacked on).
  209. */
  210. n = strlen(bp) + 1; /* for the \0 */
  211. if (n >= MAXHOSTNAMELEN) {
  212. h_errno = NO_RECOVERY;
  213. return NULL;
  214. }
  215. rs->host.h_name = bp;
  216. bp += n;
  217. /* The qname can be abbreviated, but h_name is now absolute. */
  218. qname = rs->host.h_name;
  219. }
  220. ap = rs->host_aliases;
  221. *ap = NULL;
  222. rs->host.h_aliases = rs->host_aliases;
  223. hap = rs->h_addr_ptrs;
  224. *hap = NULL;
  225. rs->host.h_addr_list = rs->h_addr_ptrs;
  226. haveanswer = 0;
  227. had_error = 0;
  228. while (ancount-- > 0 && cp < eom && !had_error) {
  229. n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
  230. if ((n < 0) || !(*name_ok)(bp)) {
  231. had_error++;
  232. continue;
  233. }
  234. cp += n; /* name */
  235. BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
  236. type = _getshort(cp);
  237. cp += INT16SZ; /* type */
  238. class = _getshort(cp);
  239. cp += INT16SZ + INT32SZ; /* class, TTL */
  240. n = _getshort(cp);
  241. cp += INT16SZ; /* len */
  242. BOUNDS_CHECK(cp, n);
  243. erdata = cp + n;
  244. if (class != C_IN) {
  245. /* XXX - debug? syslog? */
  246. cp += n;
  247. continue; /* XXX - had_error++ ? */
  248. }
  249. if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
  250. if (ap >= &rs->host_aliases[MAXALIASES-1])
  251. continue;
  252. n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
  253. if ((n < 0) || !(*name_ok)(tbuf)) {
  254. had_error++;
  255. continue;
  256. }
  257. cp += n;
  258. if (cp != erdata) {
  259. h_errno = NO_RECOVERY;
  260. return NULL;
  261. }
  262. /* Store alias. */
  263. *ap++ = bp;
  264. n = strlen(bp) + 1; /* for the \0 */
  265. if (n >= MAXHOSTNAMELEN) {
  266. had_error++;
  267. continue;
  268. }
  269. bp += n;
  270. /* Get canonical name. */
  271. n = strlen(tbuf) + 1; /* for the \0 */
  272. if (n > ep - bp || n >= MAXHOSTNAMELEN) {
  273. had_error++;
  274. continue;
  275. }
  276. strlcpy(bp, tbuf, (size_t)(ep - bp));
  277. rs->host.h_name = bp;
  278. bp += n;
  279. continue;
  280. }
  281. if (qtype == T_PTR && type == T_CNAME) {
  282. n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
  283. if (n < 0 || !res_dnok(tbuf)) {
  284. had_error++;
  285. continue;
  286. }
  287. cp += n;
  288. if (cp != erdata) {
  289. h_errno = NO_RECOVERY;
  290. return NULL;
  291. }
  292. /* Get canonical name. */
  293. n = strlen(tbuf) + 1; /* for the \0 */
  294. if (n > ep - bp || n >= MAXHOSTNAMELEN) {
  295. had_error++;
  296. continue;
  297. }
  298. strlcpy(bp, tbuf, (size_t)(ep - bp));
  299. tname = bp;
  300. bp += n;
  301. continue;
  302. }
  303. if (type != qtype) {
  304. if (type != T_KEY && type != T_SIG)
  305. syslog(LOG_NOTICE|LOG_AUTH,
  306. "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
  307. qname, p_class(C_IN), p_type(qtype),
  308. p_type(type));
  309. cp += n;
  310. continue; /* XXX - had_error++ ? */
  311. }
  312. switch (type) {
  313. case T_PTR:
  314. if (strcasecmp(tname, bp) != 0) {
  315. syslog(LOG_NOTICE|LOG_AUTH,
  316. AskedForGot, qname, bp);
  317. cp += n;
  318. continue; /* XXX - had_error++ ? */
  319. }
  320. n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
  321. if ((n < 0) || !res_hnok(bp)) {
  322. had_error++;
  323. break;
  324. }
  325. #if MULTI_PTRS_ARE_ALIASES
  326. cp += n;
  327. if (cp != erdata) {
  328. h_errno = NO_RECOVERY;
  329. return NULL;
  330. }
  331. if (!haveanswer)
  332. rs->host.h_name = bp;
  333. else if (ap < &rs->host_aliases[MAXALIASES-1])
  334. *ap++ = bp;
  335. else
  336. n = -1;
  337. if (n != -1) {
  338. n = strlen(bp) + 1; /* for the \0 */
  339. if (n >= MAXHOSTNAMELEN) {
  340. had_error++;
  341. break;
  342. }
  343. bp += n;
  344. }
  345. break;
  346. #else
  347. rs->host.h_name = bp;
  348. if (res->options & RES_USE_INET6) {
  349. n = strlen(bp) + 1; /* for the \0 */
  350. if (n >= MAXHOSTNAMELEN) {
  351. had_error++;
  352. break;
  353. }
  354. bp += n;
  355. map_v4v6_hostent(&rs->host, &bp, ep);
  356. }
  357. h_errno = NETDB_SUCCESS;
  358. return &rs->host;
  359. #endif
  360. case T_A:
  361. case T_AAAA:
  362. if (strcasecmp(rs->host.h_name, bp) != 0) {
  363. syslog(LOG_NOTICE|LOG_AUTH,
  364. AskedForGot, rs->host.h_name, bp);
  365. cp += n;
  366. continue; /* XXX - had_error++ ? */
  367. }
  368. if (n != rs->host.h_length) {
  369. cp += n;
  370. continue;
  371. }
  372. if (type == T_AAAA) {
  373. struct in6_addr in6;
  374. memcpy(&in6, cp, IN6ADDRSZ);
  375. if (IN6_IS_ADDR_V4MAPPED(&in6)) {
  376. cp += n;
  377. continue;
  378. }
  379. }
  380. if (!haveanswer) {
  381. int nn;
  382. rs->host.h_name = bp;
  383. nn = strlen(bp) + 1; /* for the \0 */
  384. bp += nn;
  385. }
  386. bp += sizeof(align) -
  387. (size_t)((u_long)bp % sizeof(align));
  388. if (bp + n >= &rs->hostbuf[sizeof rs->hostbuf]) {
  389. dprintf("size (%d) too big\n", res, n);
  390. had_error++;
  391. continue;
  392. }
  393. if (hap >= &rs->h_addr_ptrs[MAXADDRS-1]) {
  394. if (!toobig++)
  395. dprintf("Too many addresses (%d)\n",
  396. res, MAXADDRS);
  397. cp += n;
  398. continue;
  399. }
  400. (void)memcpy(*hap++ = bp, cp, (size_t)n);
  401. bp += n;
  402. cp += n;
  403. if (cp != erdata) {
  404. h_errno = NO_RECOVERY;
  405. return NULL;
  406. }
  407. break;
  408. default:
  409. abort();
  410. }
  411. if (!had_error)
  412. haveanswer++;
  413. }
  414. if (haveanswer) {
  415. *ap = NULL;
  416. *hap = NULL;
  417. /*
  418. * Note: we sort even if host can take only one address
  419. * in its return structures - should give it the "best"
  420. * address in that case, not some random one
  421. */
  422. if (res->nsort && haveanswer > 1 && qtype == T_A)
  423. addrsort(rs->h_addr_ptrs, haveanswer, res);
  424. if (!rs->host.h_name) {
  425. n = strlen(qname) + 1; /* for the \0 */
  426. if (n > ep - bp || n >= MAXHOSTNAMELEN)
  427. goto no_recovery;
  428. strlcpy(bp, qname, (size_t)(ep - bp));
  429. rs->host.h_name = bp;
  430. bp += n;
  431. }
  432. if (res->options & RES_USE_INET6)
  433. map_v4v6_hostent(&rs->host, &bp, ep);
  434. h_errno = NETDB_SUCCESS;
  435. return &rs->host;
  436. }
  437. no_recovery:
  438. h_errno = NO_RECOVERY;
  439. return NULL;
  440. }
  441. int
  442. gethostbyname_r(const char *name, struct hostent *hp, char *buf, size_t buflen,
  443. struct hostent**result, int *errorp)
  444. {
  445. struct hostent *res;
  446. res = gethostbyname(name);
  447. *errorp = h_errno;
  448. if (res == NULL) {
  449. *result = NULL;
  450. return -1;
  451. }
  452. memcpy(hp, res, sizeof *hp);
  453. *result = hp;
  454. return 0;
  455. }
  456. struct hostent *
  457. gethostbyname(const char *name)
  458. {
  459. struct hostent *hp;
  460. res_state res = __res_get_state();
  461. if (res == NULL)
  462. return NULL;
  463. assert(name != NULL);
  464. /* try IPv6 first - if that fails do IPv4 */
  465. if (res->options & RES_USE_INET6) {
  466. hp = gethostbyname_internal(name, AF_INET6, res, NULL, 0);
  467. if (hp) {
  468. __res_put_state(res);
  469. return hp;
  470. }
  471. }
  472. hp = gethostbyname_internal(name, AF_INET, res, NULL, 0);
  473. __res_put_state(res);
  474. return hp;
  475. }
  476. struct hostent *
  477. gethostbyname2(const char *name, int af)
  478. {
  479. return android_gethostbynameforiface(name, af, NULL, 0);
  480. }
  481. struct hostent *
  482. android_gethostbynameforiface(const char *name, int af, const char *iface, int mark)
  483. {
  484. struct hostent *hp;
  485. res_state res = __res_get_state();
  486. if (res == NULL)
  487. return NULL;
  488. hp = gethostbyname_internal(name, af, res, iface, mark);
  489. __res_put_state(res);
  490. return hp;
  491. }
  492. static FILE* android_open_proxy()
  493. {
  494. int sock;
  495. const int one = 1;
  496. struct sockaddr_un proxy_addr;
  497. sock = socket(AF_UNIX, SOCK_STREAM, 0);
  498. if (sock < 0) {
  499. return NULL;
  500. }
  501. setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
  502. memset(&proxy_addr, 0, sizeof(proxy_addr));
  503. proxy_addr.sun_family = AF_UNIX;
  504. strlcpy(proxy_addr.sun_path, "/dev/socket/dnsproxyd", sizeof(proxy_addr.sun_path));
  505. if (TEMP_FAILURE_RETRY(connect(sock,
  506. (const struct sockaddr*) &proxy_addr,
  507. sizeof(proxy_addr))) != 0) {
  508. close(sock);
  509. return NULL;
  510. }
  511. return fdopen(sock, "r+");
  512. }
  513. static struct hostent *
  514. android_read_hostent(FILE* proxy)
  515. {
  516. uint32_t size;
  517. char buf[4];
  518. if (fread(buf, 1, sizeof(buf), proxy) != sizeof(buf)) return NULL;
  519. /* This is reading serialized data from system/netd/DnsProxyListener.cpp
  520. * and changes here need to be matched there */
  521. int result_code = strtol(buf, NULL, 10);
  522. if (result_code != DnsProxyQueryResult) {
  523. fread(&size, 1, sizeof(size), proxy);
  524. return NULL;
  525. }
  526. if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
  527. size = ntohl(size);
  528. res_static rs = __res_get_static();
  529. memset(&rs->host, 0, sizeof(rs->host));
  530. char *ptr = rs->hostbuf;
  531. if (fread(ptr, 1, size, proxy) != size) return NULL;
  532. ptr += size;
  533. rs->host.h_name = rs->hostbuf;
  534. char **aliases = rs->host_aliases;
  535. rs->host.h_aliases = rs->host_aliases;
  536. while (1) {
  537. if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
  538. size = ntohl(size);
  539. if (size == 0) {
  540. *aliases = NULL;
  541. break;
  542. }
  543. if (fread(ptr, 1, size, proxy) != size) return NULL;
  544. *aliases++ = ptr;
  545. ptr += size;
  546. }
  547. if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
  548. rs->host.h_addrtype = ntohl(size);
  549. if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
  550. rs->host.h_length = ntohl(size);
  551. char **addrs = rs->h_addr_ptrs;
  552. rs->host.h_addr_list = rs->h_addr_ptrs;
  553. while (1) {
  554. if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
  555. size = ntohl(size);
  556. if (size == 0) {
  557. *addrs = NULL;
  558. break;
  559. }
  560. if (fread(ptr, 1, size, proxy) != size) return NULL;
  561. *addrs++ = ptr;
  562. ptr += size;
  563. }
  564. return &rs->host;
  565. }
  566. static struct hostent *
  567. gethostbyname_internal_real(const char *name, int af, res_state res)
  568. {
  569. const char *cp;
  570. char *bp, *ep;
  571. int size;
  572. struct hostent *hp;
  573. res_static rs = __res_get_static();
  574. static const ns_dtab dtab[] = {
  575. NS_FILES_CB(_gethtbyname, NULL)
  576. { NSSRC_DNS, _dns_gethtbyname, NULL }, /* force -DHESIOD */
  577. { 0, 0, 0 }
  578. };
  579. assert(name != NULL);
  580. switch (af) {
  581. case AF_INET:
  582. size = INADDRSZ;
  583. break;
  584. case AF_INET6:
  585. size = IN6ADDRSZ;
  586. break;
  587. default:
  588. h_errno = NETDB_INTERNAL;
  589. errno = EAFNOSUPPORT;
  590. return NULL;
  591. }
  592. rs->host.h_addrtype = af;
  593. rs->host.h_length = size;
  594. /*
  595. * if there aren't any dots, it could be a user-level alias.
  596. * this is also done in res_nquery() since we are not the only
  597. * function that looks up host names.
  598. */
  599. if (!strchr(name, '.') && (cp = __hostalias(name)))
  600. name = cp;
  601. /*
  602. * disallow names consisting only of digits/dots, unless
  603. * they end in a dot.
  604. */
  605. if (isdigit((u_char) name[0]))
  606. for (cp = name;; ++cp) {
  607. if (!*cp) {
  608. if (*--cp == '.')
  609. break;
  610. /*
  611. * All-numeric, no dot at the end.
  612. * Fake up a hostent as if we'd actually
  613. * done a lookup.
  614. */
  615. if (inet_pton(af, name,
  616. (char *)(void *)rs->host_addr) <= 0) {
  617. h_errno = HOST_NOT_FOUND;
  618. return NULL;
  619. }
  620. strncpy(rs->hostbuf, name, MAXDNAME);
  621. rs->hostbuf[MAXDNAME] = '\0';
  622. bp = rs->hostbuf + MAXDNAME;
  623. ep = rs->hostbuf + sizeof rs->hostbuf;
  624. rs->host.h_name = rs->hostbuf;
  625. rs->host.h_aliases = rs->host_aliases;
  626. rs->host_aliases[0] = NULL;
  627. rs->h_addr_ptrs[0] = (char *)(void *)rs->host_addr;
  628. rs->h_addr_ptrs[1] = NULL;
  629. rs->host.h_addr_list = rs->h_addr_ptrs;
  630. if (res->options & RES_USE_INET6)
  631. map_v4v6_hostent(&rs->host, &bp, ep);
  632. h_errno = NETDB_SUCCESS;
  633. return &rs->host;
  634. }
  635. if (!isdigit((u_char) *cp) && *cp != '.')
  636. break;
  637. }
  638. if ((isxdigit((u_char) name[0]) && strchr(name, ':') != NULL) ||
  639. name[0] == ':')
  640. for (cp = name;; ++cp) {
  641. if (!*cp) {
  642. if (*--cp == '.')
  643. break;
  644. /*
  645. * All-IPv6-legal, no dot at the end.
  646. * Fake up a hostent as if we'd actually
  647. * done a lookup.
  648. */
  649. if (inet_pton(af, name,
  650. (char *)(void *)rs->host_addr) <= 0) {
  651. h_errno = HOST_NOT_FOUND;
  652. return NULL;
  653. }
  654. strncpy(rs->hostbuf, name, MAXDNAME);
  655. rs->hostbuf[MAXDNAME] = '\0';
  656. bp = rs->hostbuf + MAXDNAME;
  657. ep = rs->hostbuf + sizeof rs->hostbuf;
  658. rs->host.h_name = rs->hostbuf;
  659. rs->host.h_aliases = rs->host_aliases;
  660. rs->host_aliases[0] = NULL;
  661. rs->h_addr_ptrs[0] = (char *)(void *)rs->host_addr;
  662. rs->h_addr_ptrs[1] = NULL;
  663. rs->host.h_addr_list = rs->h_addr_ptrs;
  664. h_errno = NETDB_SUCCESS;
  665. return &rs->host;
  666. }
  667. if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.')
  668. break;
  669. }
  670. hp = NULL;
  671. h_errno = NETDB_INTERNAL;
  672. if (nsdispatch(&hp, dtab, NSDB_HOSTS, "gethostbyname",
  673. default_dns_files, name, strlen(name), af) != NS_SUCCESS) {
  674. return NULL;
  675. }
  676. h_errno = NETDB_SUCCESS;
  677. return hp;
  678. }
  679. // very similar in proxy-ness to android_getaddrinfo_proxy
  680. static struct hostent *
  681. gethostbyname_internal(const char *name, int af, res_state res, const char *iface, int mark)
  682. {
  683. const char *cache_mode = getenv("ANDROID_DNS_MODE");
  684. FILE* proxy = NULL;
  685. struct hostent *result = NULL;
  686. if (cache_mode != NULL && strcmp(cache_mode, "local") == 0) {
  687. res_setiface(res, iface);
  688. res_setmark(res, mark);
  689. return gethostbyname_internal_real(name, af, res);
  690. }
  691. proxy = android_open_proxy();
  692. if (proxy == NULL) goto exit;
  693. /* This is writing to system/netd/DnsProxyListener.cpp and changes
  694. * here need to be matched there */
  695. if (fprintf(proxy, "gethostbyname %s %s %d",
  696. iface == NULL ? "^" : iface,
  697. name == NULL ? "^" : name,
  698. af) < 0) {
  699. goto exit;
  700. }
  701. if (fputc(0, proxy) == EOF || fflush(proxy) != 0) {
  702. goto exit;
  703. }
  704. result = android_read_hostent(proxy);
  705. exit:
  706. if (proxy != NULL) {
  707. fclose(proxy);
  708. }
  709. return result;
  710. }
  711. struct hostent *
  712. android_gethostbyaddrforiface_proxy(const void *addr,
  713. socklen_t len, int af, const char* iface, int mark)
  714. {
  715. struct hostent *result = NULL;
  716. FILE* proxy = android_open_proxy();
  717. if (proxy == NULL) goto exit;
  718. char buf[INET6_ADDRSTRLEN]; //big enough for IPv4 and IPv6
  719. const char * addrStr = inet_ntop(af, addr, buf, sizeof(buf));
  720. if (addrStr == NULL) goto exit;
  721. if (fprintf(proxy, "gethostbyaddr %s %d %d %s",
  722. addrStr, len, af, iface == NULL ? "^" : iface) < 0) {
  723. goto exit;
  724. }
  725. if (fputc(0, proxy) == EOF || fflush(proxy) != 0) {
  726. goto exit;
  727. }
  728. result = android_read_hostent(proxy);
  729. exit:
  730. if (proxy != NULL) {
  731. fclose(proxy);
  732. }
  733. return result;
  734. }
  735. struct hostent *
  736. android_gethostbyaddrforiface_real(const void *addr,
  737. socklen_t len, int af, const char* iface, int mark)
  738. {
  739. const u_char *uaddr = (const u_char *)addr;
  740. socklen_t size;
  741. struct hostent *hp;
  742. static const ns_dtab dtab[] = {
  743. NS_FILES_CB(_gethtbyaddr, NULL)
  744. { NSSRC_DNS, _dns_gethtbyaddr, NULL }, /* force -DHESIOD */
  745. { 0, 0, 0 }
  746. };
  747. assert(addr != NULL);
  748. if (af == AF_INET6 && len == IN6ADDRSZ &&
  749. (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)(const void *)uaddr) ||
  750. IN6_IS_ADDR_SITELOCAL((const struct in6_addr *)(const void *)uaddr))) {
  751. h_errno = HOST_NOT_FOUND;
  752. return NULL;
  753. }
  754. if (af == AF_INET6 && len == IN6ADDRSZ &&
  755. (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)(const void *)uaddr) ||
  756. IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)(const void *)uaddr))) {
  757. /* Unmap. */
  758. addr += IN6ADDRSZ - INADDRSZ;
  759. uaddr += IN6ADDRSZ - INADDRSZ;
  760. af = AF_INET;
  761. len = INADDRSZ;
  762. }
  763. switch (af) {
  764. case AF_INET:
  765. size = INADDRSZ;
  766. break;
  767. case AF_INET6:
  768. size = IN6ADDRSZ;
  769. break;
  770. default:
  771. errno = EAFNOSUPPORT;
  772. h_errno = NETDB_INTERNAL;
  773. return NULL;
  774. }
  775. if (size != len) {
  776. errno = EINVAL;
  777. h_errno = NETDB_INTERNAL;
  778. return NULL;
  779. }
  780. hp = NULL;
  781. h_errno = NETDB_INTERNAL;
  782. if (nsdispatch(&hp, dtab, NSDB_HOSTS, "gethostbyaddr",
  783. default_dns_files, uaddr, len, af, iface, mark) != NS_SUCCESS)
  784. return NULL;
  785. h_errno = NETDB_SUCCESS;
  786. return hp;
  787. }
  788. struct hostent *
  789. android_gethostbyaddrforiface(const void *addr, socklen_t len, int af, const char* iface, int mark)
  790. {
  791. const char *cache_mode = getenv("ANDROID_DNS_MODE");
  792. if (cache_mode == NULL || strcmp(cache_mode, "local") != 0) {
  793. return android_gethostbyaddrforiface_proxy(addr, len, af, iface, mark);
  794. } else {
  795. return android_gethostbyaddrforiface_real(addr,len, af, iface, mark);
  796. }
  797. }
  798. struct hostent *
  799. gethostbyaddr(const void *addr, socklen_t len, int af)
  800. {
  801. return android_gethostbyaddrforiface(addr, len, af, NULL, 0);
  802. }
  803. static void
  804. _sethtent(int f)
  805. {
  806. res_static rs = __res_get_static();
  807. if (rs == NULL) return;
  808. if (!rs->hostf)
  809. rs->hostf = fopen(_PATH_HOSTS, "r" );
  810. else
  811. rewind(rs->hostf);
  812. rs->stayopen = f;
  813. }
  814. static void
  815. _endhtent(void)
  816. {
  817. res_static rs = __res_get_static();
  818. if (rs == NULL) return;
  819. if (rs->hostf && !rs->stayopen) {
  820. (void) fclose(rs->hostf);
  821. rs->hostf = NULL;
  822. }
  823. }
  824. static struct hostent *
  825. _gethtent(void)
  826. {
  827. char *p;
  828. char *cp, **q;
  829. int af, len;
  830. res_static rs = __res_get_static();
  831. if (!rs->hostf && !(rs->hostf = fopen(_PATH_HOSTS, "r" ))) {
  832. h_errno = NETDB_INTERNAL;
  833. return NULL;
  834. }
  835. again:
  836. if (!(p = fgets(rs->hostbuf, sizeof rs->hostbuf, rs->hostf))) {
  837. h_errno = HOST_NOT_FOUND;
  838. return NULL;
  839. }
  840. if (*p == '#')
  841. goto again;
  842. if (!(cp = strpbrk(p, "#\n")))
  843. goto again;
  844. *cp = '\0';
  845. if (!(cp = strpbrk(p, " \t")))
  846. goto again;
  847. *cp++ = '\0';
  848. if (inet_pton(AF_INET6, p, (char *)(void *)rs->host_addr) > 0) {
  849. af = AF_INET6;
  850. len = IN6ADDRSZ;
  851. } else if (inet_pton(AF_INET, p, (char *)(void *)rs->host_addr) > 0) {
  852. res_state res = __res_get_state();
  853. if (res == NULL)
  854. return NULL;
  855. if (res->options & RES_USE_INET6) {
  856. map_v4v6_address((char *)(void *)rs->host_addr,
  857. (char *)(void *)rs->host_addr);
  858. af = AF_INET6;
  859. len = IN6ADDRSZ;
  860. } else {
  861. af = AF_INET;
  862. len = INADDRSZ;
  863. }
  864. __res_put_state(res);
  865. } else {
  866. goto again;
  867. }
  868. /* if this is not something we're looking for, skip it. */
  869. if (rs->host.h_addrtype != 0 && rs->host.h_addrtype != af)
  870. goto again;
  871. if (rs->host.h_length != 0 && rs->host.h_length != len)
  872. goto again;
  873. rs->h_addr_ptrs[0] = (char *)(void *)rs->host_addr;
  874. rs->h_addr_ptrs[1] = NULL;
  875. rs->host.h_addr_list = rs->h_addr_ptrs;
  876. rs->host.h_length = len;
  877. rs->host.h_addrtype = af;
  878. while (*cp == ' ' || *cp == '\t')
  879. cp++;
  880. rs->host.h_name = cp;
  881. q = rs->host.h_aliases = rs->host_aliases;
  882. if ((cp = strpbrk(cp, " \t")) != NULL)
  883. *cp++ = '\0';
  884. while (cp && *cp) {
  885. if (*cp == ' ' || *cp == '\t') {
  886. cp++;
  887. continue;
  888. }
  889. if (q < &rs->host_aliases[MAXALIASES - 1])
  890. *q++ = cp;
  891. if ((cp = strpbrk(cp, " \t")) != NULL)
  892. *cp++ = '\0';
  893. }
  894. *q = NULL;
  895. h_errno = NETDB_SUCCESS;
  896. return &rs->host;
  897. }
  898. /*ARGSUSED*/
  899. int
  900. _gethtbyname(void *rv, void *cb_data, va_list ap)
  901. {
  902. struct hostent *hp;
  903. const char *name;
  904. int af;
  905. assert(rv != NULL);
  906. name = va_arg(ap, char *);
  907. /* NOSTRICT skip len */(void)va_arg(ap, int);
  908. af = va_arg(ap, int);
  909. hp = NULL;
  910. #if 0
  911. {
  912. res_state res = __res_get_state();
  913. if (res == NULL)
  914. return NS_NOTFOUND;
  915. if (res->options & RES_USE_INET6)
  916. hp = _gethtbyname2(name, AF_INET6);
  917. if (hp==NULL)
  918. hp = _gethtbyname2(name, AF_INET);
  919. __res_put_state(res);
  920. }
  921. #else
  922. hp = _gethtbyname2(name, af);
  923. #endif
  924. *((struct hostent **)rv) = hp;
  925. if (hp == NULL) {
  926. h_errno = HOST_NOT_FOUND;
  927. return NS_NOTFOUND;
  928. }
  929. return NS_SUCCESS;
  930. }
  931. static struct hostent *
  932. _gethtbyname2(const char *name, int af)
  933. {
  934. struct hostent *p;
  935. char *tmpbuf, *ptr, **cp;
  936. int num;
  937. size_t len;
  938. res_static rs = __res_get_static();
  939. assert(name != NULL);
  940. _sethtent(rs->stayopen);
  941. ptr = tmpbuf = NULL;
  942. num = 0;
  943. while ((p = _gethtent()) != NULL && num < MAXADDRS) {
  944. if (p->h_addrtype != af)
  945. continue;
  946. if (strcasecmp(p->h_name, name) != 0) {
  947. for (cp = p->h_aliases; *cp != NULL; cp++)
  948. if (strcasecmp(*cp, name) == 0)
  949. break;
  950. if (*cp == NULL) continue;
  951. }
  952. if (num == 0) {
  953. size_t bufsize;
  954. char *src;
  955. bufsize = strlen(p->h_name) + 2 +
  956. MAXADDRS * p->h_length +
  957. ALIGNBYTES;
  958. for (cp = p->h_aliases; *cp != NULL; cp++)
  959. bufsize += strlen(*cp) + 1;
  960. if ((tmpbuf = malloc(bufsize)) == NULL) {
  961. h_errno = NETDB_INTERNAL;
  962. return NULL;
  963. }
  964. ptr = tmpbuf;
  965. src = p->h_name;
  966. while ((*ptr++ = *src++) != '\0');
  967. for (cp = p->h_aliases; *cp != NULL; cp++) {
  968. src = *cp;
  969. while ((*ptr++ = *src++) != '\0');
  970. }
  971. *ptr++ = '\0';
  972. ptr = (char *)(void *)ALIGN(ptr);
  973. }
  974. (void)memcpy(ptr, p->h_addr_list[0], (size_t)p->h_length);
  975. ptr += p->h_length;
  976. num++;
  977. }
  978. _endhtent();
  979. if (num == 0) return NULL;
  980. len = ptr - tmpbuf;
  981. if (len > (sizeof(rs->hostbuf) - ALIGNBYTES)) {
  982. free(tmpbuf);
  983. errno = ENOSPC;
  984. h_errno = NETDB_INTERNAL;
  985. return NULL;
  986. }
  987. ptr = memcpy((void *)ALIGN(rs->hostbuf), tmpbuf, len);
  988. free(tmpbuf);
  989. rs->host.h_name = ptr;
  990. while (*ptr++);
  991. cp = rs->host_aliases;
  992. while (*ptr) {
  993. *cp++ = ptr;
  994. while (*ptr++);
  995. }
  996. ptr++;
  997. *cp = NULL;
  998. ptr = (char *)(void *)ALIGN(ptr);
  999. cp = rs->h_addr_ptrs;
  1000. while (num--) {
  1001. *cp++ = ptr;
  1002. ptr += rs->host.h_length;
  1003. }
  1004. *cp = NULL;
  1005. return &rs->host;
  1006. }
  1007. /*ARGSUSED*/
  1008. static int
  1009. _gethtbyaddr(void *rv, void *cb_data, va_list ap)
  1010. {
  1011. struct hostent *p;
  1012. const unsigned char *addr;
  1013. int len, af;
  1014. res_static rs = __res_get_static();
  1015. assert(rv != NULL);
  1016. addr = va_arg(ap, unsigned char *);
  1017. len = va_arg(ap, int);
  1018. af = va_arg(ap, int);
  1019. rs->host.h_length = len;
  1020. rs->host.h_addrtype = af;
  1021. _sethtent(rs->stayopen);
  1022. while ((p = _gethtent()) != NULL)
  1023. if (p->h_addrtype == af && !memcmp(p->h_addr, addr,
  1024. (size_t)len))
  1025. break;
  1026. _endhtent();
  1027. *((struct hostent **)rv) = p;
  1028. if (p==NULL) {
  1029. h_errno = HOST_NOT_FOUND;
  1030. return NS_NOTFOUND;
  1031. }
  1032. return NS_SUCCESS;
  1033. }
  1034. static void
  1035. map_v4v6_address(const char *src, char *dst)
  1036. {
  1037. u_char *p = (u_char *)dst;
  1038. char tmp[INADDRSZ];
  1039. int i;
  1040. assert(src != NULL);
  1041. assert(dst != NULL);
  1042. /* Stash a temporary copy so our caller can update in place. */
  1043. (void)memcpy(tmp, src, INADDRSZ);
  1044. /* Mark this ipv6 addr as a mapped ipv4. */
  1045. for (i = 0; i < 10; i++)
  1046. *p++ = 0x00;
  1047. *p++ = 0xff;
  1048. *p++ = 0xff;
  1049. /* Retrieve the saved copy and we're done. */
  1050. (void)memcpy((void *)p, tmp, INADDRSZ);
  1051. }
  1052. static void
  1053. map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep)
  1054. {
  1055. char **ap;
  1056. assert(hp != NULL);
  1057. assert(bpp != NULL);
  1058. assert(ep != NULL);
  1059. if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
  1060. return;
  1061. hp->h_addrtype = AF_INET6;
  1062. hp->h_length = IN6ADDRSZ;
  1063. for (ap = hp->h_addr_list; *ap; ap++) {
  1064. int i = sizeof(align) - (size_t)((u_long)*bpp % sizeof(align));
  1065. if (ep - *bpp < (i + IN6ADDRSZ)) {
  1066. /* Out of memory. Truncate address list here. XXX */
  1067. *ap = NULL;
  1068. return;
  1069. }
  1070. *bpp += i;
  1071. map_v4v6_address(*ap, *bpp);
  1072. *ap = *bpp;
  1073. *bpp += IN6ADDRSZ;
  1074. }
  1075. }
  1076. static void
  1077. addrsort(char **ap, int num, res_state res)
  1078. {
  1079. int i, j;
  1080. char **p;
  1081. short aval[MAXADDRS];
  1082. int needsort = 0;
  1083. assert(ap != NULL);
  1084. p = ap;
  1085. for (i = 0; i < num; i++, p++) {
  1086. for (j = 0 ; (unsigned)j < res->nsort; j++)
  1087. if (res->sort_list[j].addr.s_addr ==
  1088. (((struct in_addr *)(void *)(*p))->s_addr &
  1089. res->sort_list[j].mask))
  1090. break;
  1091. aval[i] = j;
  1092. if (needsort == 0 && i > 0 && j < aval[i-1])
  1093. needsort = i;
  1094. }
  1095. if (!needsort)
  1096. return;
  1097. while (needsort < num) {
  1098. for (j = needsort - 1; j >= 0; j--) {
  1099. if (aval[j] > aval[j+1]) {
  1100. char *hp;
  1101. i = aval[j];
  1102. aval[j] = aval[j+1];
  1103. aval[j+1] = i;
  1104. hp = ap[j];
  1105. ap[j] = ap[j+1];
  1106. ap[j+1] = hp;
  1107. } else
  1108. break;
  1109. }
  1110. needsort++;
  1111. }
  1112. }
  1113. struct hostent *
  1114. gethostent(void)
  1115. {
  1116. res_static rs = __res_get_static();
  1117. rs->host.h_addrtype = 0;
  1118. rs->host.h_length = 0;
  1119. return _gethtent();
  1120. }
  1121. /*ARGSUSED*/
  1122. static int
  1123. _dns_gethtbyname(void *rv, void *cb_data, va_list ap)
  1124. {
  1125. querybuf *buf;
  1126. int n, type;
  1127. struct hostent *hp;
  1128. const char *name;
  1129. int af;
  1130. res_state res;
  1131. assert(rv != NULL);
  1132. name = va_arg(ap, char *);
  1133. /* NOSTRICT skip len */(void)va_arg(ap, int);
  1134. af = va_arg(ap, int);
  1135. switch (af) {
  1136. case AF_INET:
  1137. type = T_A;
  1138. break;
  1139. case AF_INET6:
  1140. type = T_AAAA;
  1141. break;
  1142. default:
  1143. return NS_UNAVAIL;
  1144. }
  1145. buf = malloc(sizeof(*buf));
  1146. if (buf == NULL) {
  1147. h_errno = NETDB_INTERNAL;
  1148. return NS_NOTFOUND;
  1149. }
  1150. res = __res_get_state();
  1151. if (res == NULL) {
  1152. free(buf);
  1153. return NS_NOTFOUND;
  1154. }
  1155. n = res_nsearch(res, name, C_IN, type, buf->buf, sizeof(buf->buf));
  1156. if (n < 0) {
  1157. free(buf);
  1158. dprintf("res_nsearch failed (%d)\n", res, n);
  1159. __res_put_state(res);
  1160. return NS_NOTFOUND;
  1161. }
  1162. hp = getanswer(buf, n, name, type, res);
  1163. free(buf);
  1164. __res_put_state(res);
  1165. if (hp == NULL)
  1166. switch (h_errno) {
  1167. case HOST_NOT_FOUND:
  1168. return NS_NOTFOUND;
  1169. case TRY_AGAIN:
  1170. return NS_TRYAGAIN;
  1171. default:
  1172. return NS_UNAVAIL;
  1173. }
  1174. *((struct hostent **)rv) = hp;
  1175. return NS_SUCCESS;
  1176. }
  1177. /*ARGSUSED*/
  1178. static int
  1179. _dns_gethtbyaddr(void *rv, void *cb_data, va_list ap)
  1180. {
  1181. char qbuf[MAXDNAME + 1], *qp, *ep;
  1182. int n;
  1183. querybuf *buf;
  1184. struct hostent *hp;
  1185. const unsigned char *uaddr;
  1186. int len, af, advance;
  1187. res_state res;
  1188. const char* iface;
  1189. int mark;
  1190. res_static rs = __res_get_static();
  1191. assert(rv != NULL);
  1192. uaddr = va_arg(ap, unsigned char *);
  1193. len = va_arg(ap, int);
  1194. af = va_arg(ap, int);
  1195. iface = va_arg(ap, char *);
  1196. mark = va_arg(ap, int);
  1197. switch (af) {
  1198. case AF_INET:
  1199. (void)snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa",
  1200. (uaddr[3] & 0xff), (uaddr[2] & 0xff),
  1201. (uaddr[1] & 0xff), (uaddr[0] & 0xff));
  1202. break;
  1203. case AF_INET6:
  1204. qp = qbuf;
  1205. ep = qbuf + sizeof(qbuf) - 1;
  1206. for (n = IN6ADDRSZ - 1; n >= 0; n--) {
  1207. advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.",
  1208. uaddr[n] & 0xf,
  1209. ((unsigned int)uaddr[n] >> 4) & 0xf);
  1210. if (advance > 0 && qp + advance < ep)
  1211. qp += advance;
  1212. else {
  1213. h_errno = NETDB_INTERNAL;
  1214. return NS_NOTFOUND;
  1215. }
  1216. }
  1217. if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf)) {
  1218. h_errno = NETDB_INTERNAL;
  1219. return NS_NOTFOUND;
  1220. }
  1221. break;
  1222. default:
  1223. abort();
  1224. }
  1225. buf = malloc(sizeof(*buf));
  1226. if (buf == NULL) {
  1227. h_errno = NETDB_INTERNAL;
  1228. return NS_NOTFOUND;
  1229. }
  1230. res = __res_get_state();
  1231. if (res == NULL) {
  1232. free(buf);
  1233. return NS_NOTFOUND;
  1234. }
  1235. res_setiface(res, iface);
  1236. res_setmark(res, mark);
  1237. n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, sizeof(buf->buf));
  1238. if (n < 0) {
  1239. free(buf);
  1240. dprintf("res_nquery failed (%d)\n", res, n);
  1241. __res_put_state(res);
  1242. return NS_NOTFOUND;
  1243. }
  1244. hp = getanswer(buf, n, qbuf, T_PTR, res);
  1245. free(buf);
  1246. if (hp == NULL) {
  1247. __res_put_state(res);
  1248. switch (h_errno) {
  1249. case HOST_NOT_FOUND:
  1250. return NS_NOTFOUND;
  1251. case TRY_AGAIN:
  1252. return NS_TRYAGAIN;
  1253. default:
  1254. return NS_UNAVAIL;
  1255. }
  1256. }
  1257. hp->h_addrtype = af;
  1258. hp->h_length = len;
  1259. (void)memcpy(rs->host_addr, uaddr, (size_t)len);
  1260. rs->h_addr_ptrs[0] = (char *)(void *)rs->host_addr;
  1261. rs->h_addr_ptrs[1] = NULL;
  1262. if (af == AF_INET && (res->options & RES_USE_INET6)) {
  1263. map_v4v6_address((char *)(void *)rs->host_addr,
  1264. (char *)(void *)rs->host_addr);
  1265. hp->h_addrtype = AF_INET6;
  1266. hp->h_length = IN6ADDRSZ;
  1267. }
  1268. __res_put_state(res);
  1269. *((struct hostent **)rv) = hp;
  1270. h_errno = NETDB_SUCCESS;
  1271. return NS_SUCCESS;
  1272. }