4 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (c) 1996-1999 by Internet Software Consortium.
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #if !defined(LINT) && !defined(CODECENTER)
21 static const char rcsid
[] = "Id: gethostent.c,v 1.8 2006/01/10 05:06:00 marka Exp";
26 #include "port_before.h"
28 #if !defined(__BIND_NOSTATIC)
30 #include <sys/types.h>
31 #include <sys/param.h>
32 #include <sys/socket.h>
33 #include <sys/ioctl.h>
34 #include <netinet/in.h>
36 #include <arpa/inet.h>
37 #include <arpa/nameser.h>
49 #include <isc/memcluster.h>
51 #include "port_after.h"
61 char addr
[NS_IN6ADDRSZ
];
62 char name
[NS_MAXDNAME
+ 1];
68 static struct net_data
*init(void);
69 static void freepvt(struct net_data
*);
70 static struct hostent
*fakeaddr(const char *, int, struct net_data
*);
76 gethostbyname(const char *name
) {
77 struct net_data
*net_data
= init();
79 return (gethostbyname_p(name
, net_data
));
83 gethostbyname2(const char *name
, int af
) {
84 struct net_data
*net_data
= init();
86 return (gethostbyname2_p(name
, af
, net_data
));
90 gethostbyaddr(const char *addr
, int len
, int af
) {
91 struct net_data
*net_data
= init();
93 return (gethostbyaddr_p(addr
, len
, af
, net_data
));
98 struct net_data
*net_data
= init();
100 return (gethostent_p(net_data
));
104 sethostent(int stayopen
) {
105 struct net_data
*net_data
= init();
106 sethostent_p(stayopen
, net_data
);
112 struct net_data
*net_data
= init();
113 endhostent_p(net_data
);
116 /* Shared private. */
119 gethostbyname_p(const char *name
, struct net_data
*net_data
) {
125 if (net_data
->res
->options
& RES_USE_INET6
) {
126 hp
= gethostbyname2_p(name
, AF_INET6
, net_data
);
130 return (gethostbyname2_p(name
, AF_INET
, net_data
));
134 gethostbyname2_p(const char *name
, int af
, struct net_data
*net_data
) {
136 char tmp
[NS_MAXDNAME
];
141 if (!net_data
|| !(ho
= net_data
->ho
))
143 if (net_data
->ho_stayopen
&& net_data
->ho_last
&&
144 net_data
->ho_last
->h_addrtype
== af
) {
145 if (ns_samename(name
, net_data
->ho_last
->h_name
) == 1)
146 return (net_data
->ho_last
);
147 for (hap
= net_data
->ho_last
->h_aliases
; hap
&& *hap
; hap
++)
148 if (ns_samename(name
, *hap
) == 1)
149 return (net_data
->ho_last
);
151 if (!strchr(name
, '.') && (cp
= res_hostalias(net_data
->res
, name
,
154 if ((hp
= fakeaddr(name
, af
, net_data
)) != NULL
)
156 net_data
->ho_last
= (*ho
->byname2
)(ho
, name
, af
);
157 if (!net_data
->ho_stayopen
)
159 return (net_data
->ho_last
);
163 gethostbyaddr_p(const char *addr
, int len
, int af
, struct net_data
*net_data
) {
167 if (!net_data
|| !(ho
= net_data
->ho
))
169 if (net_data
->ho_stayopen
&& net_data
->ho_last
&&
170 net_data
->ho_last
->h_length
== len
)
171 for (hap
= net_data
->ho_last
->h_addr_list
;
174 if (!memcmp(addr
, *hap
, len
))
175 return (net_data
->ho_last
);
176 net_data
->ho_last
= (*ho
->byaddr
)(ho
, addr
, len
, af
);
177 if (!net_data
->ho_stayopen
)
179 return (net_data
->ho_last
);
184 gethostent_p(struct net_data
*net_data
) {
188 if (!net_data
|| !(ho
= net_data
->ho
))
190 while ((hp
= (*ho
->next
)(ho
)) != NULL
&&
191 hp
->h_addrtype
== AF_INET6
&&
192 (net_data
->res
->options
& RES_USE_INET6
) == 0U)
194 net_data
->ho_last
= hp
;
195 return (net_data
->ho_last
);
200 sethostent_p(int stayopen
, struct net_data
*net_data
) {
203 if (!net_data
|| !(ho
= net_data
->ho
))
207 net_data
->ho_stayopen
= (stayopen
!= 0);
209 net_data_minimize(net_data
);
213 endhostent_p(struct net_data
*net_data
) {
216 if ((net_data
!= NULL
) && ((ho
= net_data
->ho
) != NULL
))
220 #ifndef IN6_IS_ADDR_V4COMPAT
221 static const unsigned char in6addr_compat
[12] = {
222 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
223 #define IN6_IS_ADDR_V4COMPAT(x) (!memcmp((x)->s6_addr, in6addr_compat, 12) && \
224 ((x)->s6_addr[12] != 0 || \
225 (x)->s6_addr[13] != 0 || \
226 (x)->s6_addr[14] != 0 || \
227 ((x)->s6_addr[15] != 0 && \
228 (x)->s6_addr[15] != 1)))
230 #ifndef IN6_IS_ADDR_V4MAPPED
231 #define IN6_IS_ADDR_V4MAPPED(x) (!memcmp((x)->s6_addr, in6addr_mapped, 12))
234 static const unsigned char in6addr_mapped
[12] = {
235 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
237 static int scan_interfaces(int *, int *);
238 static struct hostent
*copyandmerge(struct hostent
*, struct hostent
*, int, int *);
245 * AI_V4MAPPED + AF_INET6
246 * If no IPv6 address then a query for IPv4 and map returned values.
248 * AI_ALL + AI_V4MAPPED + AF_INET6
249 * Return IPv6 and IPv4 mapped.
252 * Only return IPv6 / IPv4 address if there is an interface of that
257 getipnodebyname(const char *name
, int af
, int flags
, int *error_num
) {
258 int have_v4
= 1, have_v6
= 1;
261 struct hostent he
, *he1
= NULL
, *he2
= NULL
, *he3
;
263 struct net_data
*net_data
= init();
267 if (net_data
== NULL
) {
268 *error_num
= NO_RECOVERY
;
272 /* If we care about active interfaces then check. */
273 if ((flags
& AI_ADDRCONFIG
) != 0)
274 if (scan_interfaces(&have_v4
, &have_v6
) == -1) {
275 *error_num
= NO_RECOVERY
;
279 /* Check for literal address. */
280 if ((v4
= inet_pton(AF_INET
, name
, &in4
)) != 1)
281 v6
= inet_pton(AF_INET6
, name
, &in6
);
283 /* Impossible combination? */
285 if ((af
== AF_INET6
&& (flags
& AI_V4MAPPED
) == 0 && v4
== 1) ||
286 (af
== AF_INET
&& v6
== 1) ||
287 (have_v4
== 0 && v4
== 1) ||
288 (have_v6
== 0 && v6
== 1) ||
289 (have_v4
== 0 && af
== AF_INET
) ||
290 (have_v6
== 0 && af
== AF_INET6
)) {
291 *error_num
= HOST_NOT_FOUND
;
295 /* Literal address? */
296 if (v4
== 1 || v6
== 1) {
300 DE_CONST(name
, he
.h_name
);
301 he
.h_addr_list
= addr_list
;
302 he
.h_addr_list
[0] = (v4
== 1) ? (char *)&in4
: (char *)&in6
;
303 he
.h_addr_list
[1] = NULL
;
304 he
.h_aliases
= aliases
;
305 he
.h_aliases
[0] = NULL
;
306 he
.h_length
= (v4
== 1) ? INADDRSZ
: IN6ADDRSZ
;
307 he
.h_addrtype
= (v4
== 1) ? AF_INET
: AF_INET6
;
308 return (copyandmerge(&he
, NULL
, af
, error_num
));
311 options
= net_data
->res
->options
;
312 net_data
->res
->options
&= ~RES_USE_INET6
;
314 tmp_err
= NO_RECOVERY
;
315 if (have_v6
&& af
== AF_INET6
) {
316 he2
= gethostbyname2_p(name
, AF_INET6
, net_data
);
318 he1
= copyandmerge(he2
, NULL
, af
, error_num
);
323 tmp_err
= net_data
->res
->res_h_errno
;
329 (af
== AF_INET6
&& (flags
& AI_V4MAPPED
) != 0 &&
330 (he1
== NULL
|| (flags
& AI_ALL
) != 0)))) {
331 he2
= gethostbyname2_p(name
, AF_INET
, net_data
);
332 if (he1
== NULL
&& he2
== NULL
) {
333 *error_num
= net_data
->res
->res_h_errno
;
337 *error_num
= tmp_err
;
339 net_data
->res
->options
= options
;
341 he3
= copyandmerge(he1
, he2
, af
, error_num
);
349 getipnodebyaddr(const void *src
, size_t len
, int af
, int *error_num
) {
350 struct hostent
*he1
, *he2
;
351 struct net_data
*net_data
= init();
355 *error_num
= NO_RECOVERY
;
361 if (len
!= (size_t)INADDRSZ
) {
362 *error_num
= NO_RECOVERY
;
367 if (len
!= (size_t)IN6ADDRSZ
) {
368 *error_num
= NO_RECOVERY
;
373 *error_num
= NO_RECOVERY
;
378 * Lookup IPv4 and IPv4 mapped/compatible addresses
380 if ((af
== AF_INET6
&&
381 IN6_IS_ADDR_V4COMPAT((const struct in6_addr
*)src
)) ||
383 IN6_IS_ADDR_V4MAPPED((const struct in6_addr
*)src
)) ||
385 const char *cp
= src
;
389 he1
= gethostbyaddr_p(cp
, 4, AF_INET
, net_data
);
391 *error_num
= net_data
->res
->res_h_errno
;
394 he2
= copyandmerge(he1
, NULL
, af
, error_num
);
398 * Restore original address if mapped/compatible.
401 memcpy(he1
->h_addr
, src
, len
);
406 * Lookup IPv6 address.
408 if (memcmp((const struct in6_addr
*)src
, &in6addr_any
, 16) == 0) {
409 *error_num
= HOST_NOT_FOUND
;
413 he1
= gethostbyaddr_p(src
, 16, AF_INET6
, net_data
);
415 *error_num
= net_data
->res
->res_h_errno
;
418 return (copyandmerge(he1
, NULL
, af
, error_num
));
422 freehostent(struct hostent
*he
) {
427 memput(he
->h_name
, strlen(he
->h_name
) + 1);
429 cpp
= he
->h_addr_list
;
430 while (*cpp
!= NULL
) {
431 memput(*cpp
, (he
->h_addrtype
== AF_INET
) ?
432 INADDRSZ
: IN6ADDRSZ
);
439 while (*cpp
!= NULL
) {
440 memput(*cpp
, strlen(*cpp
) + 1);
445 memput(he
->h_aliases
, sizeof(char *) * (names
));
446 memput(he
->h_addr_list
, sizeof(char *) * (addresses
));
447 memput(he
, sizeof *he
);
455 * Scan the interface table and set have_v4 and have_v6 depending
456 * upon whether there are IPv4 and IPv6 interface addresses.
463 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
464 !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF)
467 #define lifc_len iflc_len
468 #define lifc_buf iflc_buf
469 #define lifc_req iflc_req
470 #define LIFCONF if_laddrconf
472 #define SETFAMILYFLAGS
473 #define LIFCONF lifconf
477 #define lifr_addr iflr_addr
478 #define lifr_name iflr_name
479 #define lifr_dstaddr iflr_dstaddr
480 #define lifr_flags iflr_flags
481 #define ss_family sa_family
482 #define LIFREQ if_laddrreq
484 #define LIFREQ lifreq
488 scan_interfaces6(int *have_v4
, int *have_v6
) {
490 struct LIFREQ lifreq
;
493 char *buf
= NULL
, *cp
, *cplim
;
494 static unsigned int bufsiz
= 4095;
497 /* Get interface list from system. */
498 if ((s
= socket(AF_INET6
, SOCK_DGRAM
, 0)) == -1)
502 * Grow buffer until large enough to contain all interface
506 buf
= memget(bufsiz
);
509 #ifdef SETFAMILYFLAGS
510 lifc
.lifc_family
= AF_UNSPEC
; /*%< request all families */
513 lifc
.lifc_len
= bufsiz
;
515 if ((n
= ioctl(s
, SIOCGLIFCONF
, (char *)&lifc
)) != -1) {
517 * Some OS's just return what will fit rather
518 * than set EINVAL if the buffer is too small
519 * to fit all the interfaces in. If
520 * lifc.lifc_len is too near to the end of the
521 * buffer we will grow it just in case and
524 if (lifc
.lifc_len
+ 2 * sizeof(lifreq
) < bufsiz
)
527 if ((n
== -1) && errno
!= EINVAL
)
530 if (bufsiz
> 1000000)
537 /* Parse system's interface list. */
538 cplim
= buf
+ lifc
.lifc_len
; /*%< skip over if's with big ifr_addr's */
540 (*have_v4
== 0 || *have_v6
== 0) && cp
< cplim
;
542 memcpy(&lifreq
, cp
, sizeof lifreq
);
544 #ifdef FIX_ZERO_SA_LEN
545 if (lifreq
.lifr_addr
.sa_len
== 0)
546 lifreq
.lifr_addr
.sa_len
= 16;
548 #ifdef HAVE_MINIMUM_IFREQ
549 cpsize
= sizeof lifreq
;
550 if (lifreq
.lifr_addr
.sa_len
> sizeof (struct sockaddr
))
551 cpsize
+= (int)lifreq
.lifr_addr
.sa_len
-
552 (int)(sizeof (struct sockaddr
));
554 cpsize
= sizeof lifreq
.lifr_name
+ lifreq
.lifr_addr
.sa_len
;
555 #endif /* HAVE_MINIMUM_IFREQ */
556 #elif defined SIOCGIFCONF_ADDR
557 cpsize
= sizeof lifreq
;
559 cpsize
= sizeof lifreq
.lifr_name
;
560 /* XXX maybe this should be a hard error? */
561 if (ioctl(s
, SIOCGLIFADDR
, (char *)&lifreq
) < 0)
564 switch (lifreq
.lifr_addr
.ss_family
) {
568 &((struct sockaddr_in
*)
569 &lifreq
.lifr_addr
)->sin_addr
,
571 if (in4
.s_addr
== INADDR_ANY
)
573 n
= ioctl(s
, SIOCGLIFFLAGS
, (char *)&lifreq
);
576 if ((lifreq
.lifr_flags
& IFF_UP
) == 0)
584 &((struct sockaddr_in6
*)
585 &lifreq
.lifr_addr
)->sin6_addr
, sizeof in6
);
586 if (memcmp(&in6
, &in6addr_any
, sizeof in6
) == 0)
588 n
= ioctl(s
, SIOCGLIFFLAGS
, (char *)&lifreq
);
591 if ((lifreq
.lifr_flags
& IFF_UP
) == 0)
601 /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */
608 /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */
613 #if ( defined(__linux__) || defined(__linux) || defined(LINUX) )
616 # define IF_NAMESIZE IFNAMSIZ
618 # define IF_NAMESIZE 16
622 scan_linux6(int *have_v6
) {
625 char name
[IF_NAMESIZE
+1];
626 int ifindex
, prefix
, flag3
, flag4
;
628 proc
= fopen("/proc/net/if_inet6", "r");
632 if (fscanf(proc
, "%32[a-f0-9] %x %x %x %x %16s\n",
633 address
, &ifindex
, &prefix
, &flag3
, &flag4
, name
) == 6)
641 scan_interfaces(int *have_v4
, int *have_v6
) {
644 char _pad
[256]; /*%< leave space for IPv6 addresses */
649 char *buf
= NULL
, *cp
, *cplim
;
650 static unsigned int bufsiz
= 4095;
654 /* Set to zero. Used as loop terminators below. */
655 *have_v4
= *have_v6
= 0;
657 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
658 !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF)
660 * Try to scan the interfaces using IPv6 ioctls().
662 scan_interfaces6(have_v4
, have_v6
);
663 if (*have_v4
!= 0 && *have_v6
!= 0)
667 scan_linux6(have_v6
);
670 /* Get interface list from system. */
671 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
675 * Grow buffer until large enough to contain all interface
679 buf
= memget(bufsiz
);
682 ifc
.ifc_len
= bufsiz
;
684 #ifdef IRIX_EMUL_IOCTL_SIOCGIFCONF
686 * This is a fix for IRIX OS in which the call to ioctl with
687 * the flag SIOCGIFCONF may not return an entry for all the
688 * interfaces like most flavors of Unix.
690 if (emul_ioctl(&ifc
) >= 0)
693 if ((n
= ioctl(s
, SIOCGIFCONF
, (char *)&ifc
)) != -1) {
695 * Some OS's just return what will fit rather
696 * than set EINVAL if the buffer is too small
697 * to fit all the interfaces in. If
698 * ifc.ifc_len is too near to the end of the
699 * buffer we will grow it just in case and
702 if (ifc
.ifc_len
+ 2 * sizeof(u
.ifreq
) < bufsiz
)
706 if ((n
== -1) && errno
!= EINVAL
)
709 if (bufsiz
> 1000000)
716 /* Parse system's interface list. */
717 cplim
= buf
+ ifc
.ifc_len
; /*%< skip over if's with big ifr_addr's */
719 (*have_v4
== 0 || *have_v6
== 0) && cp
< cplim
;
721 memcpy(&u
.ifreq
, cp
, sizeof u
.ifreq
);
723 #ifdef FIX_ZERO_SA_LEN
724 if (u
.ifreq
.ifr_addr
.sa_len
== 0)
725 u
.ifreq
.ifr_addr
.sa_len
= 16;
727 #ifdef HAVE_MINIMUM_IFREQ
728 cpsize
= sizeof u
.ifreq
;
729 if (u
.ifreq
.ifr_addr
.sa_len
> sizeof (struct sockaddr
))
730 cpsize
+= (int)u
.ifreq
.ifr_addr
.sa_len
-
731 (int)(sizeof (struct sockaddr
));
733 cpsize
= sizeof u
.ifreq
.ifr_name
+ u
.ifreq
.ifr_addr
.sa_len
;
734 #endif /* HAVE_MINIMUM_IFREQ */
735 if (cpsize
> sizeof u
.ifreq
&& cpsize
<= sizeof u
)
736 memcpy(&u
.ifreq
, cp
, cpsize
);
737 #elif defined SIOCGIFCONF_ADDR
738 cpsize
= sizeof u
.ifreq
;
740 cpsize
= sizeof u
.ifreq
.ifr_name
;
741 /* XXX maybe this should be a hard error? */
742 if (ioctl(s
, SIOCGIFADDR
, (char *)&u
.ifreq
) < 0)
745 switch (u
.ifreq
.ifr_addr
.sa_family
) {
749 &((struct sockaddr_in
*)
750 &u
.ifreq
.ifr_addr
)->sin_addr
,
752 if (in4
.s_addr
== INADDR_ANY
)
754 n
= ioctl(s
, SIOCGIFFLAGS
, (char *)&u
.ifreq
);
757 if ((u
.ifreq
.ifr_flags
& IFF_UP
) == 0)
765 &((struct sockaddr_in6
*)
766 &u
.ifreq
.ifr_addr
)->sin6_addr
,
768 if (memcmp(&in6
, &in6addr_any
, sizeof in6
) == 0)
770 n
= ioctl(s
, SIOCGIFFLAGS
, (char *)&u
.ifreq
);
773 if ((u
.ifreq
.ifr_flags
& IFF_UP
) == 0)
783 /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */
790 /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */
794 static struct hostent
*
795 copyandmerge(struct hostent
*he1
, struct hostent
*he2
, int af
, int *error_num
) {
796 struct hostent
*he
= NULL
;
797 int addresses
= 1; /*%< NULL terminator */
798 int names
= 1; /*%< NULL terminator */
803 * Work out array sizes;
806 cpp
= he1
->h_addr_list
;
807 while (*cpp
!= NULL
) {
811 cpp
= he1
->h_aliases
;
812 while (*cpp
!= NULL
) {
819 cpp
= he2
->h_addr_list
;
820 while (*cpp
!= NULL
) {
825 cpp
= he2
->h_aliases
;
826 while (*cpp
!= NULL
) {
833 if (addresses
== 1) {
834 *error_num
= NO_ADDRESS
;
838 he
= memget(sizeof *he
);
842 he
->h_addr_list
= memget(sizeof(char *) * (addresses
));
843 if (he
->h_addr_list
== NULL
)
845 memset(he
->h_addr_list
, 0, sizeof(char *) * (addresses
));
848 npp
= he
->h_addr_list
;
850 cpp
= he1
->h_addr_list
;
851 while (*cpp
!= NULL
) {
852 *npp
= memget((af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
855 /* convert to mapped if required */
856 if (af
== AF_INET6
&& he1
->h_addrtype
== AF_INET
) {
857 memcpy(*npp
, in6addr_mapped
,
858 sizeof in6addr_mapped
);
859 memcpy(*npp
+ sizeof in6addr_mapped
, *cpp
,
863 (af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
871 cpp
= he2
->h_addr_list
;
872 while (*cpp
!= NULL
) {
873 *npp
= memget((af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
876 /* convert to mapped if required */
877 if (af
== AF_INET6
&& he2
->h_addrtype
== AF_INET
) {
878 memcpy(*npp
, in6addr_mapped
,
879 sizeof in6addr_mapped
);
880 memcpy(*npp
+ sizeof in6addr_mapped
, *cpp
,
884 (af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
891 he
->h_aliases
= memget(sizeof(char *) * (names
));
892 if (he
->h_aliases
== NULL
)
894 memset(he
->h_aliases
, 0, sizeof(char *) * (names
));
898 cpp
= (he1
!= NULL
) ? he1
->h_aliases
: he2
->h_aliases
;
899 while (*cpp
!= NULL
) {
900 len
= strlen (*cpp
) + 1;
910 he
->h_name
= memget(strlen((he1
!= NULL
) ?
911 he1
->h_name
: he2
->h_name
) + 1);
912 if (he
->h_name
== NULL
)
914 strcpy(he
->h_name
, (he1
!= NULL
) ? he1
->h_name
: he2
->h_name
);
916 /* set address type and length */
918 he
->h_length
= (af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
;
923 while (*cpp
!= NULL
) {
924 memput(*cpp
, strlen(*cpp
) + 1);
927 memput(he
->h_aliases
, sizeof(char *) * (names
));
930 cpp
= he
->h_addr_list
;
931 while (*cpp
!= NULL
) {
932 memput(*cpp
, (af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
936 memput(he
->h_addr_list
, sizeof(char *) * (addresses
));
939 memput(he
, sizeof *he
);
942 *error_num
= NO_RECOVERY
;
946 static struct net_data
*
948 struct net_data
*net_data
;
950 if (!(net_data
= net_data_init(NULL
)))
953 net_data
->ho
= (*net_data
->irs
->ho_map
)(net_data
->irs
);
954 if (!net_data
->ho
|| !net_data
->res
) {
957 if (net_data
&& net_data
->res
)
958 RES_SET_H_ERRNO(net_data
->res
, NETDB_INTERNAL
);
962 (*net_data
->ho
->res_set
)(net_data
->ho
, net_data
->res
, NULL
);
969 freepvt(struct net_data
*net_data
) {
970 if (net_data
->ho_data
) {
971 free(net_data
->ho_data
);
972 net_data
->ho_data
= NULL
;
976 static struct hostent
*
977 fakeaddr(const char *name
, int af
, struct net_data
*net_data
) {
981 net_data
->ho_data
= malloc(sizeof (struct pvt
));
982 if (!net_data
->ho_data
) {
984 RES_SET_H_ERRNO(net_data
->res
, NETDB_INTERNAL
);
987 pvt
= net_data
->ho_data
;
990 * Unlike its forebear(inet_aton), our friendly inet_pton() is strict
991 * in its interpretation of its input, and it will only return "1" if
992 * the input string is a formally valid(and thus unambiguous with
993 * respect to host names) internet address specification for this AF.
995 * This means "telnet 0xdeadbeef" and "telnet 127.1" are dead now.
997 if (inet_pton(af
, name
, pvt
->addr
) != 1) {
1000 * We put this back to inet_aton -- we really want the old behavior
1001 * Long live 127.1...
1003 if ((af
!= AF_INET
||
1004 inet_aton(name
, (struct in_addr
*)pvt
->addr
) != 1) &&
1005 inet_pton(af
, name
, pvt
->addr
) != 1) {
1007 RES_SET_H_ERRNO(net_data
->res
, HOST_NOT_FOUND
);
1010 strncpy(pvt
->name
, name
, NS_MAXDNAME
);
1011 pvt
->name
[NS_MAXDNAME
] = '\0';
1012 if (af
== AF_INET
&& (net_data
->res
->options
& RES_USE_INET6
) != 0U) {
1013 map_v4v6_address(pvt
->addr
, pvt
->addr
);
1016 pvt
->host
.h_addrtype
= af
;
1019 pvt
->host
.h_length
= NS_INADDRSZ
;
1022 pvt
->host
.h_length
= NS_IN6ADDRSZ
;
1025 errno
= EAFNOSUPPORT
;
1026 RES_SET_H_ERRNO(net_data
->res
, NETDB_INTERNAL
);
1029 pvt
->host
.h_name
= pvt
->name
;
1030 pvt
->host
.h_aliases
= pvt
->aliases
;
1031 pvt
->aliases
[0] = NULL
;
1032 pvt
->addrs
[0] = (char *)pvt
->addr
;
1033 pvt
->addrs
[1] = NULL
;
1034 pvt
->host
.h_addr_list
= pvt
->addrs
;
1035 RES_SET_H_ERRNO(net_data
->res
, NETDB_SUCCESS
);
1036 return (&pvt
->host
);
1039 #ifdef grot /*%< for future use in gethostbyaddr(), for "SUNSECURITY" */
1040 struct hostent
*rhp
;
1043 char hname2
[MAXDNAME
+1];
1045 if (af
== AF_INET
) {
1047 * turn off search as the name should be absolute,
1048 * 'localhost' should be matched by defnames
1050 strncpy(hname2
, hp
->h_name
, MAXDNAME
);
1051 hname2
[MAXDNAME
] = '\0';
1052 old_options
= net_data
->res
->options
;
1053 net_data
->res
->options
&= ~RES_DNSRCH
;
1054 net_data
->res
->options
|= RES_DEFNAMES
;
1055 if (!(rhp
= gethostbyname(hname2
))) {
1056 net_data
->res
->options
= old_options
;
1057 RES_SET_H_ERRNO(net_data
->res
, HOST_NOT_FOUND
);
1060 net_data
->res
->options
= old_options
;
1061 for (haddr
= rhp
->h_addr_list
; *haddr
; haddr
++)
1062 if (!memcmp(*haddr
, addr
, INADDRSZ
))
1065 RES_SET_H_ERRNO(net_data
->res
, HOST_NOT_FOUND
);
1070 #endif /*__BIND_NOSTATIC*/