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
37 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
38 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
40 * Permission to use, copy, modify, and distribute this software for any
41 * purpose with or without fee is hereby granted, provided that the above
42 * copyright notice and this permission notice appear in all copies.
44 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
45 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
46 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
47 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
48 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
49 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
50 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
53 /* from gethostnamadr.c 8.1 (Berkeley) 6/4/93 */
54 /* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */
56 #if defined(LIBC_SCCS) && !defined(lint)
57 static const char rcsid
[] = "Id: lcl_ho.c,v 1.5 2006/03/09 23:57:56 marka Exp";
58 #endif /* LIBC_SCCS and not lint */
62 #include "port_before.h"
64 #include <sys/types.h>
65 #include <sys/param.h>
66 #include <sys/socket.h>
68 #include <netinet/in.h>
69 #include <arpa/inet.h>
70 #include <arpa/nameser.h>
82 #include <isc/memcluster.h>
84 #include "port_after.h"
91 # define SPRINTF(x) strlen(sprintf/**/x)
93 # define SPRINTF(x) sprintf x
100 #define Max(a,b) ((a) > (b) ? (a) : (b))
103 #define MAXPACKET PACKETSZ
105 #define MAXPACKET 1024
111 char * h_addr_ptrs
[MAXADDRS
+ 1];
112 char * host_aliases
[MAXALIASES
];
113 char hostbuf
[8*1024];
114 u_char host_addr
[16]; /*%< IPv4 or IPv6 */
115 struct __res_state
*res
;
116 void (*free_res
)(void *);
124 static const u_char mapped
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
125 static const u_char tunnelled
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
129 static void ho_close(struct irs_ho
*this);
130 static struct hostent
* ho_byname(struct irs_ho
*this, const char *name
);
131 static struct hostent
* ho_byname2(struct irs_ho
*this, const char *name
,
133 static struct hostent
* ho_byaddr(struct irs_ho
*this, const void *addr
,
135 static struct hostent
* ho_next(struct irs_ho
*this);
136 static void ho_rewind(struct irs_ho
*this);
137 static void ho_minimize(struct irs_ho
*this);
138 static struct __res_state
* ho_res_get(struct irs_ho
*this);
139 static void ho_res_set(struct irs_ho
*this,
140 struct __res_state
*res
,
141 void (*free_res
)(void *));
142 static struct addrinfo
* ho_addrinfo(struct irs_ho
*this, const char *name
,
143 const struct addrinfo
*pai
);
145 static size_t ns_namelen(const char *);
146 static int init(struct irs_ho
*this);
157 irs_lcl_ho(struct irs_acc
*this) {
163 if (!(pvt
= memget(sizeof *pvt
))) {
167 memset(pvt
, 0, sizeof *pvt
);
168 if (!(ho
= memget(sizeof *ho
))) {
169 memput(pvt
, sizeof *pvt
);
173 memset(ho
, 0x5e, sizeof *ho
);
175 ho
->close
= ho_close
;
176 ho
->byname
= ho_byname
;
177 ho
->byname2
= ho_byname2
;
178 ho
->byaddr
= ho_byaddr
;
180 ho
->rewind
= ho_rewind
;
181 ho
->minimize
= ho_minimize
;
182 ho
->res_get
= ho_res_get
;
183 ho
->res_set
= ho_res_set
;
184 ho
->addrinfo
= ho_addrinfo
;
191 ho_close(struct irs_ho
*this) {
192 struct pvt
*pvt
= (struct pvt
*)this->private;
196 (void) fclose(pvt
->fp
);
197 if (pvt
->res
&& pvt
->free_res
)
198 (*pvt
->free_res
)(pvt
->res
);
199 memput(pvt
, sizeof *pvt
);
200 memput(this, sizeof *this);
203 static struct hostent
*
204 ho_byname(struct irs_ho
*this, const char *name
) {
205 struct pvt
*pvt
= (struct pvt
*)this->private;
208 if (init(this) == -1)
211 if (pvt
->res
->options
& RES_USE_INET6
) {
212 hp
= ho_byname2(this, name
, AF_INET6
);
216 return (ho_byname2(this, name
, AF_INET
));
219 static struct hostent
*
220 ho_byname2(struct irs_ho
*this, const char *name
, int af
) {
221 struct pvt
*pvt
= (struct pvt
*)this->private;
226 if (init(this) == -1)
230 n
= ns_namelen(name
);
231 while ((hp
= ho_next(this)) != NULL
) {
234 if (hp
->h_addrtype
!= af
)
236 nn
= ns_namelen(hp
->h_name
);
237 if (strncasecmp(hp
->h_name
, name
, Max(n
, nn
)) == 0)
239 for (hap
= hp
->h_aliases
; *hap
; hap
++) {
240 nn
= ns_namelen(*hap
);
241 if (strncasecmp(*hap
, name
, Max(n
, nn
)) == 0)
247 RES_SET_H_ERRNO(pvt
->res
, HOST_NOT_FOUND
);
250 RES_SET_H_ERRNO(pvt
->res
, NETDB_SUCCESS
);
254 static struct hostent
*
255 ho_byaddr(struct irs_ho
*this, const void *addr
, int len
, int af
) {
256 struct pvt
*pvt
= (struct pvt
*)this->private;
257 const u_char
*uaddr
= addr
;
261 if (init(this) == -1)
264 if (af
== AF_INET6
&& len
== IN6ADDRSZ
&&
265 (!memcmp(uaddr
, mapped
, sizeof mapped
) ||
266 !memcmp(uaddr
, tunnelled
, sizeof tunnelled
))) {
268 addr
= (const u_char
*)addr
+ sizeof mapped
;
269 uaddr
+= sizeof mapped
;
281 errno
= EAFNOSUPPORT
;
282 RES_SET_H_ERRNO(pvt
->res
, NETDB_INTERNAL
);
287 RES_SET_H_ERRNO(pvt
->res
, NETDB_INTERNAL
);
295 while ((hp
= ho_next(this)) != NULL
) {
298 for (hap
= hp
->h_addr_list
; *hap
; hap
++) {
299 const u_char
*taddr
= (const u_char
*)*hap
;
300 int taf
= hp
->h_addrtype
;
301 int tlen
= hp
->h_length
;
303 if (taf
== AF_INET6
&& tlen
== IN6ADDRSZ
&&
304 (!memcmp(taddr
, mapped
, sizeof mapped
) ||
305 !memcmp(taddr
, tunnelled
, sizeof tunnelled
))) {
307 taddr
+= sizeof mapped
;
311 if (taf
== af
&& tlen
== len
&&
312 !memcmp(taddr
, uaddr
, tlen
))
318 RES_SET_H_ERRNO(pvt
->res
, HOST_NOT_FOUND
);
321 RES_SET_H_ERRNO(pvt
->res
, NETDB_SUCCESS
);
325 static struct hostent
*
326 ho_next(struct irs_ho
*this) {
327 struct pvt
*pvt
= (struct pvt
*)this->private;
329 char *bufp
, *ndbuf
, *dbuf
= NULL
;
330 int c
, af
, len
, bufsiz
, offset
;
332 if (init(this) == -1)
338 RES_SET_H_ERRNO(pvt
->res
, NETDB_INTERNAL
);
342 bufsiz
= sizeof pvt
->hostbuf
;
345 if (!(p
= fgets(bufp
+ offset
, bufsiz
- offset
, pvt
->fp
))) {
346 RES_SET_H_ERRNO(pvt
->res
, HOST_NOT_FOUND
);
351 if (!strchr(p
, '\n') && !feof(pvt
->fp
)) {
353 /* allocate space for longer line */
355 if ((ndbuf
= malloc(bufsiz
+ GROWBUF
)) != NULL
)
358 ndbuf
= realloc(dbuf
, bufsiz
+ GROWBUF
);
363 offset
= strlen(dbuf
);
365 /* allocation failed; skip this long line */
366 while ((c
= getc(pvt
->fp
)) != EOF
)
380 if ((cp
= strpbrk(p
, "#\n")) != NULL
)
382 if (!(cp
= strpbrk(p
, " \t")))
385 if (inet_pton(AF_INET6
, p
, pvt
->host_addr
) > 0) {
388 } else if (inet_aton(p
, (struct in_addr
*)pvt
->host_addr
) > 0) {
389 if (pvt
->res
->options
& RES_USE_INET6
) {
390 map_v4v6_address((char*)pvt
->host_addr
,
391 (char*)pvt
->host_addr
);
401 pvt
->h_addr_ptrs
[0] = (char *)pvt
->host_addr
;
402 pvt
->h_addr_ptrs
[1] = NULL
;
403 pvt
->host
.h_addr_list
= pvt
->h_addr_ptrs
;
404 pvt
->host
.h_length
= len
;
405 pvt
->host
.h_addrtype
= af
;
406 while (*cp
== ' ' || *cp
== '\t')
408 pvt
->host
.h_name
= cp
;
409 q
= pvt
->host
.h_aliases
= pvt
->host_aliases
;
410 if ((cp
= strpbrk(cp
, " \t")) != NULL
)
413 if (*cp
== ' ' || *cp
== '\t') {
417 if (q
< &pvt
->host_aliases
[MAXALIASES
- 1])
419 if ((cp
= strpbrk(cp
, " \t")) != NULL
)
425 RES_SET_H_ERRNO(pvt
->res
, NETDB_SUCCESS
);
430 ho_rewind(struct irs_ho
*this) {
431 struct pvt
*pvt
= (struct pvt
*)this->private;
434 if (fseek(pvt
->fp
, 0L, SEEK_SET
) == 0)
436 (void)fclose(pvt
->fp
);
438 if (!(pvt
->fp
= fopen(_PATH_HOSTS
, "r")))
440 if (fcntl(fileno(pvt
->fp
), F_SETFD
, 1) < 0) {
441 (void)fclose(pvt
->fp
);
447 ho_minimize(struct irs_ho
*this) {
448 struct pvt
*pvt
= (struct pvt
*)this->private;
450 if (pvt
->fp
!= NULL
) {
451 (void)fclose(pvt
->fp
);
455 res_nclose(pvt
->res
);
458 static struct __res_state
*
459 ho_res_get(struct irs_ho
*this) {
460 struct pvt
*pvt
= (struct pvt
*)this->private;
463 struct __res_state
*res
;
464 res
= (struct __res_state
*)malloc(sizeof *res
);
469 memset(res
, 0, sizeof *res
);
470 ho_res_set(this, res
, free
);
477 ho_res_set(struct irs_ho
*this, struct __res_state
*res
,
478 void (*free_res
)(void *)) {
479 struct pvt
*pvt
= (struct pvt
*)this->private;
481 if (pvt
->res
&& pvt
->free_res
) {
482 res_nclose(pvt
->res
);
483 (*pvt
->free_res
)(pvt
->res
);
487 pvt
->free_res
= free_res
;
490 struct lcl_res_target
{
491 struct lcl_res_target
*next
;
496 extern struct addrinfo
*hostent2addrinfo
__P((struct hostent
*,
497 const struct addrinfo
*pai
));
499 static struct addrinfo
*
500 ho_addrinfo(struct irs_ho
*this, const char *name
, const struct addrinfo
*pai
)
502 struct pvt
*pvt
= (struct pvt
*)this->private;
504 struct lcl_res_target q
, q2
, *p
;
505 struct addrinfo sentinel
, *cur
;
507 memset(&q
, 0, sizeof(q2
));
508 memset(&q2
, 0, sizeof(q2
));
509 memset(&sentinel
, 0, sizeof(sentinel
));
512 switch(pai
->ai_family
) {
513 case AF_UNSPEC
: /*%< INET6 then INET4 */
525 RES_SET_H_ERRNO(pvt
->res
, NO_RECOVERY
); /*%< ??? */
529 for (p
= &q
; p
; p
= p
->next
) {
532 hp
= (*this->byname2
)(this, name
, p
->family
);
534 /* byname2 should've set an appropriate error */
537 if ((hp
->h_name
== NULL
) || (hp
->h_name
[0] == 0) ||
538 (hp
->h_addr_list
[0] == NULL
)) {
539 RES_SET_H_ERRNO(pvt
->res
, NO_RECOVERY
);
543 ai
= hostent2addrinfo(hp
, pai
);
551 if (sentinel
.ai_next
== NULL
)
552 RES_SET_H_ERRNO(pvt
->res
, HOST_NOT_FOUND
);
554 return(sentinel
.ai_next
);
560 ns_namelen(const char *s
) {
563 for (i
= strlen(s
); i
> 0 && s
[i
-1] == '.'; i
--)
569 init(struct irs_ho
*this) {
570 struct pvt
*pvt
= (struct pvt
*)this->private;
572 if (!pvt
->res
&& !ho_res_get(this))
574 if (((pvt
->res
->options
& RES_INIT
) == 0U) &&
575 res_ninit(pvt
->res
) == -1)