2 * Copyright 2015 Gary Mills
3 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
4 * Use is subject to license terms.
8 * Copyright (c) 1985, 1988 Regents of the University of California.
11 * Redistribution and use in source and binary forms are permitted
12 * provided that this notice is preserved and that due credit is given
13 * to the University of California at Berkeley. The name of the University
14 * may not be used to endorse or promote products derived from this
15 * software without specific prior written permission. This software
16 * is provided ``as is'' without express or implied warranty.
20 #include <sys/param.h>
21 #include <sys/socket.h>
22 #include <netinet/in.h>
28 #include <arpa/inet.h>
29 #include <arpa/nameser.h>
35 * When the name service switch calls libresolv, it doesn't want fallback
36 * to /etc/hosts, so we provide a method to turn it off.
38 static int no_hosts_fallback
= 0;
41 __res_set_no_hosts_fallback(void) {
42 no_hosts_fallback
= 1;
46 __res_no_hosts_fallback(void) {
47 return(no_hosts_fallback
);
50 static char *h_addr_ptrs
[MAXADDRS
+ 1];
52 static struct hostent host
;
53 static char *host_aliases
[MAXALIASES
];
54 static char hostbuf
[BUFSIZ
+1];
55 static struct in_addr host_addr
;
56 static char HOSTDB
[] = "/etc/hosts";
57 static FILE *hostf
= NULL
;
58 static char hostaddr
[MAXADDRS
];
59 static char *host_addrs
[2];
60 static int stayopen
= 0;
64 #define MAXPACKET PACKETSZ
66 #define MAXPACKET 1024
71 u_char buf
[MAXPACKET
];
82 static struct hostent
*
83 getanswer(answer
, anslen
, iquery
)
93 int type
, class, buflen
, ancount
, qdcount
;
94 int haveanswer
, getclass
= C_ANY
;
97 eom
= answer
->buf
+ anslen
;
99 * find first satisfactory answer
102 ancount
= ntohs(hp
->ancount
);
103 qdcount
= ntohs(hp
->qdcount
);
105 buflen
= sizeof (hostbuf
);
106 cp
= answer
->buf
+ sizeof (HEADER
);
109 if ((n
= dn_expand(answer
->buf
, eom
,
110 cp
, (u_char
*)bp
, buflen
)) < 0) {
111 h_errno
= NO_RECOVERY
;
112 return ((struct hostent
*) NULL
);
120 cp
+= dn_skipname(cp
, eom
) + QFIXEDSZ
;
121 while (--qdcount
> 0)
122 cp
+= dn_skipname(cp
, eom
) + QFIXEDSZ
;
125 h_errno
= HOST_NOT_FOUND
;
128 return ((struct hostent
*) NULL
);
131 host
.h_aliases
= host_aliases
;
133 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
134 host
.h_addr_list
= h_addr_ptrs
;
137 while (--ancount
>= 0 && cp
< eom
&& haveanswer
< MAXADDRS
) {
138 if ((n
= dn_expand(answer
->buf
, eom
,
139 cp
, (u_char
*)bp
, buflen
)) < 0)
142 type
= _getshort(cp
);
143 cp
+= sizeof (u_short
);
144 class = _getshort(cp
);
145 cp
+= sizeof (u_short
) + sizeof (u_long
);
147 cp
+= sizeof (u_short
);
148 if (type
== T_CNAME
) {
150 if (ap
>= &host_aliases
[MAXALIASES
-1])
158 if (iquery
&& type
== T_PTR
) {
159 if ((n
= dn_expand(answer
->buf
, eom
,
160 cp
, (u_char
*)bp
, buflen
)) < 0) {
168 if (iquery
|| type
!= T_A
) {
170 if (_res
.options
& RES_DEBUG
)
171 printf("unexpected answer type %d, size %d\n",
178 if (n
!= host
.h_length
) {
182 if (class != getclass
) {
189 host
.h_addrtype
= (class == C_IN
) ? AF_INET
: AF_UNSPEC
;
192 bp
+= strlen(bp
) + 1;
196 bp
+= sizeof (align
) - ((u_long
)bp
% sizeof (align
));
198 if (bp
+ n
>= &hostbuf
[sizeof (hostbuf
)]) {
200 if (_res
.options
& RES_DEBUG
)
201 printf("size (%d) too big\n", n
);
206 memcpy((void *)(*hap
++ = bp
), (void *)cp
, n
);
208 bcopy(cp
, *hap
++ = bp
, n
);
216 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
219 host
.h_addr
= h_addr_ptrs
[0];
224 return ((struct hostent
*) NULL
);
228 static struct hostent
*_gethtbyname();
231 res_gethostbyname(name
)
239 * disallow names consisting only of digits/dots, unless
242 if (isdigit(name
[0]))
243 for (cp
= name
; /*EMPTY*/; ++cp
) {
247 h_errno
= HOST_NOT_FOUND
;
248 return ((struct hostent
*) NULL
);
250 if (!isdigit(*cp
) && *cp
!= '.')
254 if ((n
= res_search(name
, C_IN
, T_A
, buf
.buf
, sizeof (buf
))) < 0) {
256 if (_res
.options
& RES_DEBUG
)
257 printf("res_search failed\n");
259 if (errno
== ECONNREFUSED
)
260 return (_gethtbyname(name
));
262 return ((struct hostent
*) NULL
);
264 return (getanswer(&buf
, n
, 0));
267 static struct hostent
*_gethtbyaddr();
269 static struct hostent
*
270 _getrhbyaddr(addr
, len
, type
)
276 register struct hostent
*hp
;
280 return ((struct hostent
*) NULL
);
281 (void) sprintf(qbuf
, "%d.%d.%d.%d.in-addr.arpa",
282 ((unsigned)addr
[3] & 0xff),
283 ((unsigned)addr
[2] & 0xff),
284 ((unsigned)addr
[1] & 0xff),
285 ((unsigned)addr
[0] & 0xff));
286 n
= res_query(qbuf
, C_IN
, T_PTR
, (u_char
*)&buf
, sizeof (buf
));
289 if (_res
.options
& RES_DEBUG
)
290 printf("res_query failed\n");
292 if (errno
== ECONNREFUSED
)
293 return (_gethtbyaddr(addr
, len
, type
));
294 return ((struct hostent
*) NULL
);
296 hp
= getanswer(&buf
, n
, 1);
298 return ((struct hostent
*) NULL
);
299 hp
->h_addrtype
= type
;
301 h_addr_ptrs
[0] = (char *)&host_addr
;
302 h_addr_ptrs
[1] = (char *)0;
303 host_addr
= *(struct in_addr
*)addr
;
308 * First we get what the PTR record says, but do an extra call
309 * to gethostbyname() to make sure that someone is not trying to
310 * spoof us. Hopefully this is not done that often, so good
311 * performance is not really an issue.
314 res_gethostbyaddr(addr
, len
, type
)
319 char **a
, hbuf
[MAXHOSTNAMELEN
];
320 struct hostent
*hp
, *hp2
;
322 if ((hp
= _getrhbyaddr(addr
, len
, type
)) == (struct hostent
*)NULL
)
323 return ((struct hostent
*)NULL
);
325 /* hang on to what we got as an answer */
326 (void) strcpy(hbuf
, hp
->h_name
);
328 /* check to make sure by doing a forward query */
329 if ((hp2
= res_gethostbyname(hbuf
)) != (struct hostent
*)NULL
)
330 for (a
= hp2
->h_addr_list
; *a
; a
++)
332 if (memcmp(*a
, addr
, hp2
->h_length
) == 0)
334 if (bcmp(*a
, addr
, hp2
->h_length
) == 0)
339 * we've been spoofed, make sure to log it.
340 * XXX - syslog needs a security priority level.
342 syslog(LOG_NOTICE
, "gethostbyaddr: %s != %s", hbuf
,
343 inet_ntoa(*(struct in_addr
*)addr
));
344 return ((struct hostent
*)NULL
);
350 if (__res_no_hosts_fallback()) return;
353 hostf
= fopen(HOSTDB
, "r");
362 if (__res_no_hosts_fallback()) return;
364 if (hostf
&& !stayopen
) {
365 (void) fclose(hostf
);
370 static struct hostent
*
374 register char *cp
, **q
;
376 if (__res_no_hosts_fallback()) return(NULL
);
378 if (hostf
== NULL
&& (hostf
= fopen(HOSTDB
, "r")) == NULL
)
381 if ((p
= fgets(hostbuf
, BUFSIZ
, hostf
)) == NULL
)
393 /* THIS STUFF IS INTERNET SPECIFIC */
394 #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
395 host
.h_addr_list
= host_addrs
;
397 host
.h_addr
= hostaddr
;
398 *((u_long
*)host
.h_addr
) = inet_addr(p
);
399 host
.h_length
= sizeof (u_long
);
400 host
.h_addrtype
= AF_INET
;
401 while (*cp
== ' ' || *cp
== '\t')
404 q
= host
.h_aliases
= host_aliases
;
409 if (*cp
== ' ' || *cp
== '\t') {
413 if (q
< &host_aliases
[MAXALIASES
- 1])
428 register char *mp
, c
;
431 for (mp
= match
; *mp
; mp
++)
439 static struct hostent
*
443 register struct hostent
*p
;
447 while (p
= _gethtent()) {
448 if (strcasecmp(p
->h_name
, name
) == 0)
450 for (cp
= p
->h_aliases
; *cp
!= 0; cp
++)
451 if (strcasecmp(*cp
, name
) == 0)
459 static struct hostent
*
460 _gethtbyaddr(addr
, len
, type
)
464 register struct hostent
*p
;
467 while (p
= _gethtent())
469 if (p
->h_addrtype
== type
&& !memcmp(p
->h_addr
, addr
, len
))
471 if (p
->h_addrtype
== type
&& !bcmp(p
->h_addr
, addr
, len
))