PageRenderTime 53ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

lib/libc/net/gethnamaddr.c

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