2 * Copyright (c) 1985, 1988, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
36 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
38 * Permission to use, copy, modify, and distribute this software for any
39 * purpose with or without fee is hereby granted, provided that the above
40 * copyright notice and this permission notice appear in all copies.
42 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
43 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
44 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
45 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
46 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
47 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
48 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
51 /* from gethostnamadr.c 8.1 (Berkeley) 6/4/93 */
52 /* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */
54 #if defined(LIBC_SCCS) && !defined(lint)
55 static const char rcsid
[] = "$Id: lcl_ho.c,v 1.1.2.2 2004/03/17 00:40:13 marka Exp $";
56 #endif /* LIBC_SCCS and not lint */
60 #include "port_before.h"
62 #include <sys/types.h>
63 #include <sys/param.h>
64 #include <sys/socket.h>
66 #include <netinet/in.h>
67 #include <arpa/inet.h>
68 #include <arpa/nameser.h>
80 #include <isc/memcluster.h>
82 #include "port_after.h"
89 # define SPRINTF(x) strlen(sprintf/**/x)
91 # define SPRINTF(x) sprintf x
98 #define Max(a,b) ((a) > (b) ? (a) : (b))
101 #define MAXPACKET PACKETSZ
103 #define MAXPACKET 1024
109 char * h_addr_ptrs
[MAXADDRS
+ 1];
110 char * host_aliases
[MAXALIASES
];
111 char hostbuf
[8*1024];
112 u_char host_addr
[16]; /* IPv4 or IPv6 */
113 struct __res_state
*res
;
114 void (*free_res
)(void *);
122 static const u_char mapped
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
123 static const u_char tunnelled
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
127 static void ho_close(struct irs_ho
*this);
128 static struct hostent
* ho_byname(struct irs_ho
*this, const char *name
);
129 static struct hostent
* ho_byname2(struct irs_ho
*this, const char *name
,
131 static struct hostent
* ho_byaddr(struct irs_ho
*this, const void *addr
,
133 static struct hostent
* ho_next(struct irs_ho
*this);
134 static void ho_rewind(struct irs_ho
*this);
135 static void ho_minimize(struct irs_ho
*this);
136 static struct __res_state
* ho_res_get(struct irs_ho
*this);
137 static void ho_res_set(struct irs_ho
*this,
138 struct __res_state
*res
,
139 void (*free_res
)(void *));
140 static struct addrinfo
* ho_addrinfo(struct irs_ho
*this, const char *name
,
141 const struct addrinfo
*pai
);
143 static size_t ns_namelen(const char *);
144 static int init(struct irs_ho
*this);
155 irs_lcl_ho(struct irs_acc
*this) {
161 if (!(pvt
= memget(sizeof *pvt
))) {
165 memset(pvt
, 0, sizeof *pvt
);
166 if (!(ho
= memget(sizeof *ho
))) {
167 memput(pvt
, sizeof *pvt
);
171 memset(ho
, 0x5e, sizeof *ho
);
173 ho
->close
= ho_close
;
174 ho
->byname
= ho_byname
;
175 ho
->byname2
= ho_byname2
;
176 ho
->byaddr
= ho_byaddr
;
178 ho
->rewind
= ho_rewind
;
179 ho
->minimize
= ho_minimize
;
180 ho
->res_get
= ho_res_get
;
181 ho
->res_set
= ho_res_set
;
182 ho
->addrinfo
= ho_addrinfo
;
189 ho_close(struct irs_ho
*this) {
190 struct pvt
*pvt
= (struct pvt
*)this->private;
194 (void) fclose(pvt
->fp
);
195 if (pvt
->res
&& pvt
->free_res
)
196 (*pvt
->free_res
)(pvt
->res
);
197 memput(pvt
, sizeof *pvt
);
198 memput(this, sizeof *this);
201 static struct hostent
*
202 ho_byname(struct irs_ho
*this, const char *name
) {
203 struct pvt
*pvt
= (struct pvt
*)this->private;
206 if (init(this) == -1)
209 if (pvt
->res
->options
& RES_USE_INET6
) {
210 hp
= ho_byname2(this, name
, AF_INET6
);
214 return (ho_byname2(this, name
, AF_INET
));
217 static struct hostent
*
218 ho_byname2(struct irs_ho
*this, const char *name
, int af
) {
219 struct pvt
*pvt
= (struct pvt
*)this->private;
224 if (init(this) == -1)
228 n
= ns_namelen(name
);
229 while ((hp
= ho_next(this)) != NULL
) {
232 if (hp
->h_addrtype
!= af
)
234 nn
= ns_namelen(hp
->h_name
);
235 if (strncasecmp(hp
->h_name
, name
, Max(n
, nn
)) == 0)
237 for (hap
= hp
->h_aliases
; *hap
; hap
++) {
238 nn
= ns_namelen(*hap
);
239 if (strncasecmp(*hap
, name
, Max(n
, nn
)) == 0)
245 RES_SET_H_ERRNO(pvt
->res
, HOST_NOT_FOUND
);
248 RES_SET_H_ERRNO(pvt
->res
, NETDB_SUCCESS
);
252 static struct hostent
*
253 ho_byaddr(struct irs_ho
*this, const void *addr
, int len
, int af
) {
254 struct pvt
*pvt
= (struct pvt
*)this->private;
255 const u_char
*uaddr
= addr
;
259 if (init(this) == -1)
262 if (af
== AF_INET6
&& len
== IN6ADDRSZ
&&
263 (!memcmp(uaddr
, mapped
, sizeof mapped
) ||
264 !memcmp(uaddr
, tunnelled
, sizeof tunnelled
))) {
266 addr
= (const u_char
*)addr
+ sizeof mapped
;
267 uaddr
+= sizeof mapped
;
279 errno
= EAFNOSUPPORT
;
280 RES_SET_H_ERRNO(pvt
->res
, NETDB_INTERNAL
);
285 RES_SET_H_ERRNO(pvt
->res
, NETDB_INTERNAL
);
293 while ((hp
= ho_next(this)) != NULL
) {
296 for (hap
= hp
->h_addr_list
; *hap
; hap
++) {
297 const u_char
*taddr
= (const u_char
*)*hap
;
298 int taf
= hp
->h_addrtype
;
299 int tlen
= hp
->h_length
;
301 if (taf
== AF_INET6
&& tlen
== IN6ADDRSZ
&&
302 (!memcmp(taddr
, mapped
, sizeof mapped
) ||
303 !memcmp(taddr
, tunnelled
, sizeof tunnelled
))) {
305 taddr
+= sizeof mapped
;
309 if (taf
== af
&& tlen
== len
&&
310 !memcmp(taddr
, uaddr
, tlen
))
316 RES_SET_H_ERRNO(pvt
->res
, HOST_NOT_FOUND
);
319 RES_SET_H_ERRNO(pvt
->res
, NETDB_SUCCESS
);
323 static struct hostent
*
324 ho_next(struct irs_ho
*this) {
325 struct pvt
*pvt
= (struct pvt
*)this->private;
327 char *bufp
, *ndbuf
, *dbuf
= NULL
;
328 int c
, af
, len
, bufsiz
, offset
;
330 if (init(this) == -1)
336 RES_SET_H_ERRNO(pvt
->res
, NETDB_INTERNAL
);
340 bufsiz
= sizeof pvt
->hostbuf
;
343 if (!(p
= fgets(bufp
+ offset
, bufsiz
- offset
, pvt
->fp
))) {
344 RES_SET_H_ERRNO(pvt
->res
, HOST_NOT_FOUND
);
349 if (!strchr(p
, '\n') && !feof(pvt
->fp
)) {
351 /* allocate space for longer line */
353 if ((ndbuf
= malloc(bufsiz
+ GROWBUF
)) != NULL
)
356 ndbuf
= realloc(dbuf
, bufsiz
+ GROWBUF
);
361 offset
= strlen(dbuf
);
363 /* allocation failed; skip this long line */
364 while ((c
= getc(pvt
->fp
)) != EOF
)
378 if ((cp
= strpbrk(p
, "#\n")) != NULL
)
380 if (!(cp
= strpbrk(p
, " \t")))
383 if (inet_pton(AF_INET6
, p
, pvt
->host_addr
) > 0) {
386 } else if (inet_aton(p
, (struct in_addr
*)pvt
->host_addr
) > 0) {
387 if (pvt
->res
->options
& RES_USE_INET6
) {
388 map_v4v6_address((char*)pvt
->host_addr
,
389 (char*)pvt
->host_addr
);
399 pvt
->h_addr_ptrs
[0] = (char *)pvt
->host_addr
;
400 pvt
->h_addr_ptrs
[1] = NULL
;
401 pvt
->host
.h_addr_list
= pvt
->h_addr_ptrs
;
402 pvt
->host
.h_length
= len
;
403 pvt
->host
.h_addrtype
= af
;
404 while (*cp
== ' ' || *cp
== '\t')
406 pvt
->host
.h_name
= cp
;
407 q
= pvt
->host
.h_aliases
= pvt
->host_aliases
;
408 if ((cp
= strpbrk(cp
, " \t")) != NULL
)
411 if (*cp
== ' ' || *cp
== '\t') {
415 if (q
< &pvt
->host_aliases
[MAXALIASES
- 1])
417 if ((cp
= strpbrk(cp
, " \t")) != NULL
)
423 RES_SET_H_ERRNO(pvt
->res
, NETDB_SUCCESS
);
428 ho_rewind(struct irs_ho
*this) {
429 struct pvt
*pvt
= (struct pvt
*)this->private;
432 if (fseek(pvt
->fp
, 0L, SEEK_SET
) == 0)
434 (void)fclose(pvt
->fp
);
436 if (!(pvt
->fp
= fopen(_PATH_HOSTS
, "r")))
438 if (fcntl(fileno(pvt
->fp
), F_SETFD
, 1) < 0) {
439 (void)fclose(pvt
->fp
);
445 ho_minimize(struct irs_ho
*this) {
446 struct pvt
*pvt
= (struct pvt
*)this->private;
448 if (pvt
->fp
!= NULL
) {
449 (void)fclose(pvt
->fp
);
453 res_nclose(pvt
->res
);
456 static struct __res_state
*
457 ho_res_get(struct irs_ho
*this) {
458 struct pvt
*pvt
= (struct pvt
*)this->private;
461 struct __res_state
*res
;
462 res
= (struct __res_state
*)malloc(sizeof *res
);
467 memset(res
, 0, sizeof *res
);
468 ho_res_set(this, res
, free
);
475 ho_res_set(struct irs_ho
*this, struct __res_state
*res
,
476 void (*free_res
)(void *)) {
477 struct pvt
*pvt
= (struct pvt
*)this->private;
479 if (pvt
->res
&& pvt
->free_res
) {
480 res_nclose(pvt
->res
);
481 (*pvt
->free_res
)(pvt
->res
);
485 pvt
->free_res
= free_res
;
488 struct lcl_res_target
{
489 struct lcl_res_target
*next
;
494 extern struct addrinfo
*hostent2addrinfo
__P((struct hostent
*,
495 const struct addrinfo
*pai
));
497 static struct addrinfo
*
498 ho_addrinfo(struct irs_ho
*this, const char *name
, const struct addrinfo
*pai
)
500 struct pvt
*pvt
= (struct pvt
*)this->private;
502 struct lcl_res_target q
, q2
, *p
;
503 struct addrinfo sentinel
, *cur
;
505 memset(&q
, 0, sizeof(q2
));
506 memset(&q2
, 0, sizeof(q2
));
507 memset(&sentinel
, 0, sizeof(sentinel
));
510 switch(pai
->ai_family
) {
511 case AF_UNSPEC
: /* INET6 then INET4 */
523 RES_SET_H_ERRNO(pvt
->res
, NO_RECOVERY
); /* ??? */
527 for (p
= &q
; p
; p
= p
->next
) {
530 hp
= (*this->byname2
)(this, name
, p
->family
);
532 /* byname2 should've set an appropriate error */
535 if ((hp
->h_name
== NULL
) || (hp
->h_name
[0] == 0) ||
536 (hp
->h_addr_list
[0] == NULL
)) {
537 RES_SET_H_ERRNO(pvt
->res
, NO_RECOVERY
);
541 ai
= hostent2addrinfo(hp
, pai
);
544 while (cur
&& cur
->ai_next
)
549 if (sentinel
.ai_next
== NULL
)
550 RES_SET_H_ERRNO(pvt
->res
, HOST_NOT_FOUND
);
552 return(sentinel
.ai_next
);
558 ns_namelen(const char *s
) {
561 for (i
= strlen(s
); i
> 0 && s
[i
-1] == '.'; i
--)
567 init(struct irs_ho
*this) {
568 struct pvt
*pvt
= (struct pvt
*)this->private;
570 if (!pvt
->res
&& !ho_res_get(this))
572 if (((pvt
->res
->options
& RES_INIT
) == 0U) &&
573 res_ninit(pvt
->res
) == -1)