1 /* $NetBSD: gethnamaddr.c,v 1.74 2009/10/02 06:49:23 cegger 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.74 2009/10/02 06:49:23 cegger 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 MAXALIASES 35
107 static const char AskedForGot
[] =
108 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
110 static char *h_addr_ptrs
[MAXADDRS
+ 1];
113 static char *__ypdomain
;
116 static struct hostent host
;
117 static char *host_aliases
[MAXALIASES
];
118 static char hostbuf
[8*1024];
119 static u_int32_t host_addr
[16 / sizeof(u_int32_t
)]; /* IPv4 or IPv6 */
120 static FILE *hostf
= NULL
;
121 static int stayopen
= 0;
123 #define MAXPACKET (64*1024)
127 u_char buf
[MAXPACKET
];
136 static void dprintf(const char *, res_state
, ...)
137 __attribute__((__format__(__printf__
, 1, 3)));
139 static struct hostent
*getanswer(const querybuf
*, int, const char *, int,
141 static void map_v4v6_address(const char *, char *);
142 static void map_v4v6_hostent(struct hostent
*, char **, char *);
143 static void addrsort(char **, int, res_state
);
146 void _endhtent(void);
147 struct hostent
*_gethtent(void);
148 void ht_sethostent(int);
149 void ht_endhostent(void);
150 struct hostent
*ht_gethostbyname(char *);
151 struct hostent
*ht_gethostbyaddr(const char *, int, int);
152 void dns_service(void);
154 int dn_skipname(const u_char
*, const u_char
*);
155 int _gethtbyaddr(void *, void *, va_list);
156 int _gethtbyname(void *, void *, va_list);
157 struct hostent
*_gethtbyname2(const char *, int);
158 int _dns_gethtbyaddr(void *, void *, va_list);
159 int _dns_gethtbyname(void *, void *, va_list);
161 struct hostent
*_yphostent(char *, int);
162 int _yp_gethtbyaddr(void *, void *, va_list);
163 int _yp_gethtbyname(void *, void *, va_list);
166 static struct hostent
*gethostbyname_internal(const char *, int, res_state
);
168 static const ns_src default_dns_files
[] = {
169 { NSSRC_FILES
, NS_SUCCESS
},
170 { NSSRC_DNS
, NS_SUCCESS
},
177 dprintf(const char *msg
, res_state res
, ...)
179 _DIAGASSERT(msg
!= NULL
);
181 if (res
->options
& RES_DEBUG
) {
193 # define dprintf(msg, res, num) /*nada*/
196 #define BOUNDED_INCR(x) \
200 h_errno = NO_RECOVERY; \
203 } while (/*CONSTCOND*/0)
205 #define BOUNDS_CHECK(ptr, count) \
207 if ((ptr) + (count) > eom) { \
208 h_errno = NO_RECOVERY; \
211 } while (/*CONSTCOND*/0)
213 static struct hostent
*
214 getanswer(const querybuf
*answer
, int anslen
, const char *qname
, int qtype
,
220 const u_char
*eom
, *erdata
;
221 char *bp
, **ap
, **hap
, *ep
;
222 int type
, class, ancount
, qdcount
;
223 int haveanswer
, had_error
;
227 int (*name_ok
)(const char *);
229 _DIAGASSERT(answer
!= NULL
);
230 _DIAGASSERT(qname
!= NULL
);
234 eom
= answer
->buf
+ anslen
;
244 return NULL
; /* XXX should be abort(); */
247 * find first satisfactory answer
250 ancount
= ntohs(hp
->ancount
);
251 qdcount
= ntohs(hp
->qdcount
);
253 ep
= hostbuf
+ sizeof hostbuf
;
255 BOUNDED_INCR(HFIXEDSZ
);
257 h_errno
= NO_RECOVERY
;
260 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, ep
- bp
);
261 if ((n
< 0) || !(*name_ok
)(bp
)) {
262 h_errno
= NO_RECOVERY
;
265 BOUNDED_INCR(n
+ QFIXEDSZ
);
266 if (qtype
== T_A
|| qtype
== T_AAAA
) {
267 /* res_send() has already verified that the query name is the
268 * same as the one we sent; this just gets the expanded name
269 * (i.e., with the succeeding search-domain tacked on).
271 n
= strlen(bp
) + 1; /* for the \0 */
272 if (n
>= MAXHOSTNAMELEN
) {
273 h_errno
= NO_RECOVERY
;
278 /* The qname can be abbreviated, but h_name is now absolute. */
283 host
.h_aliases
= host_aliases
;
286 host
.h_addr_list
= h_addr_ptrs
;
289 while (ancount
-- > 0 && cp
< eom
&& !had_error
) {
290 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, ep
- bp
);
291 if ((n
< 0) || !(*name_ok
)(bp
)) {
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 if (ap
>= &host_aliases
[MAXALIASES
-1])
313 n
= dn_expand(answer
->buf
, eom
, cp
, tbuf
, sizeof tbuf
);
314 if ((n
< 0) || !(*name_ok
)(tbuf
)) {
320 h_errno
= NO_RECOVERY
;
325 n
= strlen(bp
) + 1; /* for the \0 */
326 if (n
>= MAXHOSTNAMELEN
) {
331 /* Get canonical name. */
332 n
= strlen(tbuf
) + 1; /* for the \0 */
333 if (n
> ep
- bp
|| n
>= MAXHOSTNAMELEN
) {
337 strlcpy(bp
, tbuf
, (size_t)(ep
- bp
));
342 if (qtype
== T_PTR
&& type
== T_CNAME
) {
343 n
= dn_expand(answer
->buf
, eom
, cp
, tbuf
, sizeof tbuf
);
344 if (n
< 0 || !res_dnok(tbuf
)) {
350 h_errno
= NO_RECOVERY
;
353 /* Get canonical name. */
354 n
= strlen(tbuf
) + 1; /* for the \0 */
355 if (n
> ep
- bp
|| n
>= MAXHOSTNAMELEN
) {
359 strlcpy(bp
, tbuf
, (size_t)(ep
- bp
));
365 if (type
!= T_KEY
&& type
!= T_SIG
)
366 syslog(LOG_NOTICE
|LOG_AUTH
,
367 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
368 qname
, p_class(C_IN
), p_type(qtype
),
371 continue; /* XXX - had_error++ ? */
375 if (strcasecmp(tname
, bp
) != 0) {
376 syslog(LOG_NOTICE
|LOG_AUTH
,
377 AskedForGot
, qname
, bp
);
379 continue; /* XXX - had_error++ ? */
381 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, ep
- bp
);
382 if ((n
< 0) || !res_hnok(bp
)) {
386 #if MULTI_PTRS_ARE_ALIASES
389 h_errno
= NO_RECOVERY
;
394 else if (ap
< &host_aliases
[MAXALIASES
-1])
399 n
= strlen(bp
) + 1; /* for the \0 */
400 if (n
>= MAXHOSTNAMELEN
) {
409 if (res
->options
& RES_USE_INET6
) {
410 n
= strlen(bp
) + 1; /* for the \0 */
411 if (n
>= MAXHOSTNAMELEN
) {
416 map_v4v6_hostent(&host
, &bp
, ep
);
418 h_errno
= NETDB_SUCCESS
;
423 if (strcasecmp(host
.h_name
, bp
) != 0) {
424 syslog(LOG_NOTICE
|LOG_AUTH
,
425 AskedForGot
, host
.h_name
, bp
);
427 continue; /* XXX - had_error++ ? */
429 if (n
!= host
.h_length
) {
433 if (type
== T_AAAA
) {
435 memcpy(&in6
, cp
, IN6ADDRSZ
);
436 if (IN6_IS_ADDR_V4MAPPED(&in6
)) {
445 nn
= strlen(bp
) + 1; /* for the \0 */
449 bp
+= sizeof(align
) -
450 (size_t)((u_long
)bp
% sizeof(align
));
452 if (bp
+ n
>= &hostbuf
[sizeof hostbuf
]) {
453 dprintf("size (%d) too big\n", res
, n
);
457 if (hap
>= &h_addr_ptrs
[MAXADDRS
-1]) {
459 dprintf("Too many addresses (%d)\n",
465 (void)memcpy(*hap
++ = bp
, cp
, (size_t)n
);
469 h_errno
= NO_RECOVERY
;
483 * Note: we sort even if host can take only one address
484 * in its return structures - should give it the "best"
485 * address in that case, not some random one
487 if (res
->nsort
&& haveanswer
> 1 && qtype
== T_A
)
488 addrsort(h_addr_ptrs
, haveanswer
, res
);
490 n
= strlen(qname
) + 1; /* for the \0 */
491 if (n
> ep
- bp
|| n
>= MAXHOSTNAMELEN
)
493 strlcpy(bp
, qname
, (size_t)(ep
- bp
));
497 if (res
->options
& RES_USE_INET6
)
498 map_v4v6_hostent(&host
, &bp
, ep
);
499 h_errno
= NETDB_SUCCESS
;
503 h_errno
= NO_RECOVERY
;
508 gethostbyname(const char *name
)
511 res_state res
= __res_get_state();
516 _DIAGASSERT(name
!= NULL
);
518 if (res
->options
& RES_USE_INET6
) {
519 hp
= gethostbyname_internal(name
, AF_INET6
, res
);
521 __res_put_state(res
);
525 hp
= gethostbyname_internal(name
, AF_INET
, res
);
526 __res_put_state(res
);
531 gethostbyname2(const char *name
, int af
)
534 res_state res
= __res_get_state();
538 hp
= gethostbyname_internal(name
, af
, res
);
539 __res_put_state(res
);
543 static struct hostent
*
544 gethostbyname_internal(const char *name
, int af
, res_state res
)
550 static const ns_dtab dtab
[] = {
551 NS_FILES_CB(_gethtbyname
, NULL
)
552 { NSSRC_DNS
, _dns_gethtbyname
, NULL
}, /* force -DHESIOD */
553 NS_NIS_CB(_yp_gethtbyname
, NULL
)
557 _DIAGASSERT(name
!= NULL
);
567 h_errno
= NETDB_INTERNAL
;
568 errno
= EAFNOSUPPORT
;
572 host
.h_addrtype
= af
;
573 host
.h_length
= size
;
576 * if there aren't any dots, it could be a user-level alias.
577 * this is also done in res_nquery() since we are not the only
578 * function that looks up host names.
580 if (!strchr(name
, '.') && (cp
= __hostalias(name
)))
584 * disallow names consisting only of digits/dots, unless
587 if (isdigit((u_char
) name
[0]))
588 for (cp
= name
;; ++cp
) {
593 * All-numeric, no dot at the end.
594 * Fake up a hostent as if we'd actually
597 if (inet_pton(af
, name
,
598 (char *)(void *)host_addr
) <= 0) {
599 h_errno
= HOST_NOT_FOUND
;
602 strncpy(hostbuf
, name
, MAXDNAME
);
603 hostbuf
[MAXDNAME
] = '\0';
604 bp
= hostbuf
+ MAXDNAME
;
605 ep
= hostbuf
+ sizeof hostbuf
;
606 host
.h_name
= hostbuf
;
607 host
.h_aliases
= host_aliases
;
608 host_aliases
[0] = NULL
;
609 h_addr_ptrs
[0] = (char *)(void *)host_addr
;
610 h_addr_ptrs
[1] = NULL
;
611 host
.h_addr_list
= h_addr_ptrs
;
612 if (res
->options
& RES_USE_INET6
)
613 map_v4v6_hostent(&host
, &bp
, ep
);
614 h_errno
= NETDB_SUCCESS
;
617 if (!isdigit((u_char
) *cp
) && *cp
!= '.')
620 if ((isxdigit((u_char
) name
[0]) && strchr(name
, ':') != NULL
) ||
622 for (cp
= name
;; ++cp
) {
627 * All-IPv6-legal, no dot at the end.
628 * Fake up a hostent as if we'd actually
631 if (inet_pton(af
, name
,
632 (char *)(void *)host_addr
) <= 0) {
633 h_errno
= HOST_NOT_FOUND
;
636 strncpy(hostbuf
, name
, MAXDNAME
);
637 hostbuf
[MAXDNAME
] = '\0';
638 bp
= hostbuf
+ MAXDNAME
;
639 ep
= hostbuf
+ sizeof hostbuf
;
640 host
.h_name
= hostbuf
;
641 host
.h_aliases
= host_aliases
;
642 host_aliases
[0] = NULL
;
643 h_addr_ptrs
[0] = (char *)(void *)host_addr
;
644 h_addr_ptrs
[1] = NULL
;
645 host
.h_addr_list
= h_addr_ptrs
;
646 h_errno
= NETDB_SUCCESS
;
649 if (!isxdigit((u_char
) *cp
) && *cp
!= ':' && *cp
!= '.')
654 h_errno
= NETDB_INTERNAL
;
655 if (nsdispatch(&hp
, dtab
, NSDB_HOSTS
, "gethostbyname",
656 default_dns_files
, name
, strlen(name
), af
) != NS_SUCCESS
)
658 h_errno
= NETDB_SUCCESS
;
663 gethostbyaddr(const char *addr
, /* XXX should have been def'd as u_char! */
664 socklen_t len
, int af
)
666 const u_char
*uaddr
= (const u_char
*)addr
;
669 static const ns_dtab dtab
[] = {
670 NS_FILES_CB(_gethtbyaddr
, NULL
)
671 { NSSRC_DNS
, _dns_gethtbyaddr
, NULL
}, /* force -DHESIOD */
672 NS_NIS_CB(_yp_gethtbyaddr
, NULL
)
676 _DIAGASSERT(addr
!= NULL
);
678 if (af
== AF_INET6
&& len
== IN6ADDRSZ
&&
679 (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr
*)(const void *)uaddr
) ||
680 IN6_IS_ADDR_SITELOCAL((const struct in6_addr
*)(const void *)uaddr
))) {
681 h_errno
= HOST_NOT_FOUND
;
684 if (af
== AF_INET6
&& len
== IN6ADDRSZ
&&
685 (IN6_IS_ADDR_V4MAPPED((const struct in6_addr
*)(const void *)uaddr
) ||
686 IN6_IS_ADDR_V4COMPAT((const struct in6_addr
*)(const void *)uaddr
))) {
688 addr
+= IN6ADDRSZ
- INADDRSZ
;
689 uaddr
+= IN6ADDRSZ
- INADDRSZ
;
701 errno
= EAFNOSUPPORT
;
702 h_errno
= NETDB_INTERNAL
;
707 h_errno
= NETDB_INTERNAL
;
711 h_errno
= NETDB_INTERNAL
;
712 if (nsdispatch(&hp
, dtab
, NSDB_HOSTS
, "gethostbyaddr",
713 default_dns_files
, uaddr
, len
, af
) != NS_SUCCESS
)
715 h_errno
= NETDB_SUCCESS
;
723 hostf
= fopen(_PATH_HOSTS
, "r" );
732 if (hostf
&& !stayopen
) {
733 (void) fclose(hostf
);
745 if (!hostf
&& !(hostf
= fopen(_PATH_HOSTS
, "r" ))) {
746 h_errno
= NETDB_INTERNAL
;
750 if (!(p
= fgets(hostbuf
, sizeof hostbuf
, hostf
))) {
751 h_errno
= HOST_NOT_FOUND
;
756 if (!(cp
= strpbrk(p
, "#\n")))
759 if (!(cp
= strpbrk(p
, " \t")))
762 if (inet_pton(AF_INET6
, p
, (char *)(void *)host_addr
) > 0) {
765 } else if (inet_pton(AF_INET
, p
, (char *)(void *)host_addr
) > 0) {
766 res_state res
= __res_get_state();
769 if (res
->options
& RES_USE_INET6
) {
770 map_v4v6_address((char *)(void *)host_addr
,
771 (char *)(void *)host_addr
);
778 __res_put_state(res
);
782 /* if this is not something we're looking for, skip it. */
783 if (host
.h_addrtype
!= 0 && host
.h_addrtype
!= af
)
785 if (host
.h_length
!= 0 && host
.h_length
!= len
)
787 h_addr_ptrs
[0] = (char *)(void *)host_addr
;
788 h_addr_ptrs
[1] = NULL
;
789 host
.h_addr_list
= h_addr_ptrs
;
791 host
.h_addrtype
= af
;
792 while (*cp
== ' ' || *cp
== '\t')
795 q
= host
.h_aliases
= host_aliases
;
796 if ((cp
= strpbrk(cp
, " \t")) != NULL
)
799 if (*cp
== ' ' || *cp
== '\t') {
803 if (q
< &host_aliases
[MAXALIASES
- 1])
805 if ((cp
= strpbrk(cp
, " \t")) != NULL
)
809 h_errno
= NETDB_SUCCESS
;
815 _gethtbyname(void *rv
, void *cb_data
, va_list ap
)
821 _DIAGASSERT(rv
!= NULL
);
823 name
= va_arg(ap
, char *);
824 /* NOSTRICT skip len */(void)va_arg(ap
, int);
825 af
= va_arg(ap
, int);
830 res_state res
= __res_get_state();
833 if (res
->options
& RES_USE_INET6
)
834 hp
= _gethtbyname2(name
, AF_INET6
);
836 hp
= _gethtbyname2(name
, AF_INET
);
837 __res_put_state(res
);
840 hp
= _gethtbyname2(name
, af
);
842 *((struct hostent
**)rv
) = hp
;
844 h_errno
= HOST_NOT_FOUND
;
851 _gethtbyname2(const char *name
, int af
)
854 char *tmpbuf
, *ptr
, **cp
;
858 _DIAGASSERT(name
!= NULL
);
863 while ((p
= _gethtent()) != NULL
&& num
< MAXADDRS
) {
864 if (p
->h_addrtype
!= af
)
866 if (strcasecmp(p
->h_name
, name
) != 0) {
867 for (cp
= p
->h_aliases
; *cp
!= NULL
; cp
++)
868 if (strcasecmp(*cp
, name
) == 0)
870 if (*cp
== NULL
) continue;
877 bufsize
= strlen(p
->h_name
) + 2 +
878 MAXADDRS
* p
->h_length
+
880 for (cp
= p
->h_aliases
; *cp
!= NULL
; cp
++)
881 bufsize
+= strlen(*cp
) + 1;
883 if ((tmpbuf
= malloc(bufsize
)) == NULL
) {
884 h_errno
= NETDB_INTERNAL
;
890 while ((*ptr
++ = *src
++) != '\0');
891 for (cp
= p
->h_aliases
; *cp
!= NULL
; cp
++) {
893 while ((*ptr
++ = *src
++) != '\0');
897 ptr
= (char *)(void *)ALIGN(ptr
);
900 (void)memcpy(ptr
, p
->h_addr_list
[0], (size_t)p
->h_length
);
905 if (num
== 0) return NULL
;
908 if (len
> (sizeof(hostbuf
) - ALIGNBYTES
)) {
911 h_errno
= NETDB_INTERNAL
;
914 ptr
= memcpy((void *)ALIGN(hostbuf
), tmpbuf
, len
);
928 ptr
= (char *)(void *)ALIGN(ptr
);
932 ptr
+= host
.h_length
;
941 _gethtbyaddr(void *rv
, void *cb_data
, va_list ap
)
944 const unsigned char *addr
;
947 _DIAGASSERT(rv
!= NULL
);
949 addr
= va_arg(ap
, unsigned char *);
950 len
= va_arg(ap
, int);
951 af
= va_arg(ap
, int);
954 host
.h_addrtype
= af
;
957 while ((p
= _gethtent()) != NULL
)
958 if (p
->h_addrtype
== af
&& !memcmp(p
->h_addr
, addr
,
962 *((struct hostent
**)rv
) = p
;
964 h_errno
= HOST_NOT_FOUND
;
971 map_v4v6_address(const char *src
, char *dst
)
973 u_char
*p
= (u_char
*)dst
;
977 _DIAGASSERT(src
!= NULL
);
978 _DIAGASSERT(dst
!= NULL
);
980 /* Stash a temporary copy so our caller can update in place. */
981 (void)memcpy(tmp
, src
, INADDRSZ
);
982 /* Mark this ipv6 addr as a mapped ipv4. */
983 for (i
= 0; i
< 10; i
++)
987 /* Retrieve the saved copy and we're done. */
988 (void)memcpy((void *)p
, tmp
, INADDRSZ
);
992 map_v4v6_hostent(struct hostent
*hp
, char **bpp
, char *ep
)
996 _DIAGASSERT(hp
!= NULL
);
997 _DIAGASSERT(bpp
!= NULL
);
998 _DIAGASSERT(ep
!= NULL
);
1000 if (hp
->h_addrtype
!= AF_INET
|| hp
->h_length
!= INADDRSZ
)
1002 hp
->h_addrtype
= AF_INET6
;
1003 hp
->h_length
= IN6ADDRSZ
;
1004 for (ap
= hp
->h_addr_list
; *ap
; ap
++) {
1005 int i
= sizeof(align
) - (size_t)((u_long
)*bpp
% sizeof(align
));
1007 if (ep
- *bpp
< (i
+ IN6ADDRSZ
)) {
1008 /* Out of memory. Truncate address list here. XXX */
1013 map_v4v6_address(*ap
, *bpp
);
1020 addrsort(char **ap
, int num
, res_state res
)
1024 short aval
[MAXADDRS
];
1027 _DIAGASSERT(ap
!= NULL
);
1030 for (i
= 0; i
< num
; i
++, p
++) {
1031 for (j
= 0 ; (unsigned)j
< res
->nsort
; j
++)
1032 if (res
->sort_list
[j
].addr
.s_addr
==
1033 (((struct in_addr
*)(void *)(*p
))->s_addr
&
1034 res
->sort_list
[j
].mask
))
1037 if (needsort
== 0 && i
> 0 && j
< aval
[i
-1])
1043 while (needsort
< num
) {
1044 for (j
= needsort
- 1; j
>= 0; j
--) {
1045 if (aval
[j
] > aval
[j
+1]) {
1049 aval
[j
] = aval
[j
+1];
1065 host
.h_addrtype
= 0;
1072 _dns_gethtbyname(void *rv
, void *cb_data
, va_list ap
)
1081 _DIAGASSERT(rv
!= NULL
);
1083 name
= va_arg(ap
, char *);
1084 /* NOSTRICT skip len */(void)va_arg(ap
, int);
1085 af
= va_arg(ap
, int);
1097 buf
= malloc(sizeof(*buf
));
1099 h_errno
= NETDB_INTERNAL
;
1102 res
= __res_get_state();
1107 n
= res_nsearch(res
, name
, C_IN
, type
, buf
->buf
, sizeof(buf
->buf
));
1110 dprintf("res_nsearch failed (%d)\n", res
, n
);
1111 __res_put_state(res
);
1114 hp
= getanswer(buf
, n
, name
, type
, res
);
1116 __res_put_state(res
);
1119 case HOST_NOT_FOUND
:
1126 *((struct hostent
**)rv
) = hp
;
1132 _dns_gethtbyaddr(void *rv
, void *cb_data
, va_list ap
)
1134 char qbuf
[MAXDNAME
+ 1], *qp
, *ep
;
1138 const unsigned char *uaddr
;
1139 int len
, af
, advance
;
1142 _DIAGASSERT(rv
!= NULL
);
1144 uaddr
= va_arg(ap
, unsigned char *);
1145 len
= va_arg(ap
, int);
1146 af
= va_arg(ap
, int);
1150 (void)snprintf(qbuf
, sizeof(qbuf
), "%u.%u.%u.%u.in-addr.arpa",
1151 (uaddr
[3] & 0xff), (uaddr
[2] & 0xff),
1152 (uaddr
[1] & 0xff), (uaddr
[0] & 0xff));
1157 ep
= qbuf
+ sizeof(qbuf
) - 1;
1158 for (n
= IN6ADDRSZ
- 1; n
>= 0; n
--) {
1159 advance
= snprintf(qp
, (size_t)(ep
- qp
), "%x.%x.",
1161 ((unsigned int)uaddr
[n
] >> 4) & 0xf);
1162 if (advance
> 0 && qp
+ advance
< ep
)
1165 h_errno
= NETDB_INTERNAL
;
1169 if (strlcat(qbuf
, "ip6.arpa", sizeof(qbuf
)) >= sizeof(qbuf
)) {
1170 h_errno
= NETDB_INTERNAL
;
1178 buf
= malloc(sizeof(*buf
));
1180 h_errno
= NETDB_INTERNAL
;
1183 res
= __res_get_state();
1188 n
= res_nquery(res
, qbuf
, C_IN
, T_PTR
, buf
->buf
, sizeof(buf
->buf
));
1191 dprintf("res_nquery failed (%d)\n", res
, n
);
1192 __res_put_state(res
);
1195 hp
= getanswer(buf
, n
, qbuf
, T_PTR
, res
);
1198 __res_put_state(res
);
1200 case HOST_NOT_FOUND
:
1208 hp
->h_addrtype
= af
;
1210 (void)memcpy(host_addr
, uaddr
, (size_t)len
);
1211 h_addr_ptrs
[0] = (char *)(void *)host_addr
;
1212 h_addr_ptrs
[1] = NULL
;
1213 if (af
== AF_INET
&& (res
->options
& RES_USE_INET6
)) {
1214 map_v4v6_address((char *)(void *)host_addr
,
1215 (char *)(void *)host_addr
);
1216 hp
->h_addrtype
= AF_INET6
;
1217 hp
->h_length
= IN6ADDRSZ
;
1220 __res_put_state(res
);
1221 *((struct hostent
**)rv
) = hp
;
1222 h_errno
= NETDB_SUCCESS
;
1229 _yphostent(char *line
, int af
)
1231 static struct in_addr host_addrs
[MAXADDRS
];
1232 static struct in6_addr host6_addrs
[MAXADDRS
];
1240 _DIAGASSERT(line
!= NULL
);
1243 host
.h_addr_list
= h_addr_ptrs
;
1244 host
.h_addrtype
= af
;
1247 host
.h_length
= INADDRSZ
;
1250 host
.h_length
= IN6ADDRSZ
;
1256 q
= host
.h_aliases
= host_aliases
;
1260 /* check for host_addrs overflow */
1261 if (naddrs
>= sizeof(host_addrs
) / sizeof(host_addrs
[0]))
1263 if (naddrs
>= sizeof(host6_addrs
) / sizeof(host6_addrs
[0]))
1267 cp
= strpbrk(p
, " \t");
1272 /* p has should have an address */
1276 addrok
= inet_aton(p
, &host_addrs
[naddrs
]);
1279 addrok
= inet_pton(af
, p
, &host6_addrs
[naddrs
]);
1283 /* skip to the next line */
1297 *hap
++ = (char *)(void *)&host_addrs
[naddrs
++];
1300 *hap
++ = (char *)(void *)&host6_addrs
[naddrs
++];
1304 while (*cp
== ' ' || *cp
== '\t')
1307 cp
= strpbrk(p
, " \t\n");
1315 else if (strcmp(host
.h_name
, p
)==0)
1317 else if (q
< &host_aliases
[MAXALIASES
- 1])
1324 if (*cp
== ' ' || *cp
== '\t') {
1332 if (q
< &host_aliases
[MAXALIASES
- 1])
1334 cp
= strpbrk(cp
, " \t");
1340 if (host
.h_name
== NULL
)
1349 _yp_gethtbyaddr(void *rv
, void *cb_data
, va_list ap
)
1351 struct hostent
*hp
= NULL
;
1352 static char *__ypcurrent
;
1353 int __ypcurrentlen
, r
;
1354 char name
[INET6_ADDRSTRLEN
]; /* XXX enough? */
1355 const unsigned char *uaddr
;
1359 _DIAGASSERT(rv
!= NULL
);
1361 uaddr
= va_arg(ap
, unsigned char *);
1362 /* NOSTRICT skip len */(void)va_arg(ap
, int);
1363 af
= va_arg(ap
, int);
1366 if (_yp_check(&__ypdomain
) == 0)
1370 * XXX unfortunately, we cannot support IPv6 extended scoped address
1371 * notation here. gethostbyaddr() is not scope-aware. too bad.
1373 if (inet_ntop(af
, uaddr
, name
, sizeof(name
)) == NULL
)
1380 map
= "hosts.byaddr";
1383 map
= "ipnodes.byaddr";
1386 r
= yp_match(__ypdomain
, map
, name
,
1387 (int)strlen(name
), &__ypcurrent
, &__ypcurrentlen
);
1389 hp
= _yphostent(__ypcurrent
, af
);
1391 h_errno
= HOST_NOT_FOUND
;
1394 *((struct hostent
**)rv
) = hp
;
1400 _yp_gethtbyname(void *rv
, void *cb_data
, va_list ap
)
1402 struct hostent
*hp
= NULL
;
1403 static char *__ypcurrent
;
1404 int __ypcurrentlen
, r
;
1409 _DIAGASSERT(rv
!= NULL
);
1411 name
= va_arg(ap
, char *);
1412 /* NOSTRICT skip len */(void)va_arg(ap
, int);
1413 af
= va_arg(ap
, int);
1416 if (_yp_check(&__ypdomain
) == 0)
1424 map
= "hosts.byname";
1427 map
= "ipnodes.byname";
1430 r
= yp_match(__ypdomain
, map
, name
,
1431 (int)strlen(name
), &__ypcurrent
, &__ypcurrentlen
);
1433 hp
= _yphostent(__ypcurrent
, af
);
1435 h_errno
= HOST_NOT_FOUND
;
1438 *((struct hostent
**)rv
) = hp
;