]>
git.proxmox.com Git - mirror_edk2.git/blob - StdLib/BsdSocketLib/gethostbydns.c
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
57 * Portions copyright (c) 1999, 2000
59 * All rights reserved.
61 * Redistribution and use in source and binary forms, with or without
62 * modification, are permitted provided that the following conditions
65 * 1. Redistributions of source code must retain the above copyright
66 * notice, this list of conditions and the following disclaimer.
68 * 2. Redistributions in binary form must reproduce the above copyright
69 * notice, this list of conditions and the following disclaimer in the
70 * documentation and/or other materials provided with the distribution.
72 * 3. All advertising materials mentioning features or use of this software
73 * must display the following acknowledgement:
75 * This product includes software developed by Intel Corporation and
78 * 4. Neither the name of Intel Corporation or its contributors may be
79 * used to endorse or promote products derived from this software
80 * without specific prior written permission.
82 * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
83 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
84 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
85 * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
86 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
87 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
88 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
89 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
90 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
91 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
92 * THE POSSIBILITY OF SUCH DAMAGE.
96 #if defined(LIBC_SCCS) && !defined(lint)
97 static char sccsid
[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
98 static char fromrcsid
[] = "From: Id: gethnamaddr.c,v 8.23 1998/04/07 04:59:46 vixie Exp $";
99 static char rcsid
[] = "$Id: gethostbydns.c,v 1.1.1.1 2003/11/19 01:51:27 kyu3 Exp $";
100 #endif /* LIBC_SCCS and not lint */
102 #include <sys/types.h>
103 #include <sys/param.h>
104 #include <sys/socket.h>
105 #include <netinet/in.h>
106 #include <arpa/inet.h>
107 #include <arpa/nameser.h>
120 u_int32_t
_getlong(const u_char
*src
);
121 u_int16_t
_getshort(const u_char
*src
);
124 #include "res_config.h"
125 #include "Socklib_internals.h"
127 #define SPRINTF(x) ((size_t)sprintf x)
129 #define MAXALIASES 35
132 static const char AskedForGot
[] =
133 "gethostby*.gethostanswer: asked for \"%s\", got \"%s\"";
135 static char *h_addr_ptrs
[MAXADDRS
+ 1];
137 static struct hostent host
;
138 static char *host_aliases
[MAXALIASES
];
139 static char hostbuf
[8*1024];
140 static u_char host_addr
[16]; /* IPv4 or IPv6 */
143 static void addrsort(char **, int);
147 #define MAXPACKET PACKETSZ
149 #define MAXPACKET 1024
154 u_char buf
[MAXPACKET
];
167 dprintf(char *msg
, int num
)
169 if (_res
.options
& RES_DEBUG
) {
177 # define dprintf(msg, num) /*nada*/
180 #define BOUNDED_INCR(x) \
184 h_errno = NO_RECOVERY; \
189 #define BOUNDS_CHECK(ptr, count) \
191 if ((ptr) + (count) > eom) { \
192 h_errno = NO_RECOVERY; \
197 static struct hostent
*
198 gethostanswer(const querybuf
*answer
, int anslen
, const char *qname
, int qtype
)
200 register const HEADER
*hp
;
201 register const u_char
*cp
;
203 const u_char
*eom
, *erdata
;
204 char *bp
, **ap
, **hap
;
205 int type
, class, buflen
, ancount
, qdcount
;
206 int haveanswer
, had_error
;
210 int (*name_ok
)(const char *);
214 eom
= answer
->buf
+ anslen
;
224 h_errno
= NO_RECOVERY
;
225 return (NULL
); /* XXX should be abort(); */
228 * find first satisfactory answer
231 ancount
= ntohs(hp
->ancount
);
232 qdcount
= ntohs(hp
->qdcount
);
234 buflen
= sizeof hostbuf
;
236 BOUNDED_INCR(HFIXEDSZ
);
238 h_errno
= NO_RECOVERY
;
241 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, buflen
);
242 if ((n
< 0) || !(*name_ok
)(bp
)) {
243 h_errno
= NO_RECOVERY
;
246 BOUNDED_INCR(n
+ QFIXEDSZ
);
247 if (qtype
== T_A
|| qtype
== T_AAAA
) {
248 /* res_send() has already verified that the query name is the
249 * same as the one we sent; this just gets the expanded name
250 * (i.e., with the succeeding search-domain tacked on).
252 n
= (int)strlen(bp
) + 1; /* for the \0 */
253 if (n
>= MAXHOSTNAMELEN
) {
254 h_errno
= NO_RECOVERY
;
260 /* The qname can be abbreviated, but h_name is now absolute. */
265 host
.h_aliases
= host_aliases
;
268 host
.h_addr_list
= h_addr_ptrs
;
272 while (ancount
-- > 0 && cp
< eom
&& !had_error
) {
273 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, buflen
);
274 if ((n
< 0) || !(*name_ok
)(bp
)) {
279 BOUNDS_CHECK(cp
, 3 * INT16SZ
+ INT32SZ
);
280 type
= _getshort(cp
);
281 cp
+= INT16SZ
; /* type */
282 class = _getshort(cp
);
283 cp
+= INT16SZ
; /* class */
284 if (qtype
== T_A
&& type
== T_A
)
285 _dns_ttl_
= _getlong(cp
);
286 cp
+= INT32SZ
; /* TTL */
288 cp
+= INT16SZ
; /* len */
292 /* XXX - debug? syslog? */
294 continue; /* XXX - had_error++ ? */
296 if ((qtype
== T_A
|| qtype
== T_AAAA
) && type
== T_CNAME
) {
297 if (ap
>= &host_aliases
[MAXALIASES
-1])
299 n
= dn_expand(answer
->buf
, eom
, cp
, tbuf
, sizeof tbuf
);
300 if ((n
< 0) || !(*name_ok
)(tbuf
)) {
306 h_errno
= NO_RECOVERY
;
311 n
= (int)strlen(bp
) + 1; /* for the \0 */
312 if (n
>= MAXHOSTNAMELEN
) {
318 /* Get canonical name. */
319 n
= (int)strlen(tbuf
) + 1; /* for the \0 */
320 if (n
> buflen
|| n
>= MAXHOSTNAMELEN
) {
330 if (qtype
== T_PTR
&& type
== T_CNAME
) {
331 n
= dn_expand(answer
->buf
, eom
, cp
, tbuf
, sizeof tbuf
);
332 if (n
< 0 || !res_dnok(tbuf
)) {
338 h_errno
= NO_RECOVERY
;
341 /* Get canonical name. */
342 n
= (int)strlen(tbuf
) + 1; /* for the \0 */
343 if (n
> buflen
|| n
>= MAXHOSTNAMELEN
) {
355 syslog(LOG_NOTICE
|LOG_AUTH
,
356 "gethostby*.gethostanswer: asked for \"%s %s %s\", got type \"%s\"",
357 qname
, p_class(C_IN
), p_type(qtype
),
361 continue; /* XXX - had_error++ ? */
365 if (strcasecmp(tname
, bp
) != 0) {
367 syslog(LOG_NOTICE
|LOG_AUTH
,
368 AskedForGot
, qname
, bp
);
371 continue; /* XXX - had_error++ ? */
373 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, buflen
);
374 if ((n
< 0) || !res_hnok(bp
)) {
378 #if MULTI_PTRS_ARE_ALIASES
381 h_errno
= NO_RECOVERY
;
386 else if (ap
< &host_aliases
[MAXALIASES
-1])
391 n
= (int)strlen(bp
) + 1; /* for the \0 */
392 if (n
>= MAXHOSTNAMELEN
) {
402 if (_res
.options
& RES_USE_INET6
) {
403 n
= strlen(bp
) + 1; /* for the \0 */
404 if (n
>= MAXHOSTNAMELEN
) {
410 _map_v4v6_hostent(&host
, &bp
, &buflen
);
412 h_errno
= NETDB_SUCCESS
;
417 if (strcasecmp(host
.h_name
, bp
) != 0) {
419 syslog(LOG_NOTICE
|LOG_AUTH
,
420 AskedForGot
, host
.h_name
, bp
);
423 continue; /* XXX - had_error++ ? */
425 if (n
!= host
.h_length
) {
433 nn
= (int)strlen(bp
) + 1; /* for the \0 */
438 bp
+= sizeof(align
) - ((size_t)bp
% sizeof(align
));
440 if (bp
+ n
>= &hostbuf
[sizeof hostbuf
]) {
441 dprintf("size (%d) too big\n", n
);
445 if (hap
>= &h_addr_ptrs
[MAXADDRS
-1]) {
447 dprintf("Too many addresses (%d)\n",
458 h_errno
= NO_RECOVERY
;
463 dprintf("Impossible condition (type=%d)\n", type
);
464 h_errno
= NO_RECOVERY
;
466 /* BIND has abort() here, too risky on bad data */
474 # if defined(RESOLVSORT)
476 * Note: we sort even if host can take only one address
477 * in its return structures - should give it the "best"
478 * address in that case, not some random one
480 if (_res
.nsort
&& haveanswer
> 1 && qtype
== T_A
)
481 addrsort(h_addr_ptrs
, haveanswer
);
482 # endif /*RESOLVSORT*/
484 n
= (int)strlen(qname
) + 1; /* for the \0 */
485 if (n
> buflen
|| n
>= MAXHOSTNAMELEN
)
492 if (_res
.options
& RES_USE_INET6
)
493 _map_v4v6_hostent(&host
, &bp
, &buflen
);
494 h_errno
= NETDB_SUCCESS
;
498 h_errno
= NO_RECOVERY
;
503 __dns_getanswer(const char *answer
, int anslen
, const char *qname
, int qtype
)
507 host
.h_addrtype
= AF_INET6
;
508 host
.h_length
= IN6ADDRSZ
;
512 host
.h_addrtype
= AF_INET
;
513 host
.h_length
= INADDRSZ
;
517 return(gethostanswer((const querybuf
*)answer
, anslen
, qname
, qtype
));
521 _gethostbydnsname(const char *name
, int af
)
524 register const char *cp
;
526 int n
, size
, type
, len
;
528 if ((_res
.options
& RES_INIT
) == 0 && res_init() == -1) {
529 h_errno
= NETDB_INTERNAL
;
543 h_errno
= NETDB_INTERNAL
;
544 errno
= EAFNOSUPPORT
;
548 host
.h_addrtype
= af
;
549 host
.h_length
= size
;
552 * if there aren't any dots, it could be a user-level alias.
553 * this is also done in res_query() since we are not the only
554 * function that looks up host names.
556 if (!strchr(name
, '.') && ( NULL
!= (cp
= __hostalias(name
))))
560 * disallow names consisting only of digits/dots, unless
563 if (isdigit(name
[0]))
564 for (cp
= name
;; ++cp
) {
569 * All-numeric, no dot at the end.
570 * Fake up a hostent as if we'd actually
573 if (inet_pton(af
, name
, host_addr
) <= 0) {
574 h_errno
= HOST_NOT_FOUND
;
577 strncpy(hostbuf
, name
, MAXDNAME
);
578 hostbuf
[MAXDNAME
] = '\0';
579 bp
= hostbuf
+ MAXDNAME
;
580 len
= sizeof hostbuf
- MAXDNAME
;
581 host
.h_name
= hostbuf
;
582 host
.h_aliases
= host_aliases
;
583 host_aliases
[0] = NULL
;
584 h_addr_ptrs
[0] = (char *)host_addr
;
585 h_addr_ptrs
[1] = NULL
;
586 host
.h_addr_list
= h_addr_ptrs
;
587 if (_res
.options
& RES_USE_INET6
)
588 _map_v4v6_hostent(&host
, &bp
, &len
);
589 h_errno
= NETDB_SUCCESS
;
592 if (!isdigit(*cp
) && *cp
!= '.')
595 if ((isxdigit(name
[0]) && strchr(name
, ':') != NULL
) ||
597 for (cp
= name
;; ++cp
) {
602 * All-IPv6-legal, no dot at the end.
603 * Fake up a hostent as if we'd actually
606 if (inet_pton(af
, name
, host_addr
) <= 0) {
607 h_errno
= HOST_NOT_FOUND
;
610 strncpy(hostbuf
, name
, MAXDNAME
);
611 hostbuf
[MAXDNAME
] = '\0';
612 bp
= hostbuf
+ MAXDNAME
;
613 len
= sizeof hostbuf
- MAXDNAME
;
614 host
.h_name
= hostbuf
;
615 host
.h_aliases
= host_aliases
;
616 host_aliases
[0] = NULL
;
617 h_addr_ptrs
[0] = (char *)host_addr
;
618 h_addr_ptrs
[1] = NULL
;
619 host
.h_addr_list
= h_addr_ptrs
;
620 h_errno
= NETDB_SUCCESS
;
623 if (!isxdigit(*cp
) && *cp
!= ':' && *cp
!= '.')
627 if ((n
= res_search(name
, C_IN
, type
, buf
.buf
, sizeof(buf
))) < 0) {
628 dprintf("res_search failed (%d)\n", n
);
631 return (gethostanswer(&buf
, n
, name
, type
));
635 _gethostbydnsaddr(const char *addr
, int len
, int af
)
637 const u_char
*uaddr
= (const u_char
*)addr
;
638 static const u_char mapped
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
639 static const u_char tunnelled
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
642 register struct hostent
*hp
;
643 char qbuf
[MAXDNAME
+1], *qp
;
645 register struct hostent
*rhp
;
648 char hname2
[MAXDNAME
+1];
649 #endif /*SUNSECURITY*/
651 if ((_res
.options
& RES_INIT
) == 0 && res_init() == -1) {
652 h_errno
= NETDB_INTERNAL
;
655 if (af
== AF_INET6
&& len
== IN6ADDRSZ
&&
656 (!bcmp(uaddr
, mapped
, sizeof mapped
) ||
657 !bcmp(uaddr
, tunnelled
, sizeof tunnelled
))) {
659 addr
+= sizeof mapped
;
660 uaddr
+= sizeof mapped
;
672 errno
= EAFNOSUPPORT
;
673 h_errno
= NETDB_INTERNAL
;
678 h_errno
= NETDB_INTERNAL
;
683 (void) sprintf(qbuf
, "%u.%u.%u.%u.in-addr.arpa",
691 for (n
= IN6ADDRSZ
- 1; n
>= 0; n
--) {
692 qp
+= SPRINTF((qp
, "%x.%x.",
694 (uaddr
[n
] >> 4) & 0xf));
696 strcpy(qp
, "ip6.int");
701 n
= res_query(qbuf
, C_IN
, T_PTR
, (u_char
*)buf
.buf
, sizeof buf
.buf
);
703 dprintf("res_query failed (%d)\n", n
);
706 if ( NULL
== (hp
= gethostanswer(&buf
, n
, qbuf
, T_PTR
)))
707 return (NULL
); /* h_errno was set by gethostanswer() */
711 * turn off search as the name should be absolute,
712 * 'localhost' should be matched by defnames
714 strncpy(hname2
, hp
->h_name
, MAXDNAME
);
715 hname2
[MAXDNAME
] = '\0';
716 old_options
= _res
.options
;
717 _res
.options
&= ~RES_DNSRCH
;
718 _res
.options
|= RES_DEFNAMES
;
719 if (!(rhp
= gethostbyname(hname2
))) {
721 syslog(LOG_NOTICE
|LOG_AUTH
,
722 "gethostbyaddr: No A record for %s (verifying [%s])",
723 hname2
, inet_ntoa(*((struct in_addr
*)addr
)));
725 _res
.options
= old_options
;
726 h_errno
= HOST_NOT_FOUND
;
729 _res
.options
= old_options
;
730 for (haddr
= rhp
->h_addr_list
; *haddr
; haddr
++)
731 if (!memcmp(*haddr
, addr
, INADDRSZ
))
735 syslog(LOG_NOTICE
|LOG_AUTH
,
736 "gethostbyaddr: A record of %s != PTR record [%s]",
737 hname2
, inet_ntoa(*((struct in_addr
*)addr
)));
739 h_errno
= HOST_NOT_FOUND
;
743 #endif /*SUNSECURITY*/
746 bcopy(addr
, host_addr
, len
);
747 h_addr_ptrs
[0] = (char *)host_addr
;
748 h_addr_ptrs
[1] = NULL
;
749 if (af
== AF_INET
&& (_res
.options
& RES_USE_INET6
)) {
750 _map_v4v6_address((char*)host_addr
, (char*)host_addr
);
751 hp
->h_addrtype
= AF_INET6
;
752 hp
->h_length
= IN6ADDRSZ
;
754 h_errno
= NETDB_SUCCESS
;
760 addrsort(char **ap
, int num
)
764 short aval
[MAXADDRS
];
768 for (i
= 0; i
< num
; i
++, p
++) {
769 for (j
= 0 ; (unsigned)j
< _res
.nsort
; j
++)
770 if (_res
.sort_list
[j
].addr
.s_addr
==
771 (((struct in_addr
*)(*p
))->s_addr
& _res
.sort_list
[j
].mask
))
774 if (needsort
== 0 && i
> 0 && j
< aval
[i
-1])
780 while (needsort
< num
) {
781 for (j
= needsort
- 1; j
>= 0; j
--) {
782 if (aval
[j
] > aval
[j
+1]) {
801 _sethostdnsent(int stayopen
)
803 if ((_res
.options
& RES_INIT
) == 0 && res_init() == -1)
806 _res
.options
|= RES_STAYOPEN
| RES_USEVC
;
812 _res
.options
&= ~(RES_STAYOPEN
| RES_USEVC
);