2 * ++Copyright++ 1985, 1988, 1993
4 * Copyright (c) 1985, 1988, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
37 * Permission to use, copy, modify, and distribute this software for any
38 * purpose with or without fee is hereby granted, provided that the above
39 * copyright notice and this permission notice appear in all copies, and that
40 * the name of Digital Equipment Corporation not be used in advertising or
41 * publicity pertaining to distribution of the document or software without
42 * specific, written prior permission.
44 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
45 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
46 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
47 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
48 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
49 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
50 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
56 #if defined(LIBC_SCCS) && !defined(lint)
57 static char sccsid
[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
58 static char rcsid
[] = "$Id$";
59 #endif /* LIBC_SCCS and not lint */
61 #include <sys/types.h>
62 #include <sys/param.h>
63 #include <sys/socket.h>
64 #include <netinet/in.h>
65 #include <arpa/inet.h>
66 #include <arpa/nameser.h>
79 #define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
81 #if defined(BSD) && (BSD >= 199103) && defined(AF_INET6)
85 # include "../conf/portability.h"
88 #if defined(USE_OPTIONS_H)
89 # include <../conf/options.h>
93 # define SPRINTF(x) strlen(sprintf/**/x)
95 # define SPRINTF(x) ((size_t)sprintf x)
101 static const char AskedForGot
[] =
102 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
104 static char *h_addr_ptrs
[MAXADDRS
+ 1];
106 static struct hostent host
;
107 static char *host_aliases
[MAXALIASES
];
108 static char hostbuf
[8*1024];
109 static u_char host_addr
[16]; /* IPv4 or IPv6 */
110 static FILE *hostf
= NULL
;
111 static int stayopen
= 0;
113 static void map_v4v6_address
__P((const char *src
, char *dst
));
114 static void map_v4v6_hostent
__P((struct hostent
*hp
, char **bp
, int *len
));
117 static void addrsort
__P((char **, int));
121 #define MAXPACKET PACKETSZ
123 #define MAXPACKET 1024
128 u_char buf
[MAXPACKET
];
144 if (_res
.options
& RES_DEBUG
) {
152 # define dprintf(msg, num) /*nada*/
155 static struct hostent
*
156 getanswer(answer
, anslen
, qname
, qtype
)
157 const querybuf
*answer
;
162 register const HEADER
*hp
;
163 register const u_char
*cp
;
166 char *bp
, **ap
, **hap
;
167 int type
, class, buflen
, ancount
, qdcount
;
168 int haveanswer
, had_error
;
172 int (*name_ok
) __P((const char *));
176 eom
= answer
->buf
+ anslen
;
186 return (NULL
); /* XXX should be abort(); */
189 * find first satisfactory answer
192 ancount
= ntohs(hp
->ancount
);
193 qdcount
= ntohs(hp
->qdcount
);
195 buflen
= sizeof hostbuf
;
196 cp
= answer
->buf
+ HFIXEDSZ
;
198 __set_h_errno (NO_RECOVERY
);
201 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, buflen
);
202 if ((n
< 0) || !(*name_ok
)(bp
)) {
203 __set_h_errno (NO_RECOVERY
);
207 if (qtype
== T_A
|| qtype
== T_AAAA
) {
208 /* res_send() has already verified that the query name is the
209 * same as the one we sent; this just gets the expanded name
210 * (i.e., with the succeeding search-domain tacked on).
212 n
= strlen(bp
) + 1; /* for the \0 */
216 /* The qname can be abbreviated, but h_name is now absolute. */
221 host
.h_aliases
= host_aliases
;
224 host
.h_addr_list
= h_addr_ptrs
;
227 while (ancount
-- > 0 && cp
< eom
&& !had_error
) {
228 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, buflen
);
229 if ((n
< 0) || !(*name_ok
)(bp
)) {
234 type
= _getshort(cp
);
235 cp
+= INT16SZ
; /* type */
236 class = _getshort(cp
);
237 cp
+= INT16SZ
+ INT32SZ
; /* class, TTL */
239 cp
+= INT16SZ
; /* len */
241 /* XXX - debug? syslog? */
243 continue; /* XXX - had_error++ ? */
245 if ((qtype
== T_A
|| qtype
== T_AAAA
) && type
== T_CNAME
) {
246 if (ap
>= &host_aliases
[MAXALIASES
-1])
248 n
= dn_expand(answer
->buf
, eom
, cp
, tbuf
, sizeof tbuf
);
249 if ((n
< 0) || !(*name_ok
)(tbuf
)) {
256 n
= strlen(bp
) + 1; /* for the \0 */
259 /* Get canonical name. */
260 n
= strlen(tbuf
) + 1; /* for the \0 */
271 if (qtype
== T_PTR
&& type
== T_CNAME
) {
272 n
= dn_expand(answer
->buf
, eom
, cp
, tbuf
, sizeof tbuf
);
273 if ((n
< 0) || !res_hnok(tbuf
)) {
278 /* Get canonical name. */
279 n
= strlen(tbuf
) + 1; /* for the \0 */
291 syslog(LOG_NOTICE
|LOG_AUTH
,
292 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
293 qname
, p_class(C_IN
), p_type(qtype
),
296 continue; /* XXX - had_error++ ? */
300 if (strcasecmp(tname
, bp
) != 0) {
301 syslog(LOG_NOTICE
|LOG_AUTH
,
302 AskedForGot
, qname
, bp
);
304 continue; /* XXX - had_error++ ? */
306 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, buflen
);
307 if ((n
< 0) || !res_hnok(bp
)) {
311 #if MULTI_PTRS_ARE_ALIASES
315 else if (ap
< &host_aliases
[MAXALIASES
-1])
320 n
= strlen(bp
) + 1; /* for the \0 */
327 if (_res
.options
& RES_USE_INET6
) {
328 n
= strlen(bp
) + 1; /* for the \0 */
331 map_v4v6_hostent(&host
, &bp
, &buflen
);
333 __set_h_errno (NETDB_SUCCESS
);
338 if (strcasecmp(host
.h_name
, bp
) != 0) {
339 syslog(LOG_NOTICE
|LOG_AUTH
,
340 AskedForGot
, host
.h_name
, bp
);
342 continue; /* XXX - had_error++ ? */
344 if (n
!= host
.h_length
) {
352 nn
= strlen(bp
) + 1; /* for the \0 */
357 bp
+= sizeof(align
) - ((u_long
)bp
% sizeof(align
));
359 if (bp
+ n
>= &hostbuf
[sizeof hostbuf
]) {
360 dprintf("size (%d) too big\n", n
);
364 if (hap
>= &h_addr_ptrs
[MAXADDRS
-1]) {
366 dprintf("Too many addresses (%d)\n",
371 bcopy(cp
, *hap
++ = bp
, n
);
385 # if defined(RESOLVSORT)
387 * Note: we sort even if host can take only one address
388 * in its return structures - should give it the "best"
389 * address in that case, not some random one
391 if (_res
.nsort
&& haveanswer
> 1 && qtype
== T_A
)
392 addrsort(h_addr_ptrs
, haveanswer
);
393 # endif /*RESOLVSORT*/
395 n
= strlen(qname
) + 1; /* for the \0 */
403 if (_res
.options
& RES_USE_INET6
)
404 map_v4v6_hostent(&host
, &bp
, &buflen
);
405 __set_h_errno (NETDB_SUCCESS
);
409 __set_h_errno (TRY_AGAIN
);
419 if ((_res
.options
& RES_INIT
) == 0 && res_init() == -1) {
420 __set_h_errno (NETDB_INTERNAL
);
423 if (_res
.options
& RES_USE_INET6
) {
424 hp
= gethostbyname2(name
, AF_INET6
);
428 return (gethostbyname2(name
, AF_INET
));
432 gethostbyname2(name
, af
)
437 register const char *cp
;
439 int n
, size
, type
, len
;
440 extern struct hostent
*_gethtbyname2();
442 if ((_res
.options
& RES_INIT
) == 0 && res_init() == -1) {
443 __set_h_errno (NETDB_INTERNAL
);
457 __set_h_errno (NETDB_INTERNAL
);
458 __set_errno (EAFNOSUPPORT
);
462 host
.h_addrtype
= af
;
463 host
.h_length
= size
;
466 * if there aren't any dots, it could be a user-level alias.
467 * this is also done in res_query() since we are not the only
468 * function that looks up host names.
470 if (!strchr(name
, '.') && (cp
= __hostalias(name
)))
474 * disallow names consisting only of digits/dots, unless
477 if (isdigit(name
[0]))
478 for (cp
= name
;; ++cp
) {
483 * All-numeric, no dot at the end.
484 * Fake up a hostent as if we'd actually
487 if (inet_pton(af
, name
, host_addr
) <= 0) {
488 __set_h_errno (HOST_NOT_FOUND
);
491 strncpy(hostbuf
, name
, MAXDNAME
);
492 hostbuf
[MAXDNAME
] = '\0';
493 bp
= hostbuf
+ MAXDNAME
;
494 len
= sizeof hostbuf
- MAXDNAME
;
495 host
.h_name
= hostbuf
;
496 host
.h_aliases
= host_aliases
;
497 host_aliases
[0] = NULL
;
498 h_addr_ptrs
[0] = (char *)host_addr
;
499 h_addr_ptrs
[1] = NULL
;
500 host
.h_addr_list
= h_addr_ptrs
;
501 if (_res
.options
& RES_USE_INET6
)
502 map_v4v6_hostent(&host
, &bp
, &len
);
503 __set_h_errno (NETDB_SUCCESS
);
506 if (!isdigit(*cp
) && *cp
!= '.')
509 if (isxdigit(name
[0]) || name
[0] == ':')
510 for (cp
= name
;; ++cp
) {
515 * All-IPv6-legal, no dot at the end.
516 * Fake up a hostent as if we'd actually
519 if (inet_pton(af
, name
, host_addr
) <= 0) {
520 __set_h_errno (HOST_NOT_FOUND
);
523 strncpy(hostbuf
, name
, MAXDNAME
);
524 hostbuf
[MAXDNAME
] = '\0';
525 bp
= hostbuf
+ MAXDNAME
;
526 len
= sizeof hostbuf
- MAXDNAME
;
527 host
.h_name
= hostbuf
;
528 host
.h_aliases
= host_aliases
;
529 host_aliases
[0] = NULL
;
530 h_addr_ptrs
[0] = (char *)host_addr
;
531 h_addr_ptrs
[1] = NULL
;
532 host
.h_addr_list
= h_addr_ptrs
;
533 __set_h_errno (NETDB_SUCCESS
);
536 if (!isxdigit(*cp
) && *cp
!= ':' && *cp
!= '.')
540 if ((n
= res_search(name
, C_IN
, type
, buf
.buf
, sizeof(buf
))) < 0) {
541 dprintf("res_search failed (%d)\n", n
);
542 if (errno
== ECONNREFUSED
)
543 return (_gethtbyname2(name
, af
));
546 return (getanswer(&buf
, n
, name
, type
));
550 gethostbyaddr(addr
, len
, af
)
551 const char *addr
; /* XXX should have been def'd as u_char! */
554 const u_char
*uaddr
= (const u_char
*)addr
;
555 static const u_char mapped
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
556 static const u_char tunnelled
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
559 register struct hostent
*hp
;
560 char qbuf
[MAXDNAME
+1], *qp
;
562 register struct hostent
*rhp
;
565 char hname2
[MAXDNAME
+1];
566 #endif /*SUNSECURITY*/
567 extern struct hostent
*_gethtbyaddr();
569 if ((_res
.options
& RES_INIT
) == 0 && res_init() == -1) {
570 __set_h_errno (NETDB_INTERNAL
);
573 if (af
== AF_INET6
&& len
== IN6ADDRSZ
&&
574 (!bcmp(uaddr
, mapped
, sizeof mapped
) ||
575 !bcmp(uaddr
, tunnelled
, sizeof tunnelled
))) {
577 addr
+= sizeof mapped
;
578 uaddr
+= sizeof mapped
;
590 __set_errno (EAFNOSUPPORT
);
591 __set_h_errno (NETDB_INTERNAL
);
595 __set_errno (EINVAL
);
596 __set_h_errno (NETDB_INTERNAL
);
601 (void) sprintf(qbuf
, "%u.%u.%u.%u.in-addr.arpa",
609 for (n
= IN6ADDRSZ
- 1; n
>= 0; n
--) {
610 qp
+= SPRINTF((qp
, "%x.%x.",
612 (uaddr
[n
] >> 4) & 0xf));
614 strcpy(qp
, "ip6.int");
619 n
= res_query(qbuf
, C_IN
, T_PTR
, (u_char
*)buf
.buf
, sizeof buf
.buf
);
621 dprintf("res_query failed (%d)\n", n
);
622 if (errno
== ECONNREFUSED
)
623 return (_gethtbyaddr(addr
, len
, af
));
626 if (!(hp
= getanswer(&buf
, n
, qbuf
, T_PTR
)))
627 return (NULL
); /* h_errno was set by getanswer() */
631 * turn off search as the name should be absolute,
632 * 'localhost' should be matched by defnames
634 strncpy(hname2
, hp
->h_name
, MAXDNAME
);
635 hname2
[MAXDNAME
] = '\0';
636 old_options
= _res
.options
;
637 _res
.options
&= ~RES_DNSRCH
;
638 _res
.options
|= RES_DEFNAMES
;
639 if (!(rhp
= gethostbyname(hname2
))) {
640 syslog(LOG_NOTICE
|LOG_AUTH
,
641 "gethostbyaddr: No A record for %s (verifying [%s])",
642 hname2
, inet_ntoa(*((struct in_addr
*)addr
)));
643 _res
.options
= old_options
;
644 __set_h_errno (HOST_NOT_FOUND
);
647 _res
.options
= old_options
;
648 for (haddr
= rhp
->h_addr_list
; *haddr
; haddr
++)
649 if (!memcmp(*haddr
, addr
, INADDRSZ
))
652 syslog(LOG_NOTICE
|LOG_AUTH
,
653 "gethostbyaddr: A record of %s != PTR record [%s]",
654 hname2
, inet_ntoa(*((struct in_addr
*)addr
)));
655 __set_h_errno (HOST_NOT_FOUND
);
659 #endif /*SUNSECURITY*/
662 bcopy(addr
, host_addr
, len
);
663 h_addr_ptrs
[0] = (char *)host_addr
;
664 h_addr_ptrs
[1] = NULL
;
665 if (af
== AF_INET
&& (_res
.options
& RES_USE_INET6
)) {
666 map_v4v6_address((char*)host_addr
, (char*)host_addr
);
667 hp
->h_addrtype
= AF_INET6
;
668 hp
->h_length
= IN6ADDRSZ
;
670 __set_h_errno (NETDB_SUCCESS
);
679 hostf
= fopen(_PATH_HOSTS
, "r" );
688 if (hostf
&& !stayopen
) {
689 (void) fclose(hostf
);
698 register char *cp
, **q
;
701 if (!hostf
&& !(hostf
= fopen(_PATH_HOSTS
, "r" ))) {
702 __set_h_errno (NETDB_INTERNAL
);
706 if (!(p
= fgets(hostbuf
, sizeof hostbuf
, hostf
))) {
707 __set_h_errno (HOST_NOT_FOUND
);
712 if (!(cp
= strpbrk(p
, "#\n")))
715 if (!(cp
= strpbrk(p
, " \t")))
718 if ((_res
.options
& RES_USE_INET6
) &&
719 inet_pton(AF_INET6
, p
, host_addr
) > 0) {
722 } else if (inet_pton(AF_INET
, p
, host_addr
) > 0) {
723 if (_res
.options
& RES_USE_INET6
) {
724 map_v4v6_address((char*)host_addr
, (char*)host_addr
);
734 h_addr_ptrs
[0] = (char *)host_addr
;
735 h_addr_ptrs
[1] = NULL
;
736 host
.h_addr_list
= h_addr_ptrs
;
738 host
.h_addrtype
= af
;
739 while (*cp
== ' ' || *cp
== '\t')
742 q
= host
.h_aliases
= host_aliases
;
743 if (cp
= strpbrk(cp
, " \t"))
746 if (*cp
== ' ' || *cp
== '\t') {
750 if (q
< &host_aliases
[MAXALIASES
- 1])
752 if (cp
= strpbrk(cp
, " \t"))
756 if (_res
.options
& RES_USE_INET6
) {
758 int buflen
= sizeof hostbuf
;
760 map_v4v6_hostent(&host
, &bp
, &buflen
);
762 __set_h_errno (NETDB_SUCCESS
);
770 extern struct hostent
*_gethtbyname2();
773 if (_res
.options
& RES_USE_INET6
) {
774 hp
= _gethtbyname2(name
, AF_INET6
);
778 return (_gethtbyname2(name
, AF_INET
));
782 _gethtbyname2(name
, af
)
786 register struct hostent
*p
;
790 while (p
= _gethtent()) {
791 if (p
->h_addrtype
!= af
)
793 if (strcasecmp(p
->h_name
, name
) == 0)
795 for (cp
= p
->h_aliases
; *cp
!= 0; cp
++)
796 if (strcasecmp(*cp
, name
) == 0)
805 _gethtbyaddr(addr
, len
, af
)
809 register struct hostent
*p
;
812 while (p
= _gethtent())
813 if (p
->h_addrtype
== af
&& !bcmp(p
->h_addr
, addr
, len
))
820 map_v4v6_address(src
, dst
)
824 u_char
*p
= (u_char
*)dst
;
828 /* Stash a temporary copy so our caller can update in place. */
829 bcopy(src
, tmp
, INADDRSZ
);
830 /* Mark this ipv6 addr as a mapped ipv4. */
831 for (i
= 0; i
< 10; i
++)
835 /* Retrieve the saved copy and we're done. */
836 bcopy(tmp
, (void*)p
, INADDRSZ
);
840 map_v4v6_hostent(hp
, bpp
, lenp
)
847 if (hp
->h_addrtype
!= AF_INET
|| hp
->h_length
!= INADDRSZ
)
849 hp
->h_addrtype
= AF_INET6
;
850 hp
->h_length
= IN6ADDRSZ
;
851 for (ap
= hp
->h_addr_list
; *ap
; ap
++) {
852 int i
= sizeof(align
) - ((u_long
)*bpp
% sizeof(align
));
854 if (*lenp
< (i
+ IN6ADDRSZ
)) {
855 /* Out of memory. Truncate address list here. XXX */
861 map_v4v6_address(*ap
, *bpp
);
876 short aval
[MAXADDRS
];
880 for (i
= 0; i
< num
; i
++, p
++) {
881 for (j
= 0 ; (unsigned)j
< _res
.nsort
; j
++)
882 if (_res
.sort_list
[j
].addr
.s_addr
==
883 (((struct in_addr
*)(*p
))->s_addr
& _res
.sort_list
[j
].mask
))
886 if (needsort
== 0 && i
> 0 && j
< aval
[i
-1])
892 while (needsort
< num
) {
893 for (j
= needsort
- 1; j
>= 0; j
--) {
894 if (aval
[j
] > aval
[j
+1]) {
913 #if defined(BSD43_BSD43_NFS) || defined(sun)
914 /* some libc's out there are bound internally to these names (UMIPS) */
916 ht_sethostent(stayopen
)
929 ht_gethostbyname(name
)
932 return (_gethtbyname(name
));
936 ht_gethostbyaddr(addr
, len
, af
)
940 return (_gethtbyaddr(addr
, len
, af
));
946 return (_gethtent());
956 dn_skipname(comp_dn
, eom
)
957 const u_char
*comp_dn
, *eom
;
959 return (__dn_skipname(comp_dn
, eom
));
961 #endif /*old-style libc with yp junk in it*/