1 /* $NetBSD: gethnamaddr.c,v 1.84 2013/08/27 09:56:12 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.84 2013/08/27 09:56:12 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)
112 static const char AskedForGot
[] =
113 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
117 static char *__ypdomain
;
120 #define MAXPACKET (64*1024)
124 u_char buf
[MAXPACKET
];
133 static void debugprintf(const char *, res_state
, ...)
134 __attribute__((__format__(__printf__
, 1, 3)));
136 static struct hostent
*getanswer(const querybuf
*, int, const char *, int,
137 res_state
, struct hostent
*, char *, size_t, int *);
138 static void map_v4v6_address(const char *, char *);
139 static void map_v4v6_hostent(struct hostent
*, char **, char *);
140 static void addrsort(char **, int, res_state
);
142 void dns_service(void);
144 int dn_skipname(const u_char
*, const u_char
*);
147 static struct hostent
*_yp_hostent(char *, int, struct getnamaddr
*);
150 static struct hostent
*gethostbyname_internal(const char *, int, res_state
,
151 struct hostent
*, char *, size_t, int *);
153 static const ns_src default_dns_files
[] = {
154 { NSSRC_FILES
, NS_SUCCESS
},
155 { NSSRC_DNS
, NS_SUCCESS
},
162 debugprintf(const char *msg
, res_state res
, ...)
164 _DIAGASSERT(msg
!= NULL
);
166 if (res
->options
& RES_DEBUG
) {
178 # define debugprintf(msg, res, num) /*nada*/
181 #define BOUNDED_INCR(x) \
185 h_errno = NO_RECOVERY; \
188 } while (/*CONSTCOND*/0)
190 #define BOUNDS_CHECK(ptr, count) \
192 if ((ptr) + (count) > eom) { \
193 h_errno = NO_RECOVERY; \
196 } while (/*CONSTCOND*/0)
198 static struct hostent
*
199 getanswer(const querybuf
*answer
, int anslen
, const char *qname
, int qtype
,
200 res_state res
, struct hostent
*hent
, char *buf
, size_t buflen
, int *he
)
206 const u_char
*eom
, *erdata
;
207 char *bp
, **ap
, **hap
, *ep
;
208 int type
, class, ancount
, qdcount
;
209 int haveanswer
, had_error
;
212 char *aliases
[MAXALIASES
];
213 char *addr_ptrs
[MAXADDRS
];
215 int (*name_ok
)(const char *);
217 _DIAGASSERT(answer
!= NULL
);
218 _DIAGASSERT(qname
!= NULL
);
222 eom
= answer
->buf
+ anslen
;
232 return NULL
; /* XXX should be abort(); */
235 * find first satisfactory answer
238 ancount
= ntohs(hp
->ancount
);
239 qdcount
= ntohs(hp
->qdcount
);
243 BOUNDED_INCR(HFIXEDSZ
);
247 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, (int)(ep
- bp
));
248 if ((n
< 0) || !maybe_ok(res
, bp
, name_ok
))
251 BOUNDED_INCR(n
+ QFIXEDSZ
);
252 if (qtype
== T_A
|| qtype
== T_AAAA
) {
253 /* res_send() has already verified that the query name is the
254 * same as the one we sent; this just gets the expanded name
255 * (i.e., with the succeeding search-domain tacked on).
257 n
= (int)strlen(bp
) + 1; /* for the \0 */
258 if (n
>= MAXHOSTNAMELEN
)
262 /* The qname can be abbreviated, but h_name is now absolute. */
263 qname
= hent
->h_name
;
265 hent
->h_aliases
= ap
= aliases
;
266 hent
->h_addr_list
= hap
= addr_ptrs
;
271 while (ancount
-- > 0 && cp
< eom
&& !had_error
) {
272 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, (int)(ep
- bp
));
273 if ((n
< 0) || !maybe_ok(res
, bp
, name_ok
)) {
278 BOUNDS_CHECK(cp
, 3 * INT16SZ
+ INT32SZ
);
279 type
= _getshort(cp
);
280 cp
+= INT16SZ
; /* type */
281 class = _getshort(cp
);
282 cp
+= INT16SZ
+ INT32SZ
; /* class, TTL */
284 cp
+= INT16SZ
; /* len */
288 /* XXX - debug? syslog? */
290 continue; /* XXX - had_error++ ? */
292 if ((qtype
== T_A
|| qtype
== T_AAAA
) && type
== T_CNAME
) {
293 if (ap
>= &aliases
[MAXALIASES
-1])
295 n
= dn_expand(answer
->buf
, eom
, cp
, tbuf
,
297 if ((n
< 0) || !maybe_ok(res
, tbuf
, name_ok
)) {
306 n
= (int)strlen(bp
) + 1; /* for the \0 */
307 if (n
>= MAXHOSTNAMELEN
) {
312 /* Get canonical name. */
313 n
= (int)strlen(tbuf
) + 1; /* for the \0 */
314 if (n
> ep
- bp
|| n
>= MAXHOSTNAMELEN
) {
318 strlcpy(bp
, tbuf
, (size_t)(ep
- bp
));
323 if (qtype
== T_PTR
&& type
== T_CNAME
) {
324 n
= dn_expand(answer
->buf
, eom
, cp
, tbuf
,
326 if (n
< 0 || !maybe_dnok(res
, tbuf
)) {
333 /* Get canonical name. */
334 n
= (int)strlen(tbuf
) + 1; /* for the \0 */
335 if (n
> ep
- bp
|| n
>= MAXHOSTNAMELEN
) {
339 strlcpy(bp
, tbuf
, (size_t)(ep
- bp
));
345 if (type
!= T_KEY
&& type
!= T_SIG
)
346 syslog(LOG_NOTICE
|LOG_AUTH
,
347 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
348 qname
, p_class(C_IN
), p_type(qtype
),
351 continue; /* XXX - had_error++ ? */
355 if (strcasecmp(tname
, bp
) != 0) {
356 syslog(LOG_NOTICE
|LOG_AUTH
,
357 AskedForGot
, qname
, bp
);
359 continue; /* XXX - had_error++ ? */
361 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, (int)(ep
- bp
));
362 if ((n
< 0) || !maybe_hnok(res
, bp
)) {
366 #if MULTI_PTRS_ARE_ALIASES
372 else if (ap
< &aliases
[MAXALIASES
-1])
377 n
= (int)strlen(bp
) + 1; /* for the \0 */
378 if (n
>= MAXHOSTNAMELEN
) {
387 if (res
->options
& RES_USE_INET6
) {
388 n
= strlen(bp
) + 1; /* for the \0 */
389 if (n
>= MAXHOSTNAMELEN
) {
394 map_v4v6_hostent(hent
, &bp
, ep
);
400 if (strcasecmp(hent
->h_name
, bp
) != 0) {
401 syslog(LOG_NOTICE
|LOG_AUTH
,
402 AskedForGot
, hent
->h_name
, bp
);
404 continue; /* XXX - had_error++ ? */
406 if (n
!= hent
->h_length
) {
410 if (type
== T_AAAA
) {
412 memcpy(&in6
, cp
, NS_IN6ADDRSZ
);
413 if (IN6_IS_ADDR_V4MAPPED(&in6
)) {
422 nn
= (int)strlen(bp
) + 1; /* for the \0 */
426 bp
+= sizeof(align
) -
427 (size_t)((u_long
)bp
% sizeof(align
));
430 debugprintf("size (%d) too big\n", res
, n
);
434 if (hap
>= &addr_ptrs
[MAXADDRS
- 1]) {
436 debugprintf("Too many addresses (%d)\n",
442 (void)memcpy(*hap
++ = bp
, cp
, (size_t)n
);
458 * Note: we sort even if host can take only one address
459 * in its return structures - should give it the "best"
460 * address in that case, not some random one
462 if (res
->nsort
&& haveanswer
> 1 && qtype
== T_A
)
463 addrsort(addr_ptrs
, haveanswer
, res
);
465 n
= (int)strlen(qname
) + 1; /* for the \0 */
466 if (n
> ep
- bp
|| n
>= MAXHOSTNAMELEN
)
468 strlcpy(bp
, qname
, (size_t)(ep
- bp
));
472 if (res
->options
& RES_USE_INET6
)
473 map_v4v6_hostent(hent
, &bp
, ep
);
480 bp
= (char *)ALIGN(bp
);
481 n
= (int)(ap
- aliases
);
482 qlen
= (n
+ 1) * sizeof(*hent
->h_aliases
);
483 if ((size_t)(ep
- bp
) < qlen
)
485 hent
->h_aliases
= (void *)bp
;
486 memcpy(bp
, aliases
, qlen
);
489 n
= (int)(hap
- addr_ptrs
);
490 qlen
= (n
+ 1) * sizeof(*hent
->h_addr_list
);
491 if ((size_t)(ep
- bp
) < qlen
)
493 hent
->h_addr_list
= (void *)bp
;
494 memcpy(bp
, addr_ptrs
, qlen
);
499 *he
= NETDB_INTERNAL
;
504 gethostbyname_r(const char *name
, struct hostent
*hp
, char *buf
, size_t buflen
,
507 res_state res
= __res_get_state();
510 *he
= NETDB_INTERNAL
;
514 _DIAGASSERT(name
!= NULL
);
516 if (res
->options
& RES_USE_INET6
) {
517 hp
= gethostbyname_internal(name
, AF_INET6
, res
, hp
, buf
,
520 __res_put_state(res
);
524 hp
= gethostbyname_internal(name
, AF_INET
, res
, hp
, buf
, buflen
, he
);
525 __res_put_state(res
);
530 gethostbyname2_r(const char *name
, int af
, struct hostent
*hp
, char *buf
,
531 size_t buflen
, int *he
)
533 res_state res
= __res_get_state();
536 *he
= NETDB_INTERNAL
;
539 hp
= gethostbyname_internal(name
, af
, res
, hp
, buf
, buflen
, he
);
540 __res_put_state(res
);
544 static struct hostent
*
545 gethostbyname_internal(const char *name
, int af
, res_state res
,
546 struct hostent
*hp
, char *buf
, size_t buflen
, int *he
)
549 struct getnamaddr info
;
551 static const ns_dtab dtab
[] = {
552 NS_FILES_CB(_hf_gethtbyname
, NULL
)
553 { NSSRC_DNS
, _dns_gethtbyname
, NULL
}, /* force -DHESIOD */
554 NS_NIS_CB(_yp_gethtbyname
, NULL
)
558 _DIAGASSERT(name
!= NULL
);
568 *he
= NETDB_INTERNAL
;
569 errno
= EAFNOSUPPORT
;
576 hp
->h_length
= (int)size
;
579 * if there aren't any dots, it could be a user-level alias.
580 * this is also done in res_nquery() since we are not the only
581 * function that looks up host names.
583 if (!strchr(name
, '.') && (cp
= __hostalias(name
)))
587 * disallow names consisting only of digits/dots, unless
590 if (isdigit((u_char
) name
[0]))
591 for (cp
= name
;; ++cp
) {
596 * All-numeric, no dot at the end.
597 * Fake up a hostent as if we'd actually
602 if (!isdigit((u_char
) *cp
) && *cp
!= '.')
605 if ((isxdigit((u_char
) name
[0]) && strchr(name
, ':') != NULL
) ||
607 for (cp
= name
;; ++cp
) {
612 * All-IPv6-legal, no dot at the end.
613 * Fake up a hostent as if we'd actually
618 if (!isxdigit((u_char
) *cp
) && *cp
!= ':' && *cp
!= '.')
622 *he
= NETDB_INTERNAL
;
625 info
.buflen
= buflen
;
627 if (nsdispatch(&info
, dtab
, NSDB_HOSTS
, "gethostbyname",
628 default_dns_files
, name
, strlen(name
), af
) != NS_SUCCESS
)
633 *he
= NETDB_INTERNAL
;
637 HENT_ARRAY(hp
->h_addr_list
, 1, buf
, buflen
);
638 HENT_ARRAY(hp
->h_aliases
, 0, buf
, buflen
);
640 hp
->h_aliases
[0] = NULL
;
644 if (inet_pton(af
, name
, buf
) <= 0) {
645 *he
= HOST_NOT_FOUND
;
648 hp
->h_addr_list
[0] = buf
;
649 hp
->h_addr_list
[1] = NULL
;
652 HENT_SCOPY(hp
->h_name
, name
, buf
, buflen
);
653 if (res
->options
& RES_USE_INET6
)
654 map_v4v6_hostent(hp
, &buf
, buf
+ buflen
);
660 gethostbyaddr_r(const void *addr
, socklen_t len
, int af
, struct hostent
*hp
,
661 char *buf
, size_t buflen
, int *he
)
663 const u_char
*uaddr
= (const u_char
*)addr
;
665 struct getnamaddr info
;
666 static const ns_dtab dtab
[] = {
667 NS_FILES_CB(_hf_gethtbyaddr
, NULL
)
668 { NSSRC_DNS
, _dns_gethtbyaddr
, NULL
}, /* force -DHESIOD */
669 NS_NIS_CB(_yp_gethtbyaddr
, NULL
)
673 _DIAGASSERT(addr
!= NULL
);
675 if (af
== AF_INET6
&& len
== NS_IN6ADDRSZ
&&
676 (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr
*)addr
) ||
677 IN6_IS_ADDR_SITELOCAL((const struct in6_addr
*)addr
))) {
678 *he
= HOST_NOT_FOUND
;
681 if (af
== AF_INET6
&& len
== NS_IN6ADDRSZ
&&
682 (IN6_IS_ADDR_V4MAPPED((const struct in6_addr
*)addr
) ||
683 IN6_IS_ADDR_V4COMPAT((const struct in6_addr
*)addr
))) {
685 uaddr
+= NS_IN6ADDRSZ
- NS_INADDRSZ
;
698 errno
= EAFNOSUPPORT
;
699 *he
= NETDB_INTERNAL
;
704 *he
= NETDB_INTERNAL
;
709 info
.buflen
= buflen
;
711 *he
= NETDB_INTERNAL
;
712 if (nsdispatch(&info
, dtab
, NSDB_HOSTS
, "gethostbyaddr",
713 default_dns_files
, uaddr
, len
, af
) != NS_SUCCESS
)
720 gethostent_r(FILE *hf
, struct hostent
*hent
, char *buf
, size_t buflen
, int *he
)
726 char *aliases
[MAXALIASES
];
727 struct in6_addr host_addr
;
730 *he
= NETDB_INTERNAL
;
735 if ((p
= fgetln(hf
, &llen
)) == NULL
) {
736 *he
= HOST_NOT_FOUND
;
744 if (!(cp
= strpbrk(p
, "#\n")))
747 if (!(cp
= strpbrk(p
, " \t")))
750 if (inet_pton(AF_INET6
, p
, &host_addr
) > 0) {
753 } else if (inet_pton(AF_INET
, p
, &host_addr
) > 0) {
754 res_state res
= __res_get_state();
757 if (res
->options
& RES_USE_INET6
) {
758 map_v4v6_address(buf
, buf
);
765 __res_put_state(res
);
769 /* if this is not something we're looking for, skip it. */
770 if (hent
->h_addrtype
!= 0 && hent
->h_addrtype
!= af
)
772 if (hent
->h_length
!= 0 && hent
->h_length
!= len
)
775 while (*cp
== ' ' || *cp
== '\t')
777 if ((cp
= strpbrk(name
= cp
, " \t")) != NULL
)
781 if (*cp
== ' ' || *cp
== '\t') {
785 if (q
>= &aliases
[__arraycount(aliases
)])
788 if ((cp
= strpbrk(cp
, " \t")) != NULL
)
791 hent
->h_length
= len
;
792 hent
->h_addrtype
= af
;
793 HENT_ARRAY(hent
->h_addr_list
, 1, buf
, buflen
);
794 anum
= (size_t)(q
- aliases
);
795 HENT_ARRAY(hent
->h_aliases
, anum
, buf
, buflen
);
796 HENT_COPY(hent
->h_addr_list
[0], &host_addr
, hent
->h_length
, buf
,
798 hent
->h_addr_list
[1] = NULL
;
800 HENT_SCOPY(hent
->h_name
, name
, buf
, buflen
);
801 for (size_t i
= 0; i
< anum
; i
++)
802 HENT_SCOPY(hent
->h_aliases
[i
], aliases
[i
], buf
, buflen
);
803 hent
->h_aliases
[anum
] = NULL
;
809 *he
= NETDB_INTERNAL
;
814 map_v4v6_address(const char *src
, char *dst
)
816 u_char
*p
= (u_char
*)dst
;
817 char tmp
[NS_INADDRSZ
];
820 _DIAGASSERT(src
!= NULL
);
821 _DIAGASSERT(dst
!= NULL
);
823 /* Stash a temporary copy so our caller can update in place. */
824 (void)memcpy(tmp
, src
, NS_INADDRSZ
);
825 /* Mark this ipv6 addr as a mapped ipv4. */
826 for (i
= 0; i
< 10; i
++)
830 /* Retrieve the saved copy and we're done. */
831 (void)memcpy(p
, tmp
, NS_INADDRSZ
);
835 map_v4v6_hostent(struct hostent
*hp
, char **bpp
, char *ep
)
839 _DIAGASSERT(hp
!= NULL
);
840 _DIAGASSERT(bpp
!= NULL
);
841 _DIAGASSERT(ep
!= NULL
);
843 if (hp
->h_addrtype
!= AF_INET
|| hp
->h_length
!= NS_INADDRSZ
)
845 hp
->h_addrtype
= AF_INET6
;
846 hp
->h_length
= NS_IN6ADDRSZ
;
847 for (ap
= hp
->h_addr_list
; *ap
; ap
++) {
848 int i
= (int)(sizeof(align
) -
849 (size_t)((u_long
)*bpp
% sizeof(align
)));
851 if (ep
- *bpp
< (i
+ NS_IN6ADDRSZ
)) {
852 /* Out of memory. Truncate address list here. XXX */
857 map_v4v6_address(*ap
, *bpp
);
859 *bpp
+= NS_IN6ADDRSZ
;
864 addrsort(char **ap
, int num
, res_state res
)
868 short aval
[MAXADDRS
];
871 _DIAGASSERT(ap
!= NULL
);
874 for (i
= 0; i
< num
; i
++, p
++) {
875 for (j
= 0 ; (unsigned)j
< res
->nsort
; j
++)
876 if (res
->sort_list
[j
].addr
.s_addr
==
877 (((struct in_addr
*)(void *)(*p
))->s_addr
&
878 res
->sort_list
[j
].mask
))
881 if (needsort
== 0 && i
> 0 && j
< aval
[i
-1])
887 while (needsort
< num
) {
888 for (j
= needsort
- 1; j
>= 0; j
--) {
889 if (aval
[j
] > aval
[j
+1]) {
909 _dns_gethtbyname(void *rv
, void *cb_data
, va_list ap
)
916 struct getnamaddr
*info
= rv
;
918 _DIAGASSERT(rv
!= NULL
);
920 name
= va_arg(ap
, char *);
921 /* NOSTRICT skip string len */(void)va_arg(ap
, int);
922 info
->hp
->h_addrtype
= va_arg(ap
, int);
924 switch (info
->hp
->h_addrtype
) {
926 info
->hp
->h_length
= NS_INADDRSZ
;
930 info
->hp
->h_length
= NS_IN6ADDRSZ
;
936 buf
= malloc(sizeof(*buf
));
938 *info
->he
= NETDB_INTERNAL
;
941 res
= __res_get_state();
946 n
= res_nsearch(res
, name
, C_IN
, type
, buf
->buf
, (int)sizeof(buf
->buf
));
949 debugprintf("res_nsearch failed (%d)\n", res
, n
);
950 __res_put_state(res
);
953 hp
= getanswer(buf
, n
, name
, type
, res
, info
->hp
, info
->buf
,
954 info
->buflen
, info
->he
);
956 __res_put_state(res
);
971 _dns_gethtbyaddr(void *rv
, void *cb_data
, va_list ap
)
973 char qbuf
[MAXDNAME
+ 1], *qp
, *ep
;
977 const unsigned char *uaddr
;
982 struct getnamaddr
*info
= rv
;
984 _DIAGASSERT(rv
!= NULL
);
986 uaddr
= va_arg(ap
, unsigned char *);
987 info
->hp
->h_length
= va_arg(ap
, int);
988 info
->hp
->h_addrtype
= va_arg(ap
, int);
990 switch (info
->hp
->h_addrtype
) {
992 (void)snprintf(qbuf
, sizeof(qbuf
), "%u.%u.%u.%u.in-addr.arpa",
993 (uaddr
[3] & 0xff), (uaddr
[2] & 0xff),
994 (uaddr
[1] & 0xff), (uaddr
[0] & 0xff));
999 ep
= qbuf
+ sizeof(qbuf
) - 1;
1000 for (n
= NS_IN6ADDRSZ
- 1; n
>= 0; n
--) {
1001 advance
= snprintf(qp
, (size_t)(ep
- qp
), "%x.%x.",
1003 ((unsigned int)uaddr
[n
] >> 4) & 0xf);
1004 if (advance
> 0 && qp
+ advance
< ep
)
1007 *info
->he
= NETDB_INTERNAL
;
1011 if (strlcat(qbuf
, "ip6.arpa", sizeof(qbuf
)) >= sizeof(qbuf
)) {
1012 *info
->he
= NETDB_INTERNAL
;
1020 buf
= malloc(sizeof(*buf
));
1022 *info
->he
= NETDB_INTERNAL
;
1025 res
= __res_get_state();
1030 n
= res_nquery(res
, qbuf
, C_IN
, T_PTR
, buf
->buf
, (int)sizeof(buf
->buf
));
1033 debugprintf("res_nquery failed (%d)\n", res
, n
);
1034 __res_put_state(res
);
1037 hp
= getanswer(buf
, n
, qbuf
, T_PTR
, res
, info
->hp
, info
->buf
,
1038 info
->buflen
, info
->he
);
1041 __res_put_state(res
);
1042 switch (*info
->he
) {
1043 case HOST_NOT_FOUND
:
1052 bf
= (void *)(hp
->h_addr_list
+ 2);
1053 blen
= (size_t)(bf
- info
->buf
);
1054 if (blen
+ info
->hp
->h_length
> info
->buflen
)
1056 hp
->h_addr_list
[0] = bf
;
1057 hp
->h_addr_list
[1] = NULL
;
1058 (void)memcpy(bf
, uaddr
, (size_t)info
->hp
->h_length
);
1059 if (info
->hp
->h_addrtype
== AF_INET
&& (res
->options
& RES_USE_INET6
)) {
1060 if (blen
+ NS_IN6ADDRSZ
> info
->buflen
)
1062 map_v4v6_address(bf
, bf
);
1063 hp
->h_addrtype
= AF_INET6
;
1064 hp
->h_length
= NS_IN6ADDRSZ
;
1067 __res_put_state(res
);
1068 *info
->he
= NETDB_SUCCESS
;
1071 *info
->he
= NETDB_INTERNAL
;
1077 static struct hostent
*
1078 _yp_hostent(char *line
, int af
, struct getnamaddr
*info
)
1080 struct in6_addr host_addrs
[MAXADDRS
];
1081 char *aliases
[MAXALIASES
];
1083 char *cp
, **q
, *ptr
;
1084 size_t len
, anum
, i
;
1088 struct hostent
*hp
= info
->hp
;
1090 _DIAGASSERT(line
!= NULL
);
1093 hp
->h_addrtype
= af
;
1096 hp
->h_length
= NS_INADDRSZ
;
1099 hp
->h_length
= NS_IN6ADDRSZ
;
1108 /* check for host_addrs overflow */
1109 if (naddrs
>= __arraycount(host_addrs
))
1113 cp
= strpbrk(p
, " \t");
1118 /* p has should have an address */
1119 addrok
= inet_pton(af
, p
, &host_addrs
[naddrs
]);
1121 /* skip to the next line */
1132 while (*cp
== ' ' || *cp
== '\t')
1135 cp
= strpbrk(p
, " \t\n");
1143 else if (strcmp(hp
->h_name
, p
) == 0)
1145 else if (q
< &aliases
[MAXALIASES
- 1])
1152 if (*cp
== ' ' || *cp
== '\t') {
1160 if (q
< &aliases
[MAXALIASES
- 1])
1162 cp
= strpbrk(cp
, " \t");
1168 if (hp
->h_name
== NULL
)
1174 anum
= (size_t)(q
- aliases
);
1175 HENT_ARRAY(hp
->h_addr_list
, naddrs
, ptr
, len
);
1176 HENT_ARRAY(hp
->h_aliases
, anum
, ptr
, len
);
1178 for (i
= 0; i
< naddrs
; i
++)
1179 HENT_COPY(hp
->h_addr_list
[i
], &host_addrs
[i
], hp
->h_length
,
1181 hp
->h_addr_list
[naddrs
] = NULL
;
1183 HENT_SCOPY(hp
->h_name
, hp
->h_name
, ptr
, len
);
1185 for (i
= 0; i
< anum
; i
++)
1186 HENT_SCOPY(hp
->h_aliases
[i
], aliases
[i
], ptr
, len
);
1187 hp
->h_aliases
[anum
] = NULL
;
1191 *info
->he
= NETDB_INTERNAL
;
1198 _yp_gethtbyaddr(void *rv
, void *cb_data
, va_list ap
)
1200 struct hostent
*hp
= NULL
;
1202 int ypcurrentlen
, r
;
1203 char name
[INET6_ADDRSTRLEN
]; /* XXX enough? */
1204 const unsigned char *uaddr
;
1207 struct getnamaddr
*info
= rv
;
1209 _DIAGASSERT(rv
!= NULL
);
1211 uaddr
= va_arg(ap
, unsigned char *);
1212 /* NOSTRICT skip len */(void)va_arg(ap
, int);
1213 af
= va_arg(ap
, int);
1216 if (_yp_check(&__ypdomain
) == 0)
1220 * XXX unfortunately, we cannot support IPv6 extended scoped address
1221 * notation here. gethostbyaddr() is not scope-aware. too bad.
1223 if (inet_ntop(af
, uaddr
, name
, (socklen_t
)sizeof(name
)) == NULL
)
1227 map
= "hosts.byaddr";
1230 map
= "ipnodes.byaddr";
1234 r
= yp_match(__ypdomain
, map
, name
,
1235 (int)strlen(name
), &ypcurrent
, &ypcurrentlen
);
1237 hp
= _yp_hostent(ypcurrent
, af
, info
);
1242 *info
->he
= HOST_NOT_FOUND
;
1250 _yp_gethtbyname(void *rv
, void *cb_data
, va_list ap
)
1254 int ypcurrentlen
, r
;
1258 struct getnamaddr
*info
= rv
;
1260 _DIAGASSERT(rv
!= NULL
);
1262 name
= va_arg(ap
, char *);
1263 /* NOSTRICT skip string len */(void)va_arg(ap
, int);
1264 af
= va_arg(ap
, int);
1267 if (_yp_check(&__ypdomain
) == 0)
1272 map
= "hosts.byname";
1275 map
= "ipnodes.byname";
1279 r
= yp_match(__ypdomain
, map
, name
,
1280 (int)strlen(name
), &ypcurrent
, &ypcurrentlen
);
1282 hp
= _yp_hostent(ypcurrent
, af
, info
);
1287 *info
->he
= HOST_NOT_FOUND
;
1295 * Non-reentrant versions.
1298 static struct hostent h_ent
;
1299 static char h_buf
[16384];
1302 gethostbyaddr(const void *addr
, socklen_t len
, int af
) {
1303 return gethostbyaddr_r(addr
, len
, af
, &h_ent
, h_buf
, sizeof(h_buf
),
1308 gethostbyname(const char *name
) {
1309 return gethostbyname_r(name
, &h_ent
, h_buf
, sizeof(h_buf
), &h_errno
);
1313 gethostbyname2(const char *name
, int af
) {
1314 return gethostbyname2_r(name
, af
, &h_ent
, h_buf
, sizeof(h_buf
),
1321 if (_h_file
== NULL
) {
1322 sethostent_r(&_h_file
);
1323 if (_h_file
== NULL
) {
1324 h_errno
= NETDB_INTERNAL
;
1328 memset(&h_ent
, 0, sizeof(h_ent
));
1329 return gethostent_r(_h_file
, &h_ent
, h_buf
, sizeof(h_buf
), &h_errno
);