1 /* $NetBSD: gethnamaddr.c,v 1.92 2015/09/22 16:16:02 christos Exp $ */
4 * ++Copyright++ 1985, 1988, 1993
6 * Copyright (c) 1985, 1988, 1993
7 * The Regents of the University of California. All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
35 * Permission to use, copy, modify, and distribute this software for any
36 * purpose with or without fee is hereby granted, provided that the above
37 * copyright notice and this permission notice appear in all copies, and that
38 * the name of Digital Equipment Corporation not be used in advertising or
39 * publicity pertaining to distribution of the document or software without
40 * specific, written prior permission.
42 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
43 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
45 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
46 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
47 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
48 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
54 #include <sys/cdefs.h>
55 #if defined(LIBC_SCCS) && !defined(lint)
57 static char sccsid
[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
58 static char rcsid
[] = "Id: gethnamaddr.c,v 8.21 1997/06/01 20:34:37 vixie Exp ";
60 __RCSID("$NetBSD: gethnamaddr.c,v 1.92 2015/09/22 16:16:02 christos Exp $");
62 #endif /* LIBC_SCCS and not lint */
65 #include "namespace.h"
67 #include <sys/param.h>
68 #include <sys/socket.h>
69 #include <netinet/in.h>
70 #include <arpa/inet.h>
71 #include <arpa/nameser.h>
86 #define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
94 #include <rpcsvc/yp_prot.h>
95 #include <rpcsvc/ypclnt.h>
100 #if defined(_LIBC) && defined(__weak_alias)
101 __weak_alias(gethostbyaddr
,_gethostbyaddr
)
102 __weak_alias(gethostbyname
,_gethostbyname
)
103 __weak_alias(gethostent
,_gethostent
)
106 #define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0U || \
108 #define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok)
109 #define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok)
111 #define addalias(d, s, arr, siz) do { \
112 if (d >= &arr[siz]) { \
113 char **xptr = realloc(arr, (siz + 10) * sizeof(*arr)); \
116 d = xptr + (d - arr); \
121 } while (/*CONSTCOND*/0)
123 #define setup(arr, siz) do { \
124 arr = malloc((siz = 10) * sizeof(*arr)); \
127 } while (/*CONSTCOND*/0)
130 static const char AskedForGot
[] =
131 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
135 static char *__ypdomain
;
138 #define MAXPACKET (64*1024)
142 u_char buf
[MAXPACKET
];
151 static void debugprintf(const char *, res_state
, ...)
152 __attribute__((__format__(__printf__
, 1, 3)));
154 static struct hostent
*getanswer(const querybuf
*, int, const char *, int,
155 res_state
, struct hostent
*, char *, size_t, int *);
156 static void map_v4v6_address(const char *, char *);
157 static void map_v4v6_hostent(struct hostent
*, char **, char *);
158 static void addrsort(char **, int, res_state
);
160 void dns_service(void);
162 int dn_skipname(const u_char
*, const u_char
*);
165 static struct hostent
*_yp_hostent(char *, int, struct getnamaddr
*);
168 static struct hostent
*gethostbyname_internal(const char *, int, res_state
,
169 struct hostent
*, char *, size_t, int *);
171 static const ns_src default_dns_files
[] = {
172 { NSSRC_FILES
, NS_SUCCESS
},
173 { NSSRC_DNS
, NS_SUCCESS
},
180 debugprintf(const char *msg
, res_state res
, ...)
182 _DIAGASSERT(msg
!= NULL
);
184 if (res
->options
& RES_DEBUG
) {
196 # define debugprintf(msg, res, num) /*nada*/
199 #define BOUNDED_INCR(x) \
204 } while (/*CONSTCOND*/0)
206 #define BOUNDS_CHECK(ptr, count) \
208 if ((ptr) + (count) > eom) \
210 } while (/*CONSTCOND*/0)
212 static struct hostent
*
213 getanswer(const querybuf
*answer
, int anslen
, const char *qname
, int qtype
,
214 res_state res
, struct hostent
*hent
, char *buf
, size_t buflen
, int *he
)
220 const u_char
*eom
, *erdata
;
221 char *bp
, **ap
, **hap
, *ep
;
222 int type
, class, ancount
, qdcount
;
223 int haveanswer
, had_error
;
228 char *addr_ptrs
[MAXADDRS
];
230 int (*name_ok
)(const char *);
232 _DIAGASSERT(answer
!= NULL
);
233 _DIAGASSERT(qname
!= NULL
);
237 eom
= answer
->buf
+ anslen
;
248 return NULL
; /* XXX should be abort(); */
251 setup(aliases
, maxaliases
);
253 * find first satisfactory answer
256 ancount
= ntohs(hp
->ancount
);
257 qdcount
= ntohs(hp
->qdcount
);
261 BOUNDED_INCR(HFIXEDSZ
);
265 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, (int)(ep
- bp
));
266 if ((n
< 0) || !maybe_ok(res
, bp
, name_ok
))
269 BOUNDED_INCR(n
+ QFIXEDSZ
);
270 if (qtype
== T_A
|| qtype
== T_AAAA
) {
271 /* res_send() has already verified that the query name is the
272 * same as the one we sent; this just gets the expanded name
273 * (i.e., with the succeeding search-domain tacked on).
275 n
= (int)strlen(bp
) + 1; /* for the \0 */
276 if (n
>= MAXHOSTNAMELEN
)
280 /* The qname can be abbreviated, but h_name is now absolute. */
281 qname
= hent
->h_name
;
283 hent
->h_aliases
= ap
= aliases
;
284 hent
->h_addr_list
= hap
= addr_ptrs
;
289 while (ancount
-- > 0 && cp
< eom
&& !had_error
) {
290 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, (int)(ep
- bp
));
291 if ((n
< 0) || !maybe_ok(res
, bp
, name_ok
)) {
296 BOUNDS_CHECK(cp
, 3 * INT16SZ
+ INT32SZ
);
297 type
= _getshort(cp
);
298 cp
+= INT16SZ
; /* type */
299 class = _getshort(cp
);
300 cp
+= INT16SZ
+ INT32SZ
; /* class, TTL */
302 cp
+= INT16SZ
; /* len */
306 /* XXX - debug? syslog? */
308 continue; /* XXX - had_error++ ? */
310 if ((qtype
== T_A
|| qtype
== T_AAAA
) && type
== T_CNAME
) {
311 n
= dn_expand(answer
->buf
, eom
, cp
, tbuf
,
313 if ((n
< 0) || !maybe_ok(res
, tbuf
, name_ok
)) {
321 addalias(ap
, bp
, aliases
, maxaliases
);
322 n
= (int)strlen(bp
) + 1; /* for the \0 */
323 if (n
>= MAXHOSTNAMELEN
) {
328 /* Get canonical name. */
329 n
= (int)strlen(tbuf
) + 1; /* for the \0 */
330 if (n
> ep
- bp
|| n
>= MAXHOSTNAMELEN
) {
334 strlcpy(bp
, tbuf
, (size_t)(ep
- bp
));
339 if (qtype
== T_PTR
&& type
== T_CNAME
) {
340 n
= dn_expand(answer
->buf
, eom
, cp
, tbuf
,
342 if (n
< 0 || !maybe_dnok(res
, tbuf
)) {
349 /* Get canonical name. */
350 n
= (int)strlen(tbuf
) + 1; /* for the \0 */
351 if (n
> ep
- bp
|| n
>= MAXHOSTNAMELEN
) {
355 strlcpy(bp
, tbuf
, (size_t)(ep
- bp
));
361 if (type
!= T_KEY
&& type
!= T_SIG
)
362 syslog(LOG_NOTICE
|LOG_AUTH
,
363 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
364 qname
, p_class(C_IN
), p_type(qtype
),
367 continue; /* XXX - had_error++ ? */
371 if (strcasecmp(tname
, bp
) != 0) {
372 syslog(LOG_NOTICE
|LOG_AUTH
,
373 AskedForGot
, qname
, bp
);
375 continue; /* XXX - had_error++ ? */
377 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, (int)(ep
- bp
));
378 if ((n
< 0) || !maybe_hnok(res
, bp
)) {
382 #if MULTI_PTRS_ARE_ALIASES
389 addalias(ap
, bp
, aliases
, maxaliases
);
391 n
= (int)strlen(bp
) + 1; /* for the \0 */
392 if (n
>= MAXHOSTNAMELEN
) {
401 if (res
->options
& RES_USE_INET6
) {
402 n
= strlen(bp
) + 1; /* for the \0 */
403 if (n
>= MAXHOSTNAMELEN
) {
408 map_v4v6_hostent(hent
, &bp
, ep
);
414 if (strcasecmp(hent
->h_name
, bp
) != 0) {
415 syslog(LOG_NOTICE
|LOG_AUTH
,
416 AskedForGot
, hent
->h_name
, bp
);
418 continue; /* XXX - had_error++ ? */
420 if (n
!= hent
->h_length
) {
424 if (type
== T_AAAA
) {
426 memcpy(&in6
, cp
, NS_IN6ADDRSZ
);
427 if (IN6_IS_ADDR_V4MAPPED(&in6
)) {
436 nn
= (int)strlen(bp
) + 1; /* for the \0 */
440 bp
+= sizeof(align
) -
441 (size_t)((u_long
)bp
% sizeof(align
));
444 debugprintf("size (%d) too big\n", res
, n
);
448 if (hap
>= &addr_ptrs
[MAXADDRS
- 1]) {
450 debugprintf("Too many addresses (%d)\n",
456 (void)memcpy(*hap
++ = bp
, cp
, (size_t)n
);
472 * Note: we sort even if host can take only one address
473 * in its return structures - should give it the "best"
474 * address in that case, not some random one
476 if (res
->nsort
&& haveanswer
> 1 && qtype
== T_A
)
477 addrsort(addr_ptrs
, haveanswer
, res
);
479 n
= (int)strlen(qname
) + 1; /* for the \0 */
480 if (n
> ep
- bp
|| n
>= MAXHOSTNAMELEN
)
482 strlcpy(bp
, qname
, (size_t)(ep
- bp
));
486 if (res
->options
& RES_USE_INET6
)
487 map_v4v6_hostent(hent
, &bp
, ep
);
495 bp
= (char *)ALIGN(bp
);
496 n
= (int)(ap
- aliases
);
497 qlen
= (n
+ 1) * sizeof(*hent
->h_aliases
);
498 if ((size_t)(ep
- bp
) < qlen
)
500 hent
->h_aliases
= (void *)bp
;
501 memcpy(bp
, aliases
, qlen
);
506 n
= (int)(hap
- addr_ptrs
);
507 qlen
= (n
+ 1) * sizeof(*hent
->h_addr_list
);
508 if ((size_t)(ep
- bp
) < qlen
)
510 hent
->h_addr_list
= (void *)bp
;
511 memcpy(bp
, addr_ptrs
, qlen
);
517 *he
= NETDB_INTERNAL
;
522 gethostbyname_r(const char *name
, struct hostent
*hp
, char *buf
, size_t buflen
,
525 res_state res
= __res_get_state();
528 *he
= NETDB_INTERNAL
;
532 _DIAGASSERT(name
!= NULL
);
534 if (res
->options
& RES_USE_INET6
) {
535 struct hostent
*nhp
= gethostbyname_internal(name
, AF_INET6
,
536 res
, hp
, buf
, buflen
, he
);
538 __res_put_state(res
);
542 hp
= gethostbyname_internal(name
, AF_INET
, res
, hp
, buf
, buflen
, he
);
543 __res_put_state(res
);
548 gethostbyname2_r(const char *name
, int af
, struct hostent
*hp
, char *buf
,
549 size_t buflen
, int *he
)
551 res_state res
= __res_get_state();
554 *he
= NETDB_INTERNAL
;
557 hp
= gethostbyname_internal(name
, af
, res
, hp
, buf
, buflen
, he
);
558 __res_put_state(res
);
562 static struct hostent
*
563 gethostbyname_internal(const char *name
, int af
, res_state res
,
564 struct hostent
*hp
, char *buf
, size_t buflen
, int *he
)
567 struct getnamaddr info
;
568 char hbuf
[MAXHOSTNAMELEN
];
570 static const ns_dtab dtab
[] = {
571 NS_FILES_CB(_hf_gethtbyname
, NULL
)
572 { NSSRC_DNS
, _dns_gethtbyname
, NULL
}, /* force -DHESIOD */
573 NS_NIS_CB(_yp_gethtbyname
, NULL
)
577 _DIAGASSERT(name
!= NULL
);
587 *he
= NETDB_INTERNAL
;
588 errno
= EAFNOSUPPORT
;
595 hp
->h_length
= (int)size
;
598 * if there aren't any dots, it could be a user-level alias.
599 * this is also done in res_nquery() since we are not the only
600 * function that looks up host names.
602 if (!strchr(name
, '.') && (cp
= res_hostalias(res
, name
,
603 hbuf
, sizeof(hbuf
))))
607 * disallow names consisting only of digits/dots, unless
610 if (isdigit((u_char
) name
[0]))
611 for (cp
= name
;; ++cp
) {
616 * All-numeric, no dot at the end.
617 * Fake up a hostent as if we'd actually
622 if (!isdigit((u_char
) *cp
) && *cp
!= '.')
625 if ((isxdigit((u_char
) name
[0]) && strchr(name
, ':') != NULL
) ||
627 for (cp
= name
;; ++cp
) {
632 * All-IPv6-legal, no dot at the end.
633 * Fake up a hostent as if we'd actually
638 if (!isxdigit((u_char
) *cp
) && *cp
!= ':' && *cp
!= '.')
642 *he
= NETDB_INTERNAL
;
645 info
.buflen
= buflen
;
647 if (nsdispatch(&info
, dtab
, NSDB_HOSTS
, "gethostbyname",
648 default_dns_files
, name
, strlen(name
), af
) != NS_SUCCESS
)
653 *he
= NETDB_INTERNAL
;
657 HENT_ARRAY(hp
->h_addr_list
, 1, buf
, buflen
);
658 HENT_ARRAY(hp
->h_aliases
, 0, buf
, buflen
);
660 hp
->h_aliases
[0] = NULL
;
664 if (inet_pton(af
, name
, buf
) <= 0) {
665 *he
= HOST_NOT_FOUND
;
668 hp
->h_addr_list
[0] = buf
;
669 hp
->h_addr_list
[1] = NULL
;
672 HENT_SCOPY(hp
->h_name
, name
, buf
, buflen
);
673 if (res
->options
& RES_USE_INET6
)
674 map_v4v6_hostent(hp
, &buf
, buf
+ buflen
);
680 gethostbyaddr_r(const void *addr
, socklen_t len
, int af
, struct hostent
*hp
,
681 char *buf
, size_t buflen
, int *he
)
683 const u_char
*uaddr
= (const u_char
*)addr
;
685 struct getnamaddr info
;
686 static const ns_dtab dtab
[] = {
687 NS_FILES_CB(_hf_gethtbyaddr
, NULL
)
688 { NSSRC_DNS
, _dns_gethtbyaddr
, NULL
}, /* force -DHESIOD */
689 NS_NIS_CB(_yp_gethtbyaddr
, NULL
)
693 _DIAGASSERT(addr
!= NULL
);
695 if (af
== AF_INET6
&& len
== NS_IN6ADDRSZ
&&
696 (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr
*)addr
) ||
697 IN6_IS_ADDR_SITELOCAL((const struct in6_addr
*)addr
))) {
698 *he
= HOST_NOT_FOUND
;
701 if (af
== AF_INET6
&& len
== NS_IN6ADDRSZ
&&
702 (IN6_IS_ADDR_V4MAPPED((const struct in6_addr
*)addr
) ||
703 IN6_IS_ADDR_V4COMPAT((const struct in6_addr
*)addr
))) {
705 uaddr
+= NS_IN6ADDRSZ
- NS_INADDRSZ
;
718 errno
= EAFNOSUPPORT
;
719 *he
= NETDB_INTERNAL
;
724 *he
= NETDB_INTERNAL
;
729 info
.buflen
= buflen
;
731 *he
= NETDB_INTERNAL
;
732 if (nsdispatch(&info
, dtab
, NSDB_HOSTS
, "gethostbyaddr",
733 default_dns_files
, uaddr
, len
, af
) != NS_SUCCESS
)
740 gethostent_r(FILE *hf
, struct hostent
*hent
, char *buf
, size_t buflen
, int *he
)
748 struct in6_addr host_addr
;
751 *he
= NETDB_INTERNAL
;
756 setup(aliases
, maxaliases
);
759 p
= fparseln(hf
, NULL
, NULL
, NULL
, FPARSELN_UNESCALL
);
762 *he
= HOST_NOT_FOUND
;
765 if (!(cp
= strpbrk(p
, " \t")))
768 if (inet_pton(AF_INET6
, p
, &host_addr
) > 0) {
772 if (inet_pton(AF_INET
, p
, &host_addr
) <= 0)
775 res_state res
= __res_get_state();
778 if (res
->options
& RES_USE_INET6
) {
779 map_v4v6_address(buf
, buf
);
786 __res_put_state(res
);
789 /* if this is not something we're looking for, skip it. */
790 if (hent
->h_addrtype
!= 0 && hent
->h_addrtype
!= af
)
792 if (hent
->h_length
!= 0 && hent
->h_length
!= len
)
795 while (*cp
== ' ' || *cp
== '\t')
797 if ((cp
= strpbrk(name
= cp
, " \t")) != NULL
)
801 if (*cp
== ' ' || *cp
== '\t') {
805 addalias(q
, cp
, aliases
, maxaliases
);
806 if ((cp
= strpbrk(cp
, " \t")) != NULL
)
811 hent
->h_length
= len
;
812 hent
->h_addrtype
= af
;
813 HENT_ARRAY(hent
->h_addr_list
, 1, buf
, buflen
);
814 anum
= (size_t)(q
- aliases
);
815 HENT_ARRAY(hent
->h_aliases
, anum
, buf
, buflen
);
816 HENT_COPY(hent
->h_addr_list
[0], &host_addr
, hent
->h_length
, buf
,
818 hent
->h_addr_list
[1] = NULL
;
820 HENT_SCOPY(hent
->h_name
, name
, buf
, buflen
);
821 for (size_t i
= 0; i
< anum
; i
++)
822 HENT_SCOPY(hent
->h_aliases
[i
], aliases
[i
], buf
, buflen
);
823 hent
->h_aliases
[anum
] = NULL
;
833 *he
= NETDB_INTERNAL
;
838 map_v4v6_address(const char *src
, char *dst
)
840 u_char
*p
= (u_char
*)dst
;
841 char tmp
[NS_INADDRSZ
];
844 _DIAGASSERT(src
!= NULL
);
845 _DIAGASSERT(dst
!= NULL
);
847 /* Stash a temporary copy so our caller can update in place. */
848 (void)memcpy(tmp
, src
, NS_INADDRSZ
);
849 /* Mark this ipv6 addr as a mapped ipv4. */
850 for (i
= 0; i
< 10; i
++)
854 /* Retrieve the saved copy and we're done. */
855 (void)memcpy(p
, tmp
, NS_INADDRSZ
);
859 map_v4v6_hostent(struct hostent
*hp
, char **bpp
, char *ep
)
863 _DIAGASSERT(hp
!= NULL
);
864 _DIAGASSERT(bpp
!= NULL
);
865 _DIAGASSERT(ep
!= NULL
);
867 if (hp
->h_addrtype
!= AF_INET
|| hp
->h_length
!= NS_INADDRSZ
)
869 hp
->h_addrtype
= AF_INET6
;
870 hp
->h_length
= NS_IN6ADDRSZ
;
871 for (ap
= hp
->h_addr_list
; *ap
; ap
++) {
872 int i
= (int)(sizeof(align
) -
873 (size_t)((u_long
)*bpp
% sizeof(align
)));
875 if (ep
- *bpp
< (i
+ NS_IN6ADDRSZ
)) {
876 /* Out of memory. Truncate address list here. XXX */
881 map_v4v6_address(*ap
, *bpp
);
883 *bpp
+= NS_IN6ADDRSZ
;
888 addrsort(char **ap
, int num
, res_state res
)
892 short aval
[MAXADDRS
];
895 _DIAGASSERT(ap
!= NULL
);
898 for (i
= 0; i
< num
; i
++, p
++) {
899 for (j
= 0 ; (unsigned)j
< res
->nsort
; j
++)
900 if (res
->sort_list
[j
].addr
.s_addr
==
901 (((struct in_addr
*)(void *)(*p
))->s_addr
&
902 res
->sort_list
[j
].mask
))
905 if (needsort
== 0 && i
> 0 && j
< aval
[i
-1])
911 while (needsort
< num
) {
912 for (j
= needsort
- 1; j
>= 0; j
--) {
913 if (aval
[j
] > aval
[j
+1]) {
933 _dns_gethtbyname(void *rv
, void *cb_data
, va_list ap
)
940 struct getnamaddr
*info
= rv
;
942 _DIAGASSERT(rv
!= NULL
);
944 name
= va_arg(ap
, char *);
945 /* NOSTRICT skip string len */(void)va_arg(ap
, int);
946 info
->hp
->h_addrtype
= va_arg(ap
, int);
948 switch (info
->hp
->h_addrtype
) {
950 info
->hp
->h_length
= NS_INADDRSZ
;
954 info
->hp
->h_length
= NS_IN6ADDRSZ
;
960 buf
= malloc(sizeof(*buf
));
962 *info
->he
= NETDB_INTERNAL
;
965 res
= __res_get_state();
968 *info
->he
= NETDB_INTERNAL
;
971 n
= res_nsearch(res
, name
, C_IN
, type
, buf
->buf
, (int)sizeof(buf
->buf
));
974 debugprintf("res_nsearch failed (%d)\n", res
, n
);
975 __res_put_state(res
);
978 hp
= getanswer(buf
, n
, name
, type
, res
, info
->hp
, info
->buf
,
979 info
->buflen
, info
->he
);
981 __res_put_state(res
);
996 _dns_gethtbyaddr(void *rv
, void *cb_data
, va_list ap
)
998 char qbuf
[MAXDNAME
+ 1], *qp
, *ep
;
1002 const unsigned char *uaddr
;
1007 struct getnamaddr
*info
= rv
;
1009 _DIAGASSERT(rv
!= NULL
);
1011 uaddr
= va_arg(ap
, unsigned char *);
1012 info
->hp
->h_length
= va_arg(ap
, int);
1013 info
->hp
->h_addrtype
= va_arg(ap
, int);
1015 switch (info
->hp
->h_addrtype
) {
1017 (void)snprintf(qbuf
, sizeof(qbuf
), "%u.%u.%u.%u.in-addr.arpa",
1018 (uaddr
[3] & 0xff), (uaddr
[2] & 0xff),
1019 (uaddr
[1] & 0xff), (uaddr
[0] & 0xff));
1024 ep
= qbuf
+ sizeof(qbuf
) - 1;
1025 for (n
= NS_IN6ADDRSZ
- 1; n
>= 0; n
--) {
1026 advance
= snprintf(qp
, (size_t)(ep
- qp
), "%x.%x.",
1028 ((unsigned int)uaddr
[n
] >> 4) & 0xf);
1029 if (advance
> 0 && qp
+ advance
< ep
)
1034 if (strlcat(qbuf
, "ip6.arpa", sizeof(qbuf
)) >= sizeof(qbuf
))
1041 buf
= malloc(sizeof(*buf
));
1045 res
= __res_get_state();
1050 n
= res_nquery(res
, qbuf
, C_IN
, T_PTR
, buf
->buf
, (int)sizeof(buf
->buf
));
1053 debugprintf("res_nquery failed (%d)\n", res
, n
);
1054 __res_put_state(res
);
1055 *info
->he
= HOST_NOT_FOUND
;
1058 hp
= getanswer(buf
, n
, qbuf
, T_PTR
, res
, info
->hp
, info
->buf
,
1059 info
->buflen
, info
->he
);
1062 __res_put_state(res
);
1063 switch (*info
->he
) {
1064 case HOST_NOT_FOUND
:
1073 bf
= (void *)(hp
->h_addr_list
+ 2);
1074 blen
= (size_t)(bf
- info
->buf
);
1075 if (blen
+ info
->hp
->h_length
> info
->buflen
)
1077 hp
->h_addr_list
[0] = bf
;
1078 hp
->h_addr_list
[1] = NULL
;
1079 (void)memcpy(bf
, uaddr
, (size_t)info
->hp
->h_length
);
1080 if (info
->hp
->h_addrtype
== AF_INET
&& (res
->options
& RES_USE_INET6
)) {
1081 if (blen
+ NS_IN6ADDRSZ
> info
->buflen
) {
1082 __res_put_state(res
);
1085 map_v4v6_address(bf
, bf
);
1086 hp
->h_addrtype
= AF_INET6
;
1087 hp
->h_length
= NS_IN6ADDRSZ
;
1090 __res_put_state(res
);
1091 *info
->he
= NETDB_SUCCESS
;
1094 *info
->he
= NETDB_INTERNAL
;
1097 *info
->he
= NO_RECOVERY
;
1103 static struct hostent
*
1104 _yp_hostent(char *line
, int af
, struct getnamaddr
*info
)
1106 struct in6_addr host_addrs
[MAXADDRS
];
1110 char *cp
, **q
, *ptr
;
1111 size_t len
, anum
, i
;
1115 struct hostent
*hp
= info
->hp
;
1117 _DIAGASSERT(line
!= NULL
);
1120 hp
->h_addrtype
= af
;
1123 hp
->h_length
= NS_INADDRSZ
;
1126 hp
->h_length
= NS_IN6ADDRSZ
;
1131 setup(aliases
, maxaliases
);
1136 /* check for host_addrs overflow */
1137 if (naddrs
>= __arraycount(host_addrs
))
1141 cp
= strpbrk(p
, " \t");
1146 /* p has should have an address */
1147 addrok
= inet_pton(af
, p
, &host_addrs
[naddrs
]);
1149 /* skip to the next line */
1161 while (*cp
== ' ' || *cp
== '\t')
1164 cp
= strpbrk(p
, " \t\n");
1172 else if (strcmp(hp
->h_name
, p
) == 0)
1175 addalias(q
, p
, aliases
, maxaliases
);
1181 if (*cp
== ' ' || *cp
== '\t') {
1189 addalias(q
, cp
, aliases
, maxaliases
);
1190 cp
= strpbrk(cp
, " \t");
1196 if (hp
->h_name
== NULL
) {
1204 anum
= (size_t)(q
- aliases
);
1205 HENT_ARRAY(hp
->h_addr_list
, naddrs
, ptr
, len
);
1206 HENT_ARRAY(hp
->h_aliases
, anum
, ptr
, len
);
1208 for (i
= 0; i
< naddrs
; i
++)
1209 HENT_COPY(hp
->h_addr_list
[i
], &host_addrs
[i
], hp
->h_length
,
1211 hp
->h_addr_list
[naddrs
] = NULL
;
1213 HENT_SCOPY(hp
->h_name
, hp
->h_name
, ptr
, len
);
1215 for (i
= 0; i
< anum
; i
++)
1216 HENT_SCOPY(hp
->h_aliases
[i
], aliases
[i
], ptr
, len
);
1217 hp
->h_aliases
[anum
] = NULL
;
1223 *info
->he
= NETDB_INTERNAL
;
1230 _yp_gethtbyaddr(void *rv
, void *cb_data
, va_list ap
)
1232 struct hostent
*hp
= NULL
;
1234 int ypcurrentlen
, r
;
1235 char name
[INET6_ADDRSTRLEN
]; /* XXX enough? */
1236 const unsigned char *uaddr
;
1239 struct getnamaddr
*info
= rv
;
1241 _DIAGASSERT(rv
!= NULL
);
1243 uaddr
= va_arg(ap
, unsigned char *);
1244 /* NOSTRICT skip len */(void)va_arg(ap
, int);
1245 af
= va_arg(ap
, int);
1248 if (_yp_check(&__ypdomain
) == 0)
1252 * XXX unfortunately, we cannot support IPv6 extended scoped address
1253 * notation here. gethostbyaddr() is not scope-aware. too bad.
1255 if (inet_ntop(af
, uaddr
, name
, (socklen_t
)sizeof(name
)) == NULL
)
1259 map
= "hosts.byaddr";
1262 map
= "ipnodes.byaddr";
1266 r
= yp_match(__ypdomain
, map
, name
,
1267 (int)strlen(name
), &ypcurrent
, &ypcurrentlen
);
1269 hp
= _yp_hostent(ypcurrent
, af
, info
);
1274 *info
->he
= HOST_NOT_FOUND
;
1282 _yp_gethtbyname(void *rv
, void *cb_data
, va_list ap
)
1286 int ypcurrentlen
, r
;
1290 struct getnamaddr
*info
= rv
;
1292 _DIAGASSERT(rv
!= NULL
);
1294 name
= va_arg(ap
, char *);
1295 /* NOSTRICT skip string len */(void)va_arg(ap
, int);
1296 af
= va_arg(ap
, int);
1299 if (_yp_check(&__ypdomain
) == 0)
1304 map
= "hosts.byname";
1307 map
= "ipnodes.byname";
1311 r
= yp_match(__ypdomain
, map
, name
,
1312 (int)strlen(name
), &ypcurrent
, &ypcurrentlen
);
1314 hp
= _yp_hostent(ypcurrent
, af
, info
);
1319 *info
->he
= HOST_NOT_FOUND
;
1327 * Non-reentrant versions.
1330 static struct hostent h_ent
;
1331 static char h_buf
[16384];
1334 gethostbyaddr(const void *addr
, socklen_t len
, int af
) {
1335 return gethostbyaddr_r(addr
, len
, af
, &h_ent
, h_buf
, sizeof(h_buf
),
1340 gethostbyname(const char *name
) {
1341 return gethostbyname_r(name
, &h_ent
, h_buf
, sizeof(h_buf
), &h_errno
);
1345 gethostbyname2(const char *name
, int af
) {
1346 return gethostbyname2_r(name
, af
, &h_ent
, h_buf
, sizeof(h_buf
),
1353 if (_h_file
== NULL
) {
1354 sethostent_r(&_h_file
);
1355 if (_h_file
== NULL
) {
1356 h_errno
= NETDB_INTERNAL
;
1360 memset(&h_ent
, 0, sizeof(h_ent
));
1361 return gethostent_r(_h_file
, &h_ent
, h_buf
, sizeof(h_buf
), &h_errno
);