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 $ */
56 #include "port_before.h"
58 #include <sys/types.h>
59 #include <sys/param.h>
60 #include <sys/socket.h>
62 #include <netinet/in.h>
63 #include <arpa/inet.h>
64 #include <arpa/nameser.h>
76 #include <isc/memcluster.h>
78 #include "port_after.h"
85 # define SPRINTF(x) strlen(sprintf/**/x)
87 # define SPRINTF(x) sprintf x
94 #define Max(a,b) ((a) > (b) ? (a) : (b))
97 #define MAXPACKET PACKETSZ
99 #define MAXPACKET 1024
105 char * h_addr_ptrs
[MAXADDRS
+ 1];
106 char * host_aliases
[MAXALIASES
];
107 char hostbuf
[8*1024];
108 u_char host_addr
[16]; /*%< IPv4 or IPv6 */
109 struct __res_state
*res
;
110 void (*free_res
)(void *);
118 static const u_char mapped
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
119 static const u_char tunnelled
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
123 static void ho_close(struct irs_ho
*this);
124 static struct hostent
* ho_byname(struct irs_ho
*this, const char *name
);
125 static struct hostent
* ho_byname2(struct irs_ho
*this, const char *name
,
127 static struct hostent
* ho_byaddr(struct irs_ho
*this, const void *addr
,
129 static struct hostent
* ho_next(struct irs_ho
*this);
130 static void ho_rewind(struct irs_ho
*this);
131 static void ho_minimize(struct irs_ho
*this);
132 static struct __res_state
* ho_res_get(struct irs_ho
*this);
133 static void ho_res_set(struct irs_ho
*this,
134 struct __res_state
*res
,
135 void (*free_res
)(void *));
136 static struct addrinfo
* ho_addrinfo(struct irs_ho
*this, const char *name
,
137 const struct addrinfo
*pai
);
139 static size_t ns_namelen(const char *);
140 static int init(struct irs_ho
*this);
151 irs_lcl_ho(struct irs_acc
*this) {
157 if (!(pvt
= memget(sizeof *pvt
))) {
161 memset(pvt
, 0, sizeof *pvt
);
162 if (!(ho
= memget(sizeof *ho
))) {
163 memput(pvt
, sizeof *pvt
);
167 memset(ho
, 0x5e, sizeof *ho
);
169 ho
->close
= ho_close
;
170 ho
->byname
= ho_byname
;
171 ho
->byname2
= ho_byname2
;
172 ho
->byaddr
= ho_byaddr
;
174 ho
->rewind
= ho_rewind
;
175 ho
->minimize
= ho_minimize
;
176 ho
->res_get
= ho_res_get
;
177 ho
->res_set
= ho_res_set
;
178 ho
->addrinfo
= ho_addrinfo
;
185 ho_close(struct irs_ho
*this) {
186 struct pvt
*pvt
= (struct pvt
*)this->private;
190 (void) fclose(pvt
->fp
);
191 if (pvt
->res
&& pvt
->free_res
)
192 (*pvt
->free_res
)(pvt
->res
);
193 memput(pvt
, sizeof *pvt
);
194 memput(this, sizeof *this);
197 static struct hostent
*
198 ho_byname(struct irs_ho
*this, const char *name
) {
199 struct pvt
*pvt
= (struct pvt
*)this->private;
202 if (init(this) == -1)
205 if (pvt
->res
->options
& RES_USE_INET6
) {
206 hp
= ho_byname2(this, name
, AF_INET6
);
210 return (ho_byname2(this, name
, AF_INET
));
213 static struct hostent
*
214 ho_byname2(struct irs_ho
*this, const char *name
, int af
) {
215 struct pvt
*pvt
= (struct pvt
*)this->private;
220 if (init(this) == -1)
224 n
= ns_namelen(name
);
225 while ((hp
= ho_next(this)) != NULL
) {
228 if (hp
->h_addrtype
!= af
)
230 nn
= ns_namelen(hp
->h_name
);
231 if (strncasecmp(hp
->h_name
, name
, Max(n
, nn
)) == 0)
233 for (hap
= hp
->h_aliases
; *hap
; hap
++) {
234 nn
= ns_namelen(*hap
);
235 if (strncasecmp(*hap
, name
, Max(n
, nn
)) == 0)
241 RES_SET_H_ERRNO(pvt
->res
, HOST_NOT_FOUND
);
244 RES_SET_H_ERRNO(pvt
->res
, NETDB_SUCCESS
);
248 static struct hostent
*
249 ho_byaddr(struct irs_ho
*this, const void *addr
, int len
, int af
) {
250 struct pvt
*pvt
= (struct pvt
*)this->private;
251 const u_char
*uaddr
= addr
;
255 if (init(this) == -1)
258 if (af
== AF_INET6
&& len
== IN6ADDRSZ
&&
259 (!memcmp(uaddr
, mapped
, sizeof mapped
) ||
260 !memcmp(uaddr
, tunnelled
, sizeof tunnelled
))) {
262 addr
= (const u_char
*)addr
+ sizeof mapped
;
263 uaddr
+= sizeof mapped
;
275 errno
= EAFNOSUPPORT
;
276 RES_SET_H_ERRNO(pvt
->res
, NETDB_INTERNAL
);
281 RES_SET_H_ERRNO(pvt
->res
, NETDB_INTERNAL
);
289 while ((hp
= ho_next(this)) != NULL
) {
292 for (hap
= hp
->h_addr_list
; *hap
; hap
++) {
293 const u_char
*taddr
= (const u_char
*)*hap
;
294 int taf
= hp
->h_addrtype
;
295 int tlen
= hp
->h_length
;
297 if (taf
== AF_INET6
&& tlen
== IN6ADDRSZ
&&
298 (!memcmp(taddr
, mapped
, sizeof mapped
) ||
299 !memcmp(taddr
, tunnelled
, sizeof tunnelled
))) {
301 taddr
+= sizeof mapped
;
305 if (taf
== af
&& tlen
== len
&&
306 !memcmp(taddr
, uaddr
, tlen
))
312 RES_SET_H_ERRNO(pvt
->res
, HOST_NOT_FOUND
);
315 RES_SET_H_ERRNO(pvt
->res
, NETDB_SUCCESS
);
319 static struct hostent
*
320 ho_next(struct irs_ho
*this) {
321 struct pvt
*pvt
= (struct pvt
*)this->private;
323 char *bufp
, *ndbuf
, *dbuf
= NULL
;
324 int c
, af
, len
, bufsiz
, offset
;
326 if (init(this) == -1)
332 RES_SET_H_ERRNO(pvt
->res
, NETDB_INTERNAL
);
336 bufsiz
= sizeof pvt
->hostbuf
;
339 if (!(p
= fgets(bufp
+ offset
, bufsiz
- offset
, pvt
->fp
))) {
340 RES_SET_H_ERRNO(pvt
->res
, HOST_NOT_FOUND
);
344 if (!strchr(p
, '\n') && !feof(pvt
->fp
)) {
346 /* allocate space for longer line */
348 if ((ndbuf
= malloc(bufsiz
+ GROWBUF
)) != NULL
)
351 ndbuf
= realloc(dbuf
, bufsiz
+ GROWBUF
);
356 offset
= strlen(dbuf
);
358 /* allocation failed; skip this long line */
359 while ((c
= getc(pvt
->fp
)) != EOF
)
373 if ((cp
= strpbrk(p
, "#\n")) != NULL
)
375 if (!(cp
= strpbrk(p
, " \t")))
378 if (inet_pton(AF_INET6
, p
, pvt
->host_addr
) > 0) {
381 } else if (inet_aton(p
, (struct in_addr
*)pvt
->host_addr
) > 0) {
382 if (pvt
->res
->options
& RES_USE_INET6
) {
383 map_v4v6_address((char*)pvt
->host_addr
,
384 (char*)pvt
->host_addr
);
394 pvt
->h_addr_ptrs
[0] = (char *)pvt
->host_addr
;
395 pvt
->h_addr_ptrs
[1] = NULL
;
396 pvt
->host
.h_addr_list
= pvt
->h_addr_ptrs
;
397 pvt
->host
.h_length
= len
;
398 pvt
->host
.h_addrtype
= af
;
399 while (*cp
== ' ' || *cp
== '\t')
401 pvt
->host
.h_name
= cp
;
402 q
= pvt
->host
.h_aliases
= pvt
->host_aliases
;
403 if ((cp
= strpbrk(cp
, " \t")) != NULL
)
406 if (*cp
== ' ' || *cp
== '\t') {
410 if (q
< &pvt
->host_aliases
[MAXALIASES
- 1])
412 if ((cp
= strpbrk(cp
, " \t")) != NULL
)
417 RES_SET_H_ERRNO(pvt
->res
, NETDB_SUCCESS
);
422 ho_rewind(struct irs_ho
*this) {
423 struct pvt
*pvt
= (struct pvt
*)this->private;
426 if (fseek(pvt
->fp
, 0L, SEEK_SET
) == 0)
428 (void)fclose(pvt
->fp
);
430 if (!(pvt
->fp
= fopen(_PATH_HOSTS
, "r")))
432 if (fcntl(fileno(pvt
->fp
), F_SETFD
, 1) < 0) {
433 (void)fclose(pvt
->fp
);
439 ho_minimize(struct irs_ho
*this) {
440 struct pvt
*pvt
= (struct pvt
*)this->private;
442 if (pvt
->fp
!= NULL
) {
443 (void)fclose(pvt
->fp
);
447 res_nclose(pvt
->res
);
450 static struct __res_state
*
451 ho_res_get(struct irs_ho
*this) {
452 struct pvt
*pvt
= (struct pvt
*)this->private;
455 struct __res_state
*res
;
456 res
= (struct __res_state
*)malloc(sizeof *res
);
461 memset(res
, 0, sizeof *res
);
462 ho_res_set(this, res
, free
);
469 ho_res_set(struct irs_ho
*this, struct __res_state
*res
,
470 void (*free_res
)(void *)) {
471 struct pvt
*pvt
= (struct pvt
*)this->private;
473 if (pvt
->res
&& pvt
->free_res
) {
474 res_nclose(pvt
->res
);
475 (*pvt
->free_res
)(pvt
->res
);
479 pvt
->free_res
= free_res
;
482 struct lcl_res_target
{
483 struct lcl_res_target
*next
;
488 extern struct addrinfo
*hostent2addrinfo
__P((struct hostent
*,
489 const struct addrinfo
*pai
));
491 static struct addrinfo
*
492 ho_addrinfo(struct irs_ho
*this, const char *name
, const struct addrinfo
*pai
)
494 struct pvt
*pvt
= (struct pvt
*)this->private;
496 struct lcl_res_target q
, q2
, *p
;
497 struct addrinfo sentinel
, *cur
;
499 memset(&q
, 0, sizeof(q2
));
500 memset(&q2
, 0, sizeof(q2
));
501 memset(&sentinel
, 0, sizeof(sentinel
));
504 switch(pai
->ai_family
) {
505 case AF_UNSPEC
: /*%< INET6 then INET4 */
517 RES_SET_H_ERRNO(pvt
->res
, NO_RECOVERY
); /*%< ??? */
521 for (p
= &q
; p
; p
= p
->next
) {
524 hp
= (*this->byname2
)(this, name
, p
->family
);
526 /* byname2 should've set an appropriate error */
529 if ((hp
->h_name
== NULL
) || (hp
->h_name
[0] == 0) ||
530 (hp
->h_addr_list
[0] == NULL
)) {
531 RES_SET_H_ERRNO(pvt
->res
, NO_RECOVERY
);
535 ai
= hostent2addrinfo(hp
, pai
);
543 if (sentinel
.ai_next
== NULL
)
544 RES_SET_H_ERRNO(pvt
->res
, HOST_NOT_FOUND
);
546 return(sentinel
.ai_next
);
552 ns_namelen(const char *s
) {
555 for (i
= strlen(s
); i
> 0 && s
[i
-1] == '.'; i
--)
561 init(struct irs_ho
*this) {
562 struct pvt
*pvt
= (struct pvt
*)this->private;
564 if (!pvt
->res
&& !ho_res_get(this))
566 if (((pvt
->res
->options
& RES_INIT
) == 0U) &&
567 res_ninit(pvt
->res
) == -1)