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/param.h>
62 #include <sys/socket.h>
63 #include <netinet/in.h>
64 #include <arpa/inet.h>
65 #include <arpa/nameser.h>
78 #define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
80 #if defined(BSD) && (BSD >= 199103)
83 # include "../conf/portability.h"
85 #if defined(USE_OPTIONS_H)
86 # include <../conf/options.h>
92 static const char AskedForGot
[] =
93 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
95 static char *h_addr_ptrs
[MAXADDRS
+ 1];
97 static struct hostent host
;
98 static char *host_aliases
[MAXALIASES
];
99 static char hostbuf
[8*1024];
100 static struct in_addr host_addr
;
101 static FILE *hostf
= NULL
;
102 static int stayopen
= 0;
105 static void addrsort
__P((char **, int));
109 #define MAXPACKET PACKETSZ
111 #define MAXPACKET 1024
116 u_char buf
[MAXPACKET
];
132 if (_res
.options
& RES_DEBUG
) {
140 # define dprintf(msg, num) /*nada*/
143 static struct hostent
*
144 getanswer(answer
, anslen
, qname
, qclass
, qtype
)
145 const querybuf
*answer
;
150 register const HEADER
*hp
;
151 register const u_char
*cp
;
154 char *bp
, **ap
, **hap
;
155 int type
, class, buflen
, ancount
, qdcount
;
156 int haveanswer
, had_error
;
158 char tbuf
[MAXDNAME
+1];
161 eom
= answer
->buf
+ anslen
;
163 * find first satisfactory answer
166 ancount
= ntohs(hp
->ancount
);
167 qdcount
= ntohs(hp
->qdcount
);
169 buflen
= sizeof hostbuf
;
170 cp
= answer
->buf
+ HFIXEDSZ
;
172 h_errno
= NO_RECOVERY
;
175 if ((n
= dn_expand(answer
->buf
, eom
, cp
, bp
, buflen
)) < 0) {
176 h_errno
= NO_RECOVERY
;
181 /* res_send() has already verified that the query name is the
182 * same as the one we sent; this just gets the expanded name
183 * (i.e., with the succeeding search-domain tacked on).
185 n
= strlen(bp
) + 1; /* for the \0 */
189 /* The qname can be abbreviated, but h_name is now absolute. */
194 host
.h_aliases
= host_aliases
;
197 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
198 host
.h_addr_list
= h_addr_ptrs
;
202 while (ancount
-- > 0 && cp
< eom
&& !had_error
) {
203 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, buflen
);
209 type
= _getshort(cp
);
210 cp
+= INT16SZ
; /* type */
211 class = _getshort(cp
);
212 cp
+= INT16SZ
+ INT32SZ
; /* class, TTL */
214 cp
+= INT16SZ
; /* len */
215 if (class != qclass
) {
216 /* XXX - debug? syslog? */
218 continue; /* XXX - had_error++ ? */
220 if (qtype
== T_A
&& type
== T_CNAME
) {
221 if (ap
>= &host_aliases
[MAXALIASES
-1])
223 n
= dn_expand(answer
->buf
, eom
, cp
, tbuf
, sizeof tbuf
);
229 if (host
.h_name
&& strcasecmp(host
.h_name
, bp
) != 0) {
230 syslog(LOG_NOTICE
|LOG_AUTH
,
231 "gethostby*.getanswer: asked for \"%s\", got CNAME for \"%s\"",
233 continue; /* XXX - had_error++ ? */
237 n
= strlen(bp
) + 1; /* for the \0 */
240 /* Get canonical name. */
241 n
= strlen(tbuf
) + 1; /* for the \0 */
253 syslog(LOG_NOTICE
|LOG_AUTH
,
254 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
255 qname
, p_class(qclass
), p_type(qtype
),
258 continue; /* XXX - had_error++ ? */
262 if (strcasecmp(qname
, bp
) != 0) {
263 syslog(LOG_NOTICE
|LOG_AUTH
,
264 AskedForGot
, qname
, bp
);
266 continue; /* XXX - had_error++ ? */
268 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, buflen
);
273 #if MULTI_PTRS_ARE_ALIASES
277 else if (ap
< &host_aliases
[MAXALIASES
-1])
282 n
= strlen(bp
) + 1; /* for the \0 */
289 h_errno
= NETDB_SUCCESS
;
293 if (strcasecmp(host
.h_name
, bp
) != 0) {
294 syslog(LOG_NOTICE
|LOG_AUTH
,
295 AskedForGot
, host
.h_name
, bp
);
297 continue; /* XXX - had_error++ ? */
300 if (n
!= host
.h_length
) {
308 host
.h_addrtype
= (class == C_IN
)
312 nn
= strlen(bp
) + 1; /* for the \0 */
317 bp
+= sizeof(align
) - ((u_long
)bp
% sizeof(align
));
319 if (bp
+ n
>= &hostbuf
[sizeof hostbuf
]) {
320 dprintf("size (%d) too big\n", n
);
324 if (hap
>= &h_addr_ptrs
[MAXADDRS
-1]) {
326 dprintf("Too many addresses (%d)\n",
331 bcopy(cp
, *hap
++ = bp
, n
);
336 dprintf("Impossible condition (type=%d)\n", type
);
337 h_errno
= NO_RECOVERY
;
346 # if defined(RESOLVSORT)
348 * Note: we sort even if host can take only one address
349 * in its return structures - should give it the "best"
350 * address in that case, not some random one
352 if (_res
.nsort
&& haveanswer
> 1 &&
353 qclass
== C_IN
&& qtype
== T_A
)
354 addrsort(h_addr_ptrs
, haveanswer
);
355 # endif /*RESOLVSORT*/
356 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
359 host
.h_addr
= h_addr_ptrs
[0];
362 n
= strlen(qname
) + 1; /* for the \0 */
366 h_errno
= NETDB_SUCCESS
;
379 register const char *cp
;
381 extern struct hostent
*_gethtbyname();
384 * if there aren't any dots, it could be a user-level alias.
385 * this is also done in res_query() since we are not the only
386 * function that looks up host names.
388 if (!strchr(name
, '.') && (cp
= __hostalias(name
)))
392 * disallow names consisting only of digits/dots, unless
395 if (isdigit(name
[0]))
396 for (cp
= name
;; ++cp
) {
401 * All-numeric, no dot at the end.
402 * Fake up a hostent as if we'd actually
405 if (!inet_aton(name
, &host_addr
)) {
406 h_errno
= HOST_NOT_FOUND
;
409 host
.h_name
= (char *)name
;
410 host
.h_aliases
= host_aliases
;
411 host_aliases
[0] = NULL
;
412 host
.h_addrtype
= AF_INET
;
413 host
.h_length
= INT32SZ
;
414 h_addr_ptrs
[0] = (char *)&host_addr
;
415 h_addr_ptrs
[1] = NULL
;
416 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
417 host
.h_addr_list
= h_addr_ptrs
;
419 host
.h_addr
= h_addr_ptrs
[0];
421 h_errno
= NETDB_SUCCESS
;
424 if (!isdigit(*cp
) && *cp
!= '.')
428 if ((n
= res_search(name
, C_IN
, T_A
, buf
.buf
, sizeof(buf
))) < 0) {
429 dprintf("res_search failed (%d)\n", n
);
430 if (errno
== ECONNREFUSED
)
431 return (_gethtbyname(name
));
434 return (getanswer(&buf
, n
, name
, C_IN
, T_A
));
438 gethostbyaddr(addr
, len
, type
)
444 register struct hostent
*hp
;
445 char qbuf
[MAXDNAME
+1];
447 register struct hostent
*rhp
;
450 char hname2
[MAXDNAME
+1];
451 #endif /*SUNSECURITY*/
452 extern struct hostent
*_gethtbyaddr();
454 if (type
!= AF_INET
) {
455 errno
= EAFNOSUPPORT
;
456 h_errno
= NETDB_INTERNAL
;
459 (void)sprintf(qbuf
, "%u.%u.%u.%u.in-addr.arpa",
460 ((unsigned)addr
[3] & 0xff),
461 ((unsigned)addr
[2] & 0xff),
462 ((unsigned)addr
[1] & 0xff),
463 ((unsigned)addr
[0] & 0xff));
464 n
= res_query(qbuf
, C_IN
, T_PTR
, (u_char
*)buf
.buf
, sizeof buf
.buf
);
466 dprintf("res_query failed (%d)\n", n
);
467 if (errno
== ECONNREFUSED
)
468 return (_gethtbyaddr(addr
, len
, type
));
471 if (!(hp
= getanswer(&buf
, n
, qbuf
, C_IN
, T_PTR
)))
472 return (NULL
); /* h_errno was set by getanswer() */
475 * turn off search as the name should be absolute,
476 * 'localhost' should be matched by defnames
478 strncpy(hname2
, hp
->h_name
, MAXDNAME
);
479 hname2
[MAXDNAME
] = '\0';
480 old_options
= _res
.options
;
481 _res
.options
&= ~RES_DNSRCH
;
482 _res
.options
|= RES_DEFNAMES
;
483 if (!(rhp
= gethostbyname(hp
->h_name
))) {
484 syslog(LOG_NOTICE
|LOG_AUTH
,
485 "gethostbyaddr: No A record for %s (verifying [%s])",
486 hname2
, inet_ntoa(*((struct in_addr
*)addr
)));
487 _res
.options
= old_options
;
488 h_errno
= HOST_NOT_FOUND
;
491 _res
.options
= old_options
;
492 for (haddr
= rhp
->h_addr_list
; *haddr
; haddr
++)
493 if (!memcmp(*haddr
, addr
, INADDRSZ
))
496 syslog(LOG_NOTICE
|LOG_AUTH
,
497 "gethostbyaddr: A record of %s != PTR record [%s]",
498 hname2
, inet_ntoa(*((struct in_addr
*)addr
)));
499 h_errno
= HOST_NOT_FOUND
;
502 #endif /*SUNSECURITY*/
503 hp
->h_addrtype
= type
;
505 h_addr_ptrs
[0] = (char *)&host_addr
;
506 h_addr_ptrs
[1] = NULL
;
507 host_addr
= *(struct in_addr
*)addr
;
508 h_errno
= NETDB_SUCCESS
;
517 hostf
= fopen(_PATH_HOSTS
, "r" );
526 if (hostf
&& !stayopen
) {
527 (void) fclose(hostf
);
536 register char *cp
, **q
;
538 if (!hostf
&& !(hostf
= fopen(_PATH_HOSTS
, "r" ))) {
539 h_errno
= NETDB_INTERNAL
;
543 if (!(p
= fgets(hostbuf
, sizeof hostbuf
, hostf
))) {
544 h_errno
= HOST_NOT_FOUND
;
549 if (!(cp
= strpbrk(p
, "#\n")))
552 if (!(cp
= strpbrk(p
, " \t")))
555 /* THIS STUFF IS INTERNET SPECIFIC */
556 if (!inet_aton(p
, &host_addr
))
558 h_addr_ptrs
[0] = (char *)&host_addr
;
559 h_addr_ptrs
[1] = NULL
;
560 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
561 host
.h_addr_list
= h_addr_ptrs
;
563 host
.h_addr
= h_addr_ptrs
[0];
565 host
.h_length
= INT32SZ
;
566 host
.h_addrtype
= AF_INET
;
567 while (*cp
== ' ' || *cp
== '\t')
570 q
= host
.h_aliases
= host_aliases
;
571 if (cp
= strpbrk(cp
, " \t"))
574 if (*cp
== ' ' || *cp
== '\t') {
578 if (q
< &host_aliases
[MAXALIASES
- 1])
580 if (cp
= strpbrk(cp
, " \t"))
584 h_errno
= NETDB_SUCCESS
;
592 register struct hostent
*p
;
596 while (p
= _gethtent()) {
597 if (strcasecmp(p
->h_name
, name
) == 0)
599 for (cp
= p
->h_aliases
; *cp
!= 0; cp
++)
600 if (strcasecmp(*cp
, name
) == 0)
609 _gethtbyaddr(addr
, len
, type
)
613 register struct hostent
*p
;
616 while (p
= _gethtent())
617 if (p
->h_addrtype
== type
&& !bcmp(p
->h_addr
, addr
, len
))
631 short aval
[MAXADDRS
];
635 for (i
= 0; i
< num
; i
++, p
++) {
636 for (j
= 0 ; (unsigned)j
< _res
.nsort
; j
++)
637 if (_res
.sort_list
[j
].addr
.s_addr
==
638 (((struct in_addr
*)(*p
))->s_addr
& _res
.sort_list
[j
].mask
))
641 if (needsort
== 0 && i
> 0 && j
< aval
[i
-1])
647 while (needsort
< num
) {
648 for (j
= needsort
- 1; j
>= 0; j
--) {
649 if (aval
[j
] > aval
[j
+1]) {
668 #if defined(BSD43_BSD43_NFS) || defined(sun)
669 /* some libc's out there are bound internally to these names (UMIPS) */
671 ht_sethostent(stayopen
)
684 ht_gethostbyname(name
)
687 return (_gethtbyname(name
));
691 ht_gethostbyaddr(addr
, len
, type
)
695 return (_gethtbyaddr(addr
, len
, type
));
701 return (_gethtent());
711 dn_skipname(comp_dn
, eom
)
712 const u_char
*comp_dn
, *eom
;
714 return (__dn_skipname(comp_dn
, eom
));
716 #endif /*old-style libc with yp junk in it*/
719 /* more icky libc packaging in ultrix */
721 local_hostname_length(hostname
)
722 const char *hostname
;
724 int len_host
, len_domain
;
728 len_host
= strlen(hostname
);
729 len_domain
= strlen(_res
.defdname
);
730 if (len_host
> len_domain
&&
731 !strcasecmp(hostname
+ len_host
- len_domain
, _res
.defdname
) &&
732 hostname
[len_host
- len_domain
- 1] == '.')
733 return (len_host
- len_domain
- 1);