2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
7 * Copyright (c) 1985, 1988 Regents of the University of California.
10 * Redistribution and use in source and binary forms are permitted
11 * provided that this notice is preserved and that due credit is given
12 * to the University of California at Berkeley. The name of the University
13 * may not be used to endorse or promote products derived from this
14 * software without specific prior written permission. This software
15 * is provided ``as is'' without express or implied warranty.
19 #pragma ident "%Z%%M% %I% %E% SMI"
21 #include <sys/param.h>
22 #include <sys/socket.h>
23 #include <netinet/in.h>
28 #include <arpa/inet.h>
29 #include <arpa/nameser.h>
34 * When the name service switch calls libresolv, it doesn't want fallback
35 * to /etc/hosts, so we provide a method to turn it off.
37 static int no_hosts_fallback
= 0;
40 __res_set_no_hosts_fallback(void) {
41 no_hosts_fallback
= 1;
45 __res_no_hosts_fallback(void) {
46 return(no_hosts_fallback
);
49 static char *h_addr_ptrs
[MAXADDRS
+ 1];
51 static struct hostent host
;
52 static char *host_aliases
[MAXALIASES
];
53 static char hostbuf
[BUFSIZ
+1];
54 static struct in_addr host_addr
;
55 static char HOSTDB
[] = "/etc/hosts";
56 static FILE *hostf
= NULL
;
57 static char hostaddr
[MAXADDRS
];
58 static char *host_addrs
[2];
59 static int stayopen
= 0;
63 #define MAXPACKET PACKETSZ
65 #define MAXPACKET 1024
70 u_char buf
[MAXPACKET
];
81 static struct hostent
*
82 getanswer(answer
, anslen
, iquery
)
92 int type
, class, buflen
, ancount
, qdcount
;
93 int haveanswer
, getclass
= C_ANY
;
96 eom
= answer
->buf
+ anslen
;
98 * find first satisfactory answer
101 ancount
= ntohs(hp
->ancount
);
102 qdcount
= ntohs(hp
->qdcount
);
104 buflen
= sizeof (hostbuf
);
105 cp
= answer
->buf
+ sizeof (HEADER
);
108 if ((n
= dn_expand((char *)answer
->buf
, eom
,
109 cp
, bp
, buflen
)) < 0) {
110 h_errno
= NO_RECOVERY
;
111 return ((struct hostent
*) NULL
);
119 cp
+= dn_skipname(cp
, eom
) + QFIXEDSZ
;
120 while (--qdcount
> 0)
121 cp
+= dn_skipname(cp
, eom
) + QFIXEDSZ
;
124 h_errno
= HOST_NOT_FOUND
;
127 return ((struct hostent
*) NULL
);
130 host
.h_aliases
= host_aliases
;
132 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
133 host
.h_addr_list
= h_addr_ptrs
;
136 while (--ancount
>= 0 && cp
< eom
&& haveanswer
< MAXADDRS
) {
137 if ((n
= dn_expand((char *)answer
->buf
, eom
,
138 cp
, bp
, buflen
)) < 0)
141 type
= _getshort(cp
);
142 cp
+= sizeof (u_short
);
143 class = _getshort(cp
);
144 cp
+= sizeof (u_short
) + sizeof (u_long
);
146 cp
+= sizeof (u_short
);
147 if (type
== T_CNAME
) {
149 if (ap
>= &host_aliases
[MAXALIASES
-1])
157 if (iquery
&& type
== T_PTR
) {
158 if ((n
= dn_expand((char *)answer
->buf
, eom
,
159 cp
, bp
, buflen
)) < 0) {
167 if (iquery
|| type
!= T_A
) {
169 if (_res
.options
& RES_DEBUG
)
170 printf("unexpected answer type %d, size %d\n",
177 if (n
!= host
.h_length
) {
181 if (class != getclass
) {
188 host
.h_addrtype
= (class == C_IN
) ? AF_INET
: AF_UNSPEC
;
191 bp
+= strlen(bp
) + 1;
195 bp
+= sizeof (align
) - ((u_long
)bp
% sizeof (align
));
197 if (bp
+ n
>= &hostbuf
[sizeof (hostbuf
)]) {
199 if (_res
.options
& RES_DEBUG
)
200 printf("size (%d) too big\n", n
);
205 memcpy((void *)(*hap
++ = bp
), (void *)cp
, n
);
207 bcopy(cp
, *hap
++ = bp
, n
);
215 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
218 host
.h_addr
= h_addr_ptrs
[0];
223 return ((struct hostent
*) NULL
);
228 res_gethostbyname(name
)
234 struct hostent
*hp
, *gethostdomain();
235 static struct hostent
*_gethtbyname();
238 * disallow names consisting only of digits/dots, unless
241 if (isdigit(name
[0]))
242 for (cp
= name
; /*EMPTY*/; ++cp
) {
246 h_errno
= HOST_NOT_FOUND
;
247 return ((struct hostent
*) NULL
);
249 if (!isdigit(*cp
) && *cp
!= '.')
253 if ((n
= res_search(name
, C_IN
, T_A
, buf
.buf
, sizeof (buf
))) < 0) {
255 if (_res
.options
& RES_DEBUG
)
256 printf("res_search failed\n");
258 if (errno
== ECONNREFUSED
)
259 return (_gethtbyname(name
));
261 return ((struct hostent
*) NULL
);
263 return (getanswer(&buf
, n
, 0));
266 static struct hostent
*
267 _getrhbyaddr(addr
, len
, type
)
273 register struct hostent
*hp
;
275 static struct hostent
*_gethtbyaddr();
278 return ((struct hostent
*) NULL
);
279 (void) sprintf(qbuf
, "%d.%d.%d.%d.in-addr.arpa",
280 ((unsigned)addr
[3] & 0xff),
281 ((unsigned)addr
[2] & 0xff),
282 ((unsigned)addr
[1] & 0xff),
283 ((unsigned)addr
[0] & 0xff));
284 n
= res_query(qbuf
, C_IN
, T_PTR
, (char *)&buf
, sizeof (buf
));
287 if (_res
.options
& RES_DEBUG
)
288 printf("res_query failed\n");
290 if (errno
== ECONNREFUSED
)
291 return (_gethtbyaddr(addr
, len
, type
));
292 return ((struct hostent
*) NULL
);
294 hp
= getanswer(&buf
, n
, 1);
296 return ((struct hostent
*) NULL
);
297 hp
->h_addrtype
= type
;
299 h_addr_ptrs
[0] = (char *)&host_addr
;
300 h_addr_ptrs
[1] = (char *)0;
301 host_addr
= *(struct in_addr
*)addr
;
306 * First we get what the PTR record says, but do an extra call
307 * to gethostbyname() to make sure that someone is not trying to
308 * spoof us. Hopefully this is not done that often, so good
309 * performance is not really an issue.
312 res_gethostbyaddr(addr
, len
, type
)
317 char **a
, hbuf
[MAXHOSTNAMELEN
];
318 struct hostent
*hp
, *hp2
;
320 if ((hp
= _getrhbyaddr(addr
, len
, type
)) == (struct hostent
*)NULL
)
321 return ((struct hostent
*)NULL
);
323 /* hang on to what we got as an answer */
324 (void) strcpy(hbuf
, hp
->h_name
);
326 /* check to make sure by doing a forward query */
327 if ((hp2
= res_gethostbyname(hbuf
)) != (struct hostent
*)NULL
)
328 for (a
= hp2
->h_addr_list
; *a
; a
++)
330 if (memcmp(*a
, addr
, hp2
->h_length
) == 0)
332 if (bcmp(*a
, addr
, hp2
->h_length
) == 0)
337 * we've been spoofed, make sure to log it.
338 * XXX - syslog needs a security priority level.
340 syslog(LOG_NOTICE
, "gethostbyaddr: %s != %s", hbuf
,
341 inet_ntoa(*(struct in_addr
*)addr
));
342 return ((struct hostent
*)NULL
);
348 if (__res_no_hosts_fallback()) return;
351 hostf
= fopen(HOSTDB
, "r");
360 if (__res_no_hosts_fallback()) return;
362 if (hostf
&& !stayopen
) {
363 (void) fclose(hostf
);
368 static struct hostent
*
372 register char *cp
, **q
;
374 if (__res_no_hosts_fallback()) return(NULL
);
376 if (hostf
== NULL
&& (hostf
= fopen(HOSTDB
, "r")) == NULL
)
379 if ((p
= fgets(hostbuf
, BUFSIZ
, hostf
)) == NULL
)
391 /* THIS STUFF IS INTERNET SPECIFIC */
392 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
393 host
.h_addr_list
= host_addrs
;
395 host
.h_addr
= hostaddr
;
396 *((u_long
*)host
.h_addr
) = inet_addr(p
);
397 host
.h_length
= sizeof (u_long
);
398 host
.h_addrtype
= AF_INET
;
399 while (*cp
== ' ' || *cp
== '\t')
402 q
= host
.h_aliases
= host_aliases
;
407 if (*cp
== ' ' || *cp
== '\t') {
411 if (q
< &host_aliases
[MAXALIASES
- 1])
426 register char *mp
, c
;
429 for (mp
= match
; *mp
; mp
++)
437 static struct hostent
*
441 register struct hostent
*p
;
445 while (p
= _gethtent()) {
446 if (strcasecmp(p
->h_name
, name
) == 0)
448 for (cp
= p
->h_aliases
; *cp
!= 0; cp
++)
449 if (strcasecmp(*cp
, name
) == 0)
457 static struct hostent
*
458 _gethtbyaddr(addr
, len
, type
)
462 register struct hostent
*p
;
465 while (p
= _gethtent())
467 if (p
->h_addrtype
== type
&& !memcmp(p
->h_addr
, addr
, len
))
469 if (p
->h_addrtype
== type
&& !bcmp(p
->h_addr
, addr
, len
))