]>
git.saurik.com Git - apple/libinfo.git/blob - dns.subproj/gethnamaddr.c
250a3c4cbfe65c91fa5c3c5baf7ae903a4a6c656
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
25 * ++Copyright++ 1985, 1988, 1993
27 * Copyright (c) 1985, 1988, 1993
28 * The Regents of the University of California. All rights reserved.
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed by the University of
41 * California, Berkeley and its contributors.
42 * 4. Neither the name of the University nor the names of its contributors
43 * may be used to endorse or promote products derived from this software
44 * without specific prior written permission.
46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
60 * Permission to use, copy, modify, and distribute this software for any
61 * purpose with or without fee is hereby granted, provided that the above
62 * copyright notice and this permission notice appear in all copies, and that
63 * the name of Digital Equipment Corporation not be used in advertising or
64 * publicity pertaining to distribution of the document or software without
65 * specific, written prior permission.
67 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
68 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
69 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
70 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
71 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
72 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
73 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
79 #if defined(LIBC_SCCS) && !defined(lint)
80 static char sccsid
[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
81 static char rcsid
[] = "$Id: gethnamaddr.c,v 1.6 2002/06/13 01:04:37 majka Exp $";
82 #endif /* LIBC_SCCS and not lint */
84 #include <sys/param.h>
85 #include <sys/socket.h>
86 #include <netinet/in.h>
87 #include <arpa/inet.h>
88 #include <arpa/nameser.h>
102 #define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
104 #if defined(BSD) && (BSD >= 199103)
107 # include "portability.h"
109 #if defined(USE_OPTIONS_H)
110 # include "options.h"
113 #define MAXALIASES 35
115 #define MAXHOSTBUF 8*1024
117 static const char AskedForGot
[] =
118 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
120 static char *h_addr_ptrs
[MAXADDRS
+ 1];
121 static struct hostent
*gethostbyname_ipv4
__P((const char *));
123 static struct hostent host
;
124 static char *host_aliases
[MAXALIASES
];
125 static char *hostbuf
= NULL
;
126 static struct in_addr host_addr
;
127 static FILE *hostf
= NULL
;
128 static int stayopen
= 0;
131 static void addrsort
__P((char **, int));
135 #define MAXPACKET PACKETSZ
137 #define MAXPACKET 1024
142 u_char buf
[MAXPACKET
];
152 extern int _lu_running(void);
160 if (_res
.options
& RES_DEBUG
) {
168 # define dprintf(msg, num) /*nada*/
171 static struct hostent
*
172 getanswer(answer
, anslen
, qname
, qclass
, qtype
)
173 const querybuf
*answer
;
178 register const HEADER
*hp
;
179 register const u_char
*cp
;
182 char *bp
, **ap
, **hap
;
183 int type
, class, buflen
, ancount
, qdcount
;
184 int haveanswer
, had_error
;
186 char tbuf
[MAXDNAME
+1];
189 if (hostbuf
== NULL
) {
190 hostbuf
= malloc(MAXHOSTBUF
);
198 eom
= answer
->buf
+ anslen
;
200 * find first satisfactory answer
203 ancount
= ntohs(hp
->ancount
);
204 qdcount
= ntohs(hp
->qdcount
);
206 cp
= answer
->buf
+ HFIXEDSZ
;
208 h_errno
= NO_RECOVERY
;
211 if ((n
= dn_expand(answer
->buf
, eom
, cp
, bp
, buflen
)) < 0) {
212 h_errno
= NO_RECOVERY
;
217 /* res_send() has already verified that the query name is the
218 * same as the one we sent; this just gets the expanded name
219 * (i.e., with the succeeding search-domain tacked on).
221 n
= strlen(bp
) + 1; /* for the \0 */
225 /* The qname can be abbreviated, but h_name is now absolute. */
230 host
.h_aliases
= host_aliases
;
233 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
234 host
.h_addr_list
= h_addr_ptrs
;
238 while (ancount
-- > 0 && cp
< eom
&& !had_error
) {
239 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, buflen
);
245 type
= _getshort(cp
);
246 cp
+= INT16SZ
; /* type */
247 class = _getshort(cp
);
248 cp
+= INT16SZ
+ INT32SZ
; /* class, TTL */
250 cp
+= INT16SZ
; /* len */
251 if (class != qclass
) {
252 /* XXX - debug? syslog? */
254 continue; /* XXX - had_error++ ? */
256 if (qtype
== T_A
&& type
== T_CNAME
) {
257 if (ap
>= &host_aliases
[MAXALIASES
-1])
259 n
= dn_expand(answer
->buf
, eom
, cp
, tbuf
, sizeof tbuf
);
265 if (host
.h_name
&& strcasecmp(host
.h_name
, bp
) != 0) {
266 syslog(LOG_NOTICE
|LOG_AUTH
,
267 "gethostby*.getanswer: asked for \"%s\", got CNAME for \"%s\"",
269 continue; /* XXX - had_error++ ? */
273 n
= strlen(bp
) + 1; /* for the \0 */
276 /* Get canonical name. */
277 n
= strlen(tbuf
) + 1; /* for the \0 */
288 if (qtype
== T_PTR
&& type
== T_CNAME
) {
289 n
= dn_expand(answer
->buf
, eom
, cp
, tbuf
, sizeof tbuf
);
295 /* Get canonical name. */
296 n
= strlen(tbuf
) + 1; /* for the \0 */
308 syslog(LOG_NOTICE
|LOG_AUTH
,
309 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
310 qname
, p_class(qclass
), p_type(qtype
),
313 continue; /* XXX - had_error++ ? */
317 if (strcasecmp(tname
, bp
) != 0) {
318 syslog(LOG_NOTICE
|LOG_AUTH
,
319 AskedForGot
, qname
, bp
);
321 continue; /* XXX - had_error++ ? */
323 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, buflen
);
328 #if MULTI_PTRS_ARE_ALIASES
332 else if (ap
< &host_aliases
[MAXALIASES
-1])
337 n
= strlen(bp
) + 1; /* for the \0 */
344 h_errno
= NETDB_SUCCESS
;
348 if (strcasecmp(host
.h_name
, bp
) != 0) {
349 syslog(LOG_NOTICE
|LOG_AUTH
,
350 AskedForGot
, host
.h_name
, bp
);
352 continue; /* XXX - had_error++ ? */
355 if (n
!= host
.h_length
) {
363 host
.h_addrtype
= (class == C_IN
)
367 nn
= strlen(bp
) + 1; /* for the \0 */
372 bp
+= sizeof(align
) - ((u_long
)bp
% sizeof(align
));
374 if (bp
+ n
>= &hostbuf
[MAXHOSTBUF
]) {
375 dprintf("size (%d) too big\n", n
);
379 if (hap
>= &h_addr_ptrs
[MAXADDRS
-1]) {
381 dprintf("Too many addresses (%d)\n",
386 bcopy(cp
, *hap
++ = bp
, n
);
391 dprintf("Impossible condition (type=%d)\n", type
);
392 h_errno
= NO_RECOVERY
;
401 # if defined(RESOLVSORT)
403 * Note: we sort even if host can take only one address
404 * in its return structures - should give it the "best"
405 * address in that case, not some random one
407 if (_res
.nsort
&& haveanswer
> 1 &&
408 qclass
== C_IN
&& qtype
== T_A
)
409 addrsort(h_addr_ptrs
, haveanswer
);
410 # endif /*RESOLVSORT*/
411 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
414 host
.h_addr
= h_addr_ptrs
[0];
417 n
= strlen(qname
) + 1; /* for the \0 */
421 h_errno
= NETDB_SUCCESS
;
433 #if defined(AF_INET6) && defined(RES_TRY_INET6)
436 if (_res
.options
& RES_TRY_INET6
) {
437 hp
= gethostbyname2(name
, AF_INET6
);
442 return (gethostbyname2(name
, AF_INET
));
446 gethostbyname2(name
, af
)
452 return getipnodebyname(name
, af
, 0, &h_errno
);
456 if (af
== AF_INET
) return gethostbyname_ipv4(name
);
458 errno
= EAFNOSUPPORT
;
459 h_errno
= NETDB_INTERNAL
;
464 static struct hostent
*
465 gethostbyname_ipv4(name
)
469 register const char *cp
;
471 #if !defined(__APPLE__)
472 extern struct hostent
*_gethtbyname();
477 hostbuf
= malloc(MAXHOSTBUF
);
478 if (hostbuf
== NULL
) {
479 h_errno
= NETDB_INTERNAL
;
484 if ((_res
.options
& RES_INIT
) == 0 && res_init() == -1) {
485 h_errno
= NETDB_INTERNAL
;
490 * if there aren't any dots, it could be a user-level alias.
491 * this is also done in res_query() since we are not the only
492 * function that looks up host names.
494 if (!strchr(name
, '.') && (cp
= __hostalias(name
)))
498 * disallow names consisting only of digits/dots, unless
501 if (isdigit(name
[0]))
502 for (cp
= name
;; ++cp
) {
507 * All-numeric, no dot at the end.
508 * Fake up a hostent as if we'd actually
511 if (!inet_aton(name
, &host_addr
)) {
512 h_errno
= HOST_NOT_FOUND
;
515 strncpy(hostbuf
, name
, MAXDNAME
);
516 hostbuf
[MAXDNAME
] = '\0';
517 host
.h_name
= hostbuf
;
518 host
.h_aliases
= host_aliases
;
519 host_aliases
[0] = NULL
;
520 host
.h_addrtype
= AF_INET
;
521 host
.h_length
= INT32SZ
;
522 h_addr_ptrs
[0] = (char *)&host_addr
;
523 h_addr_ptrs
[1] = NULL
;
524 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
525 host
.h_addr_list
= h_addr_ptrs
;
527 host
.h_addr
= h_addr_ptrs
[0];
529 h_errno
= NETDB_SUCCESS
;
532 if (!isdigit(*cp
) && *cp
!= '.')
536 if ((n
= res_search(name
, C_IN
, T_A
, buf
.buf
, sizeof(buf
))) < 0) {
537 dprintf("res_search failed (%d)\n", n
);
538 #if !defined(__APPLE__)
539 if (errno
== ECONNREFUSED
)
540 return (_gethtbyname(name
));
544 return (getanswer(&buf
, n
, name
, C_IN
, T_A
));
548 gethostbyaddr(addr
, len
, type
)
554 register struct hostent
*hp
;
555 char qbuf
[MAXDNAME
+1];
557 register struct hostent
*rhp
;
560 char hname2
[MAXDNAME
+1];
561 #endif /*SUNSECURITY*/
562 #if !defined(__APPLE__)
563 extern struct hostent
*_gethtbyaddr();
566 if ((_res
.options
& RES_INIT
) == 0 && res_init() == -1) {
567 h_errno
= NETDB_INTERNAL
;
570 if (type
!= AF_INET
) {
571 errno
= EAFNOSUPPORT
;
572 h_errno
= NETDB_INTERNAL
;
575 (void)sprintf(qbuf
, "%u.%u.%u.%u.in-addr.arpa",
576 ((unsigned)addr
[3] & 0xff),
577 ((unsigned)addr
[2] & 0xff),
578 ((unsigned)addr
[1] & 0xff),
579 ((unsigned)addr
[0] & 0xff));
580 n
= res_query(qbuf
, C_IN
, T_PTR
, (u_char
*)buf
.buf
, sizeof buf
.buf
);
582 dprintf("res_query failed (%d)\n", n
);
583 #if !defined(__APPLE__)
584 if (errno
== ECONNREFUSED
)
585 return (_gethtbyaddr(addr
, len
, type
));
589 if (!(hp
= getanswer(&buf
, n
, qbuf
, C_IN
, T_PTR
)))
590 return (NULL
); /* h_errno was set by getanswer() */
593 * turn off search as the name should be absolute,
594 * 'localhost' should be matched by defnames
596 strncpy(hname2
, hp
->h_name
, MAXDNAME
);
597 hname2
[MAXDNAME
] = '\0';
598 old_options
= _res
.options
;
599 _res
.options
&= ~RES_DNSRCH
;
600 _res
.options
|= RES_DEFNAMES
;
601 if (!(rhp
= gethostbyname(hname2
))) {
602 syslog(LOG_NOTICE
|LOG_AUTH
,
603 "gethostbyaddr: No A record for %s (verifying [%s])",
604 hname2
, inet_ntoa(*((struct in_addr
*)addr
)));
605 _res
.options
= old_options
;
606 h_errno
= HOST_NOT_FOUND
;
609 _res
.options
= old_options
;
610 for (haddr
= rhp
->h_addr_list
; *haddr
; haddr
++)
611 if (!memcmp(*haddr
, addr
, INADDRSZ
))
614 syslog(LOG_NOTICE
|LOG_AUTH
,
615 "gethostbyaddr: A record of %s != PTR record [%s]",
616 hname2
, inet_ntoa(*((struct in_addr
*)addr
)));
617 h_errno
= HOST_NOT_FOUND
;
620 #endif /*SUNSECURITY*/
621 hp
->h_addrtype
= type
;
623 h_addr_ptrs
[0] = (char *)&host_addr
;
624 h_addr_ptrs
[1] = NULL
;
625 host_addr
= *(struct in_addr
*)addr
;
626 h_errno
= NETDB_SUCCESS
;
635 hostf
= fopen(_PATH_HOSTS
, "r" );
644 if (hostf
&& !stayopen
) {
645 (void) fclose(hostf
);
654 register char *cp
, **q
;
656 if (!hostf
&& !(hostf
= fopen(_PATH_HOSTS
, "r" ))) {
657 h_errno
= NETDB_INTERNAL
;
660 if (hostbuf
== NULL
) {
661 hostbuf
= malloc(MAXHOSTBUF
);
662 if (hostbuf
== NULL
) {
663 h_errno
= NETDB_INTERNAL
;
668 if (!(p
= fgets(hostbuf
, MAXHOSTBUF
, hostf
))) {
669 h_errno
= HOST_NOT_FOUND
;
674 if (!(cp
= strpbrk(p
, "#\n")))
677 if (!(cp
= strpbrk(p
, " \t")))
680 /* THIS STUFF IS INTERNET SPECIFIC */
681 if (!inet_aton(p
, &host_addr
))
683 h_addr_ptrs
[0] = (char *)&host_addr
;
684 h_addr_ptrs
[1] = NULL
;
685 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
686 host
.h_addr_list
= h_addr_ptrs
;
688 host
.h_addr
= h_addr_ptrs
[0];
690 host
.h_length
= INT32SZ
;
691 host
.h_addrtype
= AF_INET
;
692 while (*cp
== ' ' || *cp
== '\t')
695 q
= host
.h_aliases
= host_aliases
;
696 if ((cp
= strpbrk(cp
, " \t")))
699 if (*cp
== ' ' || *cp
== '\t') {
703 if (q
< &host_aliases
[MAXALIASES
- 1])
705 if ((cp
= strpbrk(cp
, " \t")))
709 h_errno
= NETDB_SUCCESS
;
717 register struct hostent
*p
;
721 while ((p
= _gethtent())) {
722 if (strcasecmp(p
->h_name
, name
) == 0)
724 for (cp
= p
->h_aliases
; *cp
!= 0; cp
++)
725 if (strcasecmp(*cp
, name
) == 0)
734 _gethtbyaddr(addr
, len
, type
)
738 register struct hostent
*p
;
741 while ((p
= _gethtent()))
742 if (p
->h_addrtype
== type
&& !bcmp(p
->h_addr
, addr
, len
))
756 short aval
[MAXADDRS
];
760 for (i
= 0; i
< num
; i
++, p
++) {
761 for (j
= 0 ; (unsigned)j
< _res
.nsort
; j
++)
762 if (_res
.sort_list
[j
].addr
.s_addr
==
763 (((struct in_addr
*)(*p
))->s_addr
& _res
.sort_list
[j
].mask
))
766 if (needsort
== 0 && i
> 0 && j
< aval
[i
-1])
772 while (needsort
< num
) {
773 for (j
= needsort
- 1; j
>= 0; j
--) {
774 if (aval
[j
] > aval
[j
+1]) {
793 #if defined(BSD43_BSD43_NFS) || defined(sun)
794 /* some libc's out there are bound internally to these names (UMIPS) */
796 ht_sethostent(stayopen
)
809 ht_gethostbyname(name
)
812 return (_gethtbyname(name
));
816 ht_gethostbyaddr(addr
, len
, type
)
820 return (_gethtbyaddr(addr
, len
, type
));
826 return (_gethtent());
836 dn_skipname(comp_dn
, eom
)
837 const u_char
*comp_dn
, *eom
;
839 return (__dn_skipname(comp_dn
, eom
));
841 #endif /*old-style libc with yp junk in it*/