1 /* $NetBSD: gethnamaddr.c,v 1.79 2012/09/09 16:42:23 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.79 2012/09/09 16:42:23 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>
98 #if defined(_LIBC) && defined(__weak_alias)
99 __weak_alias(gethostbyaddr
,_gethostbyaddr
)
100 __weak_alias(gethostbyname
,_gethostbyname
)
101 __weak_alias(gethostent
,_gethostent
)
104 #define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0U || \
106 #define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok)
107 #define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok)
110 #define MAXALIASES 35
113 static const char AskedForGot
[] =
114 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
116 static char *h_addr_ptrs
[MAXADDRS
+ 1];
119 static char *__ypdomain
;
122 static struct hostent host
;
123 static char *host_aliases
[MAXALIASES
];
124 static char hostbuf
[8*1024];
125 static u_int32_t host_addr
[16 / sizeof(u_int32_t
)]; /* IPv4 or IPv6 */
126 static FILE *hostf
= NULL
;
127 static int stayopen
= 0;
129 #define MAXPACKET (64*1024)
133 u_char buf
[MAXPACKET
];
142 static void debugprintf(const char *, res_state
, ...)
143 __attribute__((__format__(__printf__
, 1, 3)));
145 static struct hostent
*getanswer(const querybuf
*, int, const char *, int,
147 static void map_v4v6_address(const char *, char *);
148 static void map_v4v6_hostent(struct hostent
*, char **, char *);
149 static void addrsort(char **, int, res_state
);
152 void _endhtent(void);
153 struct hostent
*_gethtent(void);
154 void ht_sethostent(int);
155 void ht_endhostent(void);
156 struct hostent
*ht_gethostbyname(char *);
157 struct hostent
*ht_gethostbyaddr(const char *, int, int);
158 void dns_service(void);
160 int dn_skipname(const u_char
*, const u_char
*);
161 int _gethtbyaddr(void *, void *, va_list);
162 int _gethtbyname(void *, void *, va_list);
163 struct hostent
*_gethtbyname2(const char *, int);
164 int _dns_gethtbyaddr(void *, void *, va_list);
165 int _dns_gethtbyname(void *, void *, va_list);
167 struct hostent
*_yphostent(char *, int);
168 int _yp_gethtbyaddr(void *, void *, va_list);
169 int _yp_gethtbyname(void *, void *, va_list);
172 static struct hostent
*gethostbyname_internal(const char *, int, res_state
);
174 static const ns_src default_dns_files
[] = {
175 { NSSRC_FILES
, NS_SUCCESS
},
176 { NSSRC_DNS
, NS_SUCCESS
},
183 debugprintf(const char *msg
, res_state res
, ...)
185 _DIAGASSERT(msg
!= NULL
);
187 if (res
->options
& RES_DEBUG
) {
199 # define debugprintf(msg, res, num) /*nada*/
202 #define BOUNDED_INCR(x) \
206 h_errno = NO_RECOVERY; \
209 } while (/*CONSTCOND*/0)
211 #define BOUNDS_CHECK(ptr, count) \
213 if ((ptr) + (count) > eom) { \
214 h_errno = NO_RECOVERY; \
217 } while (/*CONSTCOND*/0)
219 static struct hostent
*
220 getanswer(const querybuf
*answer
, int anslen
, const char *qname
, int qtype
,
226 const u_char
*eom
, *erdata
;
227 char *bp
, **ap
, **hap
, *ep
;
228 int type
, class, ancount
, qdcount
;
229 int haveanswer
, had_error
;
233 int (*name_ok
)(const char *);
235 _DIAGASSERT(answer
!= NULL
);
236 _DIAGASSERT(qname
!= NULL
);
240 eom
= answer
->buf
+ anslen
;
250 return NULL
; /* XXX should be abort(); */
253 * find first satisfactory answer
256 ancount
= ntohs(hp
->ancount
);
257 qdcount
= ntohs(hp
->qdcount
);
259 ep
= hostbuf
+ sizeof hostbuf
;
261 BOUNDED_INCR(HFIXEDSZ
);
263 h_errno
= NO_RECOVERY
;
266 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, (int)(ep
- bp
));
267 if ((n
< 0) || !maybe_ok(res
, bp
, name_ok
)) {
268 h_errno
= NO_RECOVERY
;
271 BOUNDED_INCR(n
+ QFIXEDSZ
);
272 if (qtype
== T_A
|| qtype
== T_AAAA
) {
273 /* res_send() has already verified that the query name is the
274 * same as the one we sent; this just gets the expanded name
275 * (i.e., with the succeeding search-domain tacked on).
277 n
= (int)strlen(bp
) + 1; /* for the \0 */
278 if (n
>= MAXHOSTNAMELEN
) {
279 h_errno
= NO_RECOVERY
;
284 /* The qname can be abbreviated, but h_name is now absolute. */
289 host
.h_aliases
= host_aliases
;
292 host
.h_addr_list
= h_addr_ptrs
;
295 while (ancount
-- > 0 && cp
< eom
&& !had_error
) {
296 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, (int)(ep
- bp
));
297 if ((n
< 0) || !maybe_ok(res
, bp
, name_ok
)) {
302 BOUNDS_CHECK(cp
, 3 * INT16SZ
+ INT32SZ
);
303 type
= _getshort(cp
);
304 cp
+= INT16SZ
; /* type */
305 class = _getshort(cp
);
306 cp
+= INT16SZ
+ INT32SZ
; /* class, TTL */
308 cp
+= INT16SZ
; /* len */
312 /* XXX - debug? syslog? */
314 continue; /* XXX - had_error++ ? */
316 if ((qtype
== T_A
|| qtype
== T_AAAA
) && type
== T_CNAME
) {
317 if (ap
>= &host_aliases
[MAXALIASES
-1])
319 n
= dn_expand(answer
->buf
, eom
, cp
, tbuf
, (int)sizeof tbuf
);
320 if ((n
< 0) || !maybe_ok(res
, tbuf
, name_ok
)) {
326 h_errno
= NO_RECOVERY
;
331 n
= (int)strlen(bp
) + 1; /* for the \0 */
332 if (n
>= MAXHOSTNAMELEN
) {
337 /* Get canonical name. */
338 n
= (int)strlen(tbuf
) + 1; /* for the \0 */
339 if (n
> ep
- bp
|| n
>= MAXHOSTNAMELEN
) {
343 strlcpy(bp
, tbuf
, (size_t)(ep
- bp
));
348 if (qtype
== T_PTR
&& type
== T_CNAME
) {
349 n
= dn_expand(answer
->buf
, eom
, cp
, tbuf
, (int)sizeof tbuf
);
350 if (n
< 0 || !maybe_dnok(res
, tbuf
)) {
356 h_errno
= NO_RECOVERY
;
359 /* Get canonical name. */
360 n
= (int)strlen(tbuf
) + 1; /* for the \0 */
361 if (n
> ep
- bp
|| n
>= MAXHOSTNAMELEN
) {
365 strlcpy(bp
, tbuf
, (size_t)(ep
- bp
));
371 if (type
!= T_KEY
&& type
!= T_SIG
)
372 syslog(LOG_NOTICE
|LOG_AUTH
,
373 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
374 qname
, p_class(C_IN
), p_type(qtype
),
377 continue; /* XXX - had_error++ ? */
381 if (strcasecmp(tname
, bp
) != 0) {
382 syslog(LOG_NOTICE
|LOG_AUTH
,
383 AskedForGot
, qname
, bp
);
385 continue; /* XXX - had_error++ ? */
387 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, (int)(ep
- bp
));
388 if ((n
< 0) || !maybe_hnok(res
, bp
)) {
392 #if MULTI_PTRS_ARE_ALIASES
395 h_errno
= NO_RECOVERY
;
400 else if (ap
< &host_aliases
[MAXALIASES
-1])
405 n
= (int)strlen(bp
) + 1; /* for the \0 */
406 if (n
>= MAXHOSTNAMELEN
) {
415 if (res
->options
& RES_USE_INET6
) {
416 n
= strlen(bp
) + 1; /* for the \0 */
417 if (n
>= MAXHOSTNAMELEN
) {
422 map_v4v6_hostent(&host
, &bp
, ep
);
424 h_errno
= NETDB_SUCCESS
;
429 if (strcasecmp(host
.h_name
, bp
) != 0) {
430 syslog(LOG_NOTICE
|LOG_AUTH
,
431 AskedForGot
, host
.h_name
, bp
);
433 continue; /* XXX - had_error++ ? */
435 if (n
!= host
.h_length
) {
439 if (type
== T_AAAA
) {
441 memcpy(&in6
, cp
, IN6ADDRSZ
);
442 if (IN6_IS_ADDR_V4MAPPED(&in6
)) {
451 nn
= (int)strlen(bp
) + 1; /* for the \0 */
455 bp
+= sizeof(align
) -
456 (size_t)((u_long
)bp
% sizeof(align
));
458 if (bp
+ n
>= &hostbuf
[sizeof hostbuf
]) {
459 debugprintf("size (%d) too big\n", res
, n
);
463 if (hap
>= &h_addr_ptrs
[MAXADDRS
-1]) {
465 debugprintf("Too many addresses (%d)\n",
471 (void)memcpy(*hap
++ = bp
, cp
, (size_t)n
);
475 h_errno
= NO_RECOVERY
;
489 * Note: we sort even if host can take only one address
490 * in its return structures - should give it the "best"
491 * address in that case, not some random one
493 if (res
->nsort
&& haveanswer
> 1 && qtype
== T_A
)
494 addrsort(h_addr_ptrs
, haveanswer
, res
);
496 n
= (int)strlen(qname
) + 1; /* for the \0 */
497 if (n
> ep
- bp
|| n
>= MAXHOSTNAMELEN
)
499 strlcpy(bp
, qname
, (size_t)(ep
- bp
));
503 if (res
->options
& RES_USE_INET6
)
504 map_v4v6_hostent(&host
, &bp
, ep
);
505 h_errno
= NETDB_SUCCESS
;
509 h_errno
= NO_RECOVERY
;
514 gethostbyname(const char *name
)
517 res_state res
= __res_get_state();
522 _DIAGASSERT(name
!= NULL
);
524 if (res
->options
& RES_USE_INET6
) {
525 hp
= gethostbyname_internal(name
, AF_INET6
, res
);
527 __res_put_state(res
);
531 hp
= gethostbyname_internal(name
, AF_INET
, res
);
532 __res_put_state(res
);
537 gethostbyname2(const char *name
, int af
)
540 res_state res
= __res_get_state();
544 hp
= gethostbyname_internal(name
, af
, res
);
545 __res_put_state(res
);
549 static struct hostent
*
550 gethostbyname_internal(const char *name
, int af
, res_state res
)
556 static const ns_dtab dtab
[] = {
557 NS_FILES_CB(_gethtbyname
, NULL
)
558 { NSSRC_DNS
, _dns_gethtbyname
, NULL
}, /* force -DHESIOD */
559 NS_NIS_CB(_yp_gethtbyname
, NULL
)
563 _DIAGASSERT(name
!= NULL
);
573 h_errno
= NETDB_INTERNAL
;
574 errno
= EAFNOSUPPORT
;
578 host
.h_addrtype
= af
;
579 host
.h_length
= size
;
582 * if there aren't any dots, it could be a user-level alias.
583 * this is also done in res_nquery() since we are not the only
584 * function that looks up host names.
586 if (!strchr(name
, '.') && (cp
= __hostalias(name
)))
590 * disallow names consisting only of digits/dots, unless
593 if (isdigit((u_char
) name
[0]))
594 for (cp
= name
;; ++cp
) {
599 * All-numeric, no dot at the end.
600 * Fake up a hostent as if we'd actually
603 if (inet_pton(af
, name
,
604 (char *)(void *)host_addr
) <= 0) {
605 h_errno
= HOST_NOT_FOUND
;
608 strncpy(hostbuf
, name
, MAXDNAME
);
609 hostbuf
[MAXDNAME
] = '\0';
610 bp
= hostbuf
+ MAXDNAME
;
611 ep
= hostbuf
+ sizeof hostbuf
;
612 host
.h_name
= hostbuf
;
613 host
.h_aliases
= host_aliases
;
614 host_aliases
[0] = NULL
;
615 h_addr_ptrs
[0] = (char *)(void *)host_addr
;
616 h_addr_ptrs
[1] = NULL
;
617 host
.h_addr_list
= h_addr_ptrs
;
618 if (res
->options
& RES_USE_INET6
)
619 map_v4v6_hostent(&host
, &bp
, ep
);
620 h_errno
= NETDB_SUCCESS
;
623 if (!isdigit((u_char
) *cp
) && *cp
!= '.')
626 if ((isxdigit((u_char
) name
[0]) && strchr(name
, ':') != NULL
) ||
628 for (cp
= name
;; ++cp
) {
633 * All-IPv6-legal, no dot at the end.
634 * Fake up a hostent as if we'd actually
637 if (inet_pton(af
, name
,
638 (char *)(void *)host_addr
) <= 0) {
639 h_errno
= HOST_NOT_FOUND
;
642 strncpy(hostbuf
, name
, MAXDNAME
);
643 hostbuf
[MAXDNAME
] = '\0';
644 bp
= hostbuf
+ MAXDNAME
;
645 ep
= hostbuf
+ sizeof hostbuf
;
646 host
.h_name
= hostbuf
;
647 host
.h_aliases
= host_aliases
;
648 host_aliases
[0] = NULL
;
649 h_addr_ptrs
[0] = (char *)(void *)host_addr
;
650 h_addr_ptrs
[1] = NULL
;
651 host
.h_addr_list
= h_addr_ptrs
;
652 h_errno
= NETDB_SUCCESS
;
655 if (!isxdigit((u_char
) *cp
) && *cp
!= ':' && *cp
!= '.')
660 h_errno
= NETDB_INTERNAL
;
661 if (nsdispatch(&hp
, dtab
, NSDB_HOSTS
, "gethostbyname",
662 default_dns_files
, name
, strlen(name
), af
) != NS_SUCCESS
)
664 h_errno
= NETDB_SUCCESS
;
669 gethostbyaddr(const char *addr
, /* XXX should have been def'd as u_char! */
670 socklen_t len
, int af
)
672 const u_char
*uaddr
= (const u_char
*)addr
;
675 static const ns_dtab dtab
[] = {
676 NS_FILES_CB(_gethtbyaddr
, NULL
)
677 { NSSRC_DNS
, _dns_gethtbyaddr
, NULL
}, /* force -DHESIOD */
678 NS_NIS_CB(_yp_gethtbyaddr
, NULL
)
682 _DIAGASSERT(addr
!= NULL
);
684 if (af
== AF_INET6
&& len
== IN6ADDRSZ
&&
685 (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr
*)(const void *)uaddr
) ||
686 IN6_IS_ADDR_SITELOCAL((const struct in6_addr
*)(const void *)uaddr
))) {
687 h_errno
= HOST_NOT_FOUND
;
690 if (af
== AF_INET6
&& len
== IN6ADDRSZ
&&
691 (IN6_IS_ADDR_V4MAPPED((const struct in6_addr
*)(const void *)uaddr
) ||
692 IN6_IS_ADDR_V4COMPAT((const struct in6_addr
*)(const void *)uaddr
))) {
694 addr
+= IN6ADDRSZ
- INADDRSZ
;
695 uaddr
+= IN6ADDRSZ
- INADDRSZ
;
707 errno
= EAFNOSUPPORT
;
708 h_errno
= NETDB_INTERNAL
;
713 h_errno
= NETDB_INTERNAL
;
717 h_errno
= NETDB_INTERNAL
;
718 if (nsdispatch(&hp
, dtab
, NSDB_HOSTS
, "gethostbyaddr",
719 default_dns_files
, uaddr
, len
, af
) != NS_SUCCESS
)
721 h_errno
= NETDB_SUCCESS
;
729 hostf
= fopen(_PATH_HOSTS
, "re");
738 if (hostf
&& !stayopen
) {
739 (void) fclose(hostf
);
751 if (!hostf
&& !(hostf
= fopen(_PATH_HOSTS
, "re"))) {
752 h_errno
= NETDB_INTERNAL
;
756 if (!(p
= fgets(hostbuf
, (int)sizeof hostbuf
, hostf
))) {
757 h_errno
= HOST_NOT_FOUND
;
762 if (!(cp
= strpbrk(p
, "#\n")))
765 if (!(cp
= strpbrk(p
, " \t")))
768 if (inet_pton(AF_INET6
, p
, (char *)(void *)host_addr
) > 0) {
771 } else if (inet_pton(AF_INET
, p
, (char *)(void *)host_addr
) > 0) {
772 res_state res
= __res_get_state();
775 if (res
->options
& RES_USE_INET6
) {
776 map_v4v6_address((char *)(void *)host_addr
,
777 (char *)(void *)host_addr
);
784 __res_put_state(res
);
788 /* if this is not something we're looking for, skip it. */
789 if (host
.h_addrtype
!= 0 && host
.h_addrtype
!= af
)
791 if (host
.h_length
!= 0 && host
.h_length
!= len
)
793 h_addr_ptrs
[0] = (char *)(void *)host_addr
;
794 h_addr_ptrs
[1] = NULL
;
795 host
.h_addr_list
= h_addr_ptrs
;
797 host
.h_addrtype
= af
;
798 while (*cp
== ' ' || *cp
== '\t')
801 q
= host
.h_aliases
= host_aliases
;
802 if ((cp
= strpbrk(cp
, " \t")) != NULL
)
805 if (*cp
== ' ' || *cp
== '\t') {
809 if (q
< &host_aliases
[MAXALIASES
- 1])
811 if ((cp
= strpbrk(cp
, " \t")) != NULL
)
815 h_errno
= NETDB_SUCCESS
;
821 _gethtbyname(void *rv
, void *cb_data
, va_list ap
)
827 _DIAGASSERT(rv
!= NULL
);
829 name
= va_arg(ap
, char *);
830 /* NOSTRICT skip len */(void)va_arg(ap
, int);
831 af
= va_arg(ap
, int);
836 res_state res
= __res_get_state();
839 if (res
->options
& RES_USE_INET6
)
840 hp
= _gethtbyname2(name
, AF_INET6
);
842 hp
= _gethtbyname2(name
, AF_INET
);
843 __res_put_state(res
);
846 hp
= _gethtbyname2(name
, af
);
848 *((struct hostent
**)rv
) = hp
;
850 h_errno
= HOST_NOT_FOUND
;
857 _gethtbyname2(const char *name
, int af
)
860 char *tmpbuf
, *ptr
, **cp
;
864 _DIAGASSERT(name
!= NULL
);
869 while ((p
= _gethtent()) != NULL
&& num
< MAXADDRS
) {
870 if (p
->h_addrtype
!= af
)
872 if (strcasecmp(p
->h_name
, name
) != 0) {
873 for (cp
= p
->h_aliases
; *cp
!= NULL
; cp
++)
874 if (strcasecmp(*cp
, name
) == 0)
876 if (*cp
== NULL
) continue;
883 bufsize
= strlen(p
->h_name
) + 2 +
884 MAXADDRS
* p
->h_length
+
886 for (cp
= p
->h_aliases
; *cp
!= NULL
; cp
++)
887 bufsize
+= strlen(*cp
) + 1;
889 if ((tmpbuf
= malloc(bufsize
)) == NULL
) {
890 h_errno
= NETDB_INTERNAL
;
896 while ((*ptr
++ = *src
++) != '\0');
897 for (cp
= p
->h_aliases
; *cp
!= NULL
; cp
++) {
899 while ((*ptr
++ = *src
++) != '\0');
903 ptr
= (char *)(void *)ALIGN(ptr
);
906 (void)memcpy(ptr
, p
->h_addr_list
[0], (size_t)p
->h_length
);
911 if (num
== 0) return NULL
;
914 if (len
> (sizeof(hostbuf
) - ALIGNBYTES
)) {
917 h_errno
= NETDB_INTERNAL
;
920 ptr
= memcpy((void *)ALIGN(hostbuf
), tmpbuf
, len
);
934 ptr
= (char *)(void *)ALIGN(ptr
);
938 ptr
+= host
.h_length
;
947 _gethtbyaddr(void *rv
, void *cb_data
, va_list ap
)
950 const unsigned char *addr
;
953 _DIAGASSERT(rv
!= NULL
);
955 addr
= va_arg(ap
, unsigned char *);
956 len
= va_arg(ap
, int);
957 af
= va_arg(ap
, int);
960 host
.h_addrtype
= af
;
963 while ((p
= _gethtent()) != NULL
)
964 if (p
->h_addrtype
== af
&& !memcmp(p
->h_addr
, addr
,
968 *((struct hostent
**)rv
) = p
;
970 h_errno
= HOST_NOT_FOUND
;
977 map_v4v6_address(const char *src
, char *dst
)
979 u_char
*p
= (u_char
*)dst
;
983 _DIAGASSERT(src
!= NULL
);
984 _DIAGASSERT(dst
!= NULL
);
986 /* Stash a temporary copy so our caller can update in place. */
987 (void)memcpy(tmp
, src
, INADDRSZ
);
988 /* Mark this ipv6 addr as a mapped ipv4. */
989 for (i
= 0; i
< 10; i
++)
993 /* Retrieve the saved copy and we're done. */
994 (void)memcpy((void *)p
, tmp
, INADDRSZ
);
998 map_v4v6_hostent(struct hostent
*hp
, char **bpp
, char *ep
)
1002 _DIAGASSERT(hp
!= NULL
);
1003 _DIAGASSERT(bpp
!= NULL
);
1004 _DIAGASSERT(ep
!= NULL
);
1006 if (hp
->h_addrtype
!= AF_INET
|| hp
->h_length
!= INADDRSZ
)
1008 hp
->h_addrtype
= AF_INET6
;
1009 hp
->h_length
= IN6ADDRSZ
;
1010 for (ap
= hp
->h_addr_list
; *ap
; ap
++) {
1011 int i
= (int)(sizeof(align
) -
1012 (size_t)((u_long
)*bpp
% sizeof(align
)));
1014 if (ep
- *bpp
< (i
+ IN6ADDRSZ
)) {
1015 /* Out of memory. Truncate address list here. XXX */
1020 map_v4v6_address(*ap
, *bpp
);
1027 addrsort(char **ap
, int num
, res_state res
)
1031 short aval
[MAXADDRS
];
1034 _DIAGASSERT(ap
!= NULL
);
1037 for (i
= 0; i
< num
; i
++, p
++) {
1038 for (j
= 0 ; (unsigned)j
< res
->nsort
; j
++)
1039 if (res
->sort_list
[j
].addr
.s_addr
==
1040 (((struct in_addr
*)(void *)(*p
))->s_addr
&
1041 res
->sort_list
[j
].mask
))
1044 if (needsort
== 0 && i
> 0 && j
< aval
[i
-1])
1050 while (needsort
< num
) {
1051 for (j
= needsort
- 1; j
>= 0; j
--) {
1052 if (aval
[j
] > aval
[j
+1]) {
1056 aval
[j
] = aval
[j
+1];
1072 host
.h_addrtype
= 0;
1079 _dns_gethtbyname(void *rv
, void *cb_data
, va_list ap
)
1088 _DIAGASSERT(rv
!= NULL
);
1090 name
= va_arg(ap
, char *);
1091 /* NOSTRICT skip len */(void)va_arg(ap
, int);
1092 af
= va_arg(ap
, int);
1104 buf
= malloc(sizeof(*buf
));
1106 h_errno
= NETDB_INTERNAL
;
1109 res
= __res_get_state();
1114 n
= res_nsearch(res
, name
, C_IN
, type
, buf
->buf
, (int)sizeof(buf
->buf
));
1117 debugprintf("res_nsearch failed (%d)\n", res
, n
);
1118 __res_put_state(res
);
1121 hp
= getanswer(buf
, n
, name
, type
, res
);
1123 __res_put_state(res
);
1126 case HOST_NOT_FOUND
:
1133 *((struct hostent
**)rv
) = hp
;
1139 _dns_gethtbyaddr(void *rv
, void *cb_data
, va_list ap
)
1141 char qbuf
[MAXDNAME
+ 1], *qp
, *ep
;
1145 const unsigned char *uaddr
;
1146 int len
, af
, advance
;
1149 _DIAGASSERT(rv
!= NULL
);
1151 uaddr
= va_arg(ap
, unsigned char *);
1152 len
= va_arg(ap
, int);
1153 af
= va_arg(ap
, int);
1157 (void)snprintf(qbuf
, sizeof(qbuf
), "%u.%u.%u.%u.in-addr.arpa",
1158 (uaddr
[3] & 0xff), (uaddr
[2] & 0xff),
1159 (uaddr
[1] & 0xff), (uaddr
[0] & 0xff));
1164 ep
= qbuf
+ sizeof(qbuf
) - 1;
1165 for (n
= IN6ADDRSZ
- 1; n
>= 0; n
--) {
1166 advance
= snprintf(qp
, (size_t)(ep
- qp
), "%x.%x.",
1168 ((unsigned int)uaddr
[n
] >> 4) & 0xf);
1169 if (advance
> 0 && qp
+ advance
< ep
)
1172 h_errno
= NETDB_INTERNAL
;
1176 if (strlcat(qbuf
, "ip6.arpa", sizeof(qbuf
)) >= sizeof(qbuf
)) {
1177 h_errno
= NETDB_INTERNAL
;
1185 buf
= malloc(sizeof(*buf
));
1187 h_errno
= NETDB_INTERNAL
;
1190 res
= __res_get_state();
1195 n
= res_nquery(res
, qbuf
, C_IN
, T_PTR
, buf
->buf
, (int)sizeof(buf
->buf
));
1198 debugprintf("res_nquery failed (%d)\n", res
, n
);
1199 __res_put_state(res
);
1202 hp
= getanswer(buf
, n
, qbuf
, T_PTR
, res
);
1205 __res_put_state(res
);
1207 case HOST_NOT_FOUND
:
1215 hp
->h_addrtype
= af
;
1217 (void)memcpy(host_addr
, uaddr
, (size_t)len
);
1218 h_addr_ptrs
[0] = (char *)(void *)host_addr
;
1219 h_addr_ptrs
[1] = NULL
;
1220 if (af
== AF_INET
&& (res
->options
& RES_USE_INET6
)) {
1221 map_v4v6_address((char *)(void *)host_addr
,
1222 (char *)(void *)host_addr
);
1223 hp
->h_addrtype
= AF_INET6
;
1224 hp
->h_length
= IN6ADDRSZ
;
1227 __res_put_state(res
);
1228 *((struct hostent
**)rv
) = hp
;
1229 h_errno
= NETDB_SUCCESS
;
1236 _yphostent(char *line
, int af
)
1238 static struct in_addr host_addrs
[MAXADDRS
];
1239 static struct in6_addr host6_addrs
[MAXADDRS
];
1247 _DIAGASSERT(line
!= NULL
);
1250 host
.h_addr_list
= h_addr_ptrs
;
1251 host
.h_addrtype
= af
;
1254 host
.h_length
= INADDRSZ
;
1257 host
.h_length
= IN6ADDRSZ
;
1263 q
= host
.h_aliases
= host_aliases
;
1267 /* check for host_addrs overflow */
1268 if (naddrs
>= sizeof(host_addrs
) / sizeof(host_addrs
[0]))
1270 if (naddrs
>= sizeof(host6_addrs
) / sizeof(host6_addrs
[0]))
1274 cp
= strpbrk(p
, " \t");
1279 /* p has should have an address */
1283 addrok
= inet_aton(p
, &host_addrs
[naddrs
]);
1286 addrok
= inet_pton(af
, p
, &host6_addrs
[naddrs
]);
1290 /* skip to the next line */
1304 *hap
++ = (char *)(void *)&host_addrs
[naddrs
++];
1307 *hap
++ = (char *)(void *)&host6_addrs
[naddrs
++];
1311 while (*cp
== ' ' || *cp
== '\t')
1314 cp
= strpbrk(p
, " \t\n");
1322 else if (strcmp(host
.h_name
, p
)==0)
1324 else if (q
< &host_aliases
[MAXALIASES
- 1])
1331 if (*cp
== ' ' || *cp
== '\t') {
1339 if (q
< &host_aliases
[MAXALIASES
- 1])
1341 cp
= strpbrk(cp
, " \t");
1347 if (host
.h_name
== NULL
)
1356 _yp_gethtbyaddr(void *rv
, void *cb_data
, va_list ap
)
1358 struct hostent
*hp
= NULL
;
1359 static char *__ypcurrent
;
1360 int __ypcurrentlen
, r
;
1361 char name
[INET6_ADDRSTRLEN
]; /* XXX enough? */
1362 const unsigned char *uaddr
;
1366 _DIAGASSERT(rv
!= NULL
);
1368 uaddr
= va_arg(ap
, unsigned char *);
1369 /* NOSTRICT skip len */(void)va_arg(ap
, int);
1370 af
= va_arg(ap
, int);
1373 if (_yp_check(&__ypdomain
) == 0)
1377 * XXX unfortunately, we cannot support IPv6 extended scoped address
1378 * notation here. gethostbyaddr() is not scope-aware. too bad.
1380 if (inet_ntop(af
, uaddr
, name
, (socklen_t
)sizeof(name
)) == NULL
)
1387 map
= "hosts.byaddr";
1390 map
= "ipnodes.byaddr";
1393 r
= yp_match(__ypdomain
, map
, name
,
1394 (int)strlen(name
), &__ypcurrent
, &__ypcurrentlen
);
1396 hp
= _yphostent(__ypcurrent
, af
);
1398 h_errno
= HOST_NOT_FOUND
;
1401 *((struct hostent
**)rv
) = hp
;
1407 _yp_gethtbyname(void *rv
, void *cb_data
, va_list ap
)
1409 struct hostent
*hp
= NULL
;
1410 static char *__ypcurrent
;
1411 int __ypcurrentlen
, r
;
1416 _DIAGASSERT(rv
!= NULL
);
1418 name
= va_arg(ap
, char *);
1419 /* NOSTRICT skip len */(void)va_arg(ap
, int);
1420 af
= va_arg(ap
, int);
1423 if (_yp_check(&__ypdomain
) == 0)
1431 map
= "hosts.byname";
1434 map
= "ipnodes.byname";
1437 r
= yp_match(__ypdomain
, map
, name
,
1438 (int)strlen(name
), &__ypcurrent
, &__ypcurrentlen
);
1440 hp
= _yphostent(__ypcurrent
, af
);
1442 h_errno
= HOST_NOT_FOUND
;
1445 *((struct hostent
**)rv
) = hp
;