2 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (c) 1996-1999 by Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #if !defined(LINT) && !defined(CODECENTER)
19 static const char rcsid
[] = "$Id: gethostent.c,v 1.8 2006/01/10 05:06:00 marka Exp $";
24 #include "port_before.h"
26 #if !defined(__BIND_NOSTATIC)
28 #include <sys/types.h>
29 #include <sys/param.h>
30 #include <sys/socket.h>
31 #include <sys/ioctl.h>
32 #include <netinet/in.h>
34 #include <arpa/inet.h>
35 #include <arpa/nameser.h>
47 #include <isc/memcluster.h>
49 #include "port_after.h"
59 char addr
[NS_IN6ADDRSZ
];
60 char name
[NS_MAXDNAME
+ 1];
66 static struct net_data
*init(void);
67 static void freepvt(struct net_data
*);
68 static struct hostent
*fakeaddr(const char *, int, struct net_data
*);
74 gethostbyname(const char *name
) {
75 struct net_data
*net_data
= init();
77 return (gethostbyname_p(name
, net_data
));
81 gethostbyname2(const char *name
, int af
) {
82 struct net_data
*net_data
= init();
84 return (gethostbyname2_p(name
, af
, net_data
));
88 gethostbyaddr(const char *addr
, int len
, int af
) {
89 struct net_data
*net_data
= init();
91 return (gethostbyaddr_p(addr
, len
, af
, net_data
));
96 struct net_data
*net_data
= init();
98 return (gethostent_p(net_data
));
102 sethostent(int stayopen
) {
103 struct net_data
*net_data
= init();
104 sethostent_p(stayopen
, net_data
);
110 struct net_data
*net_data
= init();
111 endhostent_p(net_data
);
114 /* Shared private. */
117 gethostbyname_p(const char *name
, struct net_data
*net_data
) {
123 if (net_data
->res
->options
& RES_USE_INET6
) {
124 hp
= gethostbyname2_p(name
, AF_INET6
, net_data
);
128 return (gethostbyname2_p(name
, AF_INET
, net_data
));
132 gethostbyname2_p(const char *name
, int af
, struct net_data
*net_data
) {
134 char tmp
[NS_MAXDNAME
];
139 if (!net_data
|| !(ho
= net_data
->ho
))
141 if (net_data
->ho_stayopen
&& net_data
->ho_last
&&
142 net_data
->ho_last
->h_addrtype
== af
) {
143 if (ns_samename(name
, net_data
->ho_last
->h_name
) == 1)
144 return (net_data
->ho_last
);
145 for (hap
= net_data
->ho_last
->h_aliases
; hap
&& *hap
; hap
++)
146 if (ns_samename(name
, *hap
) == 1)
147 return (net_data
->ho_last
);
149 if (!strchr(name
, '.') && (cp
= res_hostalias(net_data
->res
, name
,
152 if ((hp
= fakeaddr(name
, af
, net_data
)) != NULL
)
154 net_data
->ho_last
= (*ho
->byname2
)(ho
, name
, af
);
155 if (!net_data
->ho_stayopen
)
157 return (net_data
->ho_last
);
161 gethostbyaddr_p(const char *addr
, int len
, int af
, struct net_data
*net_data
) {
165 if (!net_data
|| !(ho
= net_data
->ho
))
167 if (net_data
->ho_stayopen
&& net_data
->ho_last
&&
168 net_data
->ho_last
->h_length
== len
)
169 for (hap
= net_data
->ho_last
->h_addr_list
;
172 if (!memcmp(addr
, *hap
, len
))
173 return (net_data
->ho_last
);
174 net_data
->ho_last
= (*ho
->byaddr
)(ho
, addr
, len
, af
);
175 if (!net_data
->ho_stayopen
)
177 return (net_data
->ho_last
);
182 gethostent_p(struct net_data
*net_data
) {
186 if (!net_data
|| !(ho
= net_data
->ho
))
188 while ((hp
= (*ho
->next
)(ho
)) != NULL
&&
189 hp
->h_addrtype
== AF_INET6
&&
190 (net_data
->res
->options
& RES_USE_INET6
) == 0U)
192 net_data
->ho_last
= hp
;
193 return (net_data
->ho_last
);
198 sethostent_p(int stayopen
, struct net_data
*net_data
) {
201 if (!net_data
|| !(ho
= net_data
->ho
))
205 net_data
->ho_stayopen
= (stayopen
!= 0);
207 net_data_minimize(net_data
);
211 endhostent_p(struct net_data
*net_data
) {
214 if ((net_data
!= NULL
) && ((ho
= net_data
->ho
) != NULL
))
218 #ifndef IN6_IS_ADDR_V4COMPAT
219 static const unsigned char in6addr_compat
[12] = {
220 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
221 #define IN6_IS_ADDR_V4COMPAT(x) (!memcmp((x)->s6_addr, in6addr_compat, 12) && \
222 ((x)->s6_addr[12] != 0 || \
223 (x)->s6_addr[13] != 0 || \
224 (x)->s6_addr[14] != 0 || \
225 ((x)->s6_addr[15] != 0 && \
226 (x)->s6_addr[15] != 1)))
228 #ifndef IN6_IS_ADDR_V4MAPPED
229 #define IN6_IS_ADDR_V4MAPPED(x) (!memcmp((x)->s6_addr, in6addr_mapped, 12))
232 static const unsigned char in6addr_mapped
[12] = {
233 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
235 static int scan_interfaces(int *, int *);
236 static struct hostent
*copyandmerge(struct hostent
*, struct hostent
*, int, int *);
243 * AI_V4MAPPED + AF_INET6
244 * If no IPv6 address then a query for IPv4 and map returned values.
246 * AI_ALL + AI_V4MAPPED + AF_INET6
247 * Return IPv6 and IPv4 mapped.
250 * Only return IPv6 / IPv4 address if there is an interface of that
255 getipnodebyname(const char *name
, int af
, int flags
, int *error_num
) {
256 int have_v4
= 1, have_v6
= 1;
259 struct hostent he
, *he1
= NULL
, *he2
= NULL
, *he3
;
261 struct net_data
*net_data
= init();
265 if (net_data
== NULL
) {
266 *error_num
= NO_RECOVERY
;
270 /* If we care about active interfaces then check. */
271 if ((flags
& AI_ADDRCONFIG
) != 0)
272 if (scan_interfaces(&have_v4
, &have_v6
) == -1) {
273 *error_num
= NO_RECOVERY
;
277 /* Check for literal address. */
278 if ((v4
= inet_pton(AF_INET
, name
, &in4
)) != 1)
279 v6
= inet_pton(AF_INET6
, name
, &in6
);
281 /* Impossible combination? */
283 if ((af
== AF_INET6
&& (flags
& AI_V4MAPPED
) == 0 && v4
== 1) ||
284 (af
== AF_INET
&& v6
== 1) ||
285 (have_v4
== 0 && v4
== 1) ||
286 (have_v6
== 0 && v6
== 1) ||
287 (have_v4
== 0 && af
== AF_INET
) ||
288 (have_v6
== 0 && af
== AF_INET6
)) {
289 *error_num
= HOST_NOT_FOUND
;
293 /* Literal address? */
294 if (v4
== 1 || v6
== 1) {
298 DE_CONST(name
, he
.h_name
);
299 he
.h_addr_list
= addr_list
;
300 he
.h_addr_list
[0] = (v4
== 1) ? (char *)&in4
: (char *)&in6
;
301 he
.h_addr_list
[1] = NULL
;
302 he
.h_aliases
= aliases
;
303 he
.h_aliases
[0] = NULL
;
304 he
.h_length
= (v4
== 1) ? INADDRSZ
: IN6ADDRSZ
;
305 he
.h_addrtype
= (v4
== 1) ? AF_INET
: AF_INET6
;
306 return (copyandmerge(&he
, NULL
, af
, error_num
));
309 options
= net_data
->res
->options
;
310 net_data
->res
->options
&= ~RES_USE_INET6
;
312 tmp_err
= NO_RECOVERY
;
313 if (have_v6
&& af
== AF_INET6
) {
314 he2
= gethostbyname2_p(name
, AF_INET6
, net_data
);
316 he1
= copyandmerge(he2
, NULL
, af
, error_num
);
321 tmp_err
= net_data
->res
->res_h_errno
;
327 (af
== AF_INET6
&& (flags
& AI_V4MAPPED
) != 0 &&
328 (he1
== NULL
|| (flags
& AI_ALL
) != 0)))) {
329 he2
= gethostbyname2_p(name
, AF_INET
, net_data
);
330 if (he1
== NULL
&& he2
== NULL
) {
331 *error_num
= net_data
->res
->res_h_errno
;
335 *error_num
= tmp_err
;
337 net_data
->res
->options
= options
;
339 he3
= copyandmerge(he1
, he2
, af
, error_num
);
347 getipnodebyaddr(const void *src
, size_t len
, int af
, int *error_num
) {
348 struct hostent
*he1
, *he2
;
349 struct net_data
*net_data
= init();
353 *error_num
= NO_RECOVERY
;
359 if (len
!= (size_t)INADDRSZ
) {
360 *error_num
= NO_RECOVERY
;
365 if (len
!= (size_t)IN6ADDRSZ
) {
366 *error_num
= NO_RECOVERY
;
371 *error_num
= NO_RECOVERY
;
376 * Lookup IPv4 and IPv4 mapped/compatible addresses
378 if ((af
== AF_INET6
&&
379 IN6_IS_ADDR_V4COMPAT((const struct in6_addr
*)src
)) ||
381 IN6_IS_ADDR_V4MAPPED((const struct in6_addr
*)src
)) ||
383 const char *cp
= src
;
387 he1
= gethostbyaddr_p(cp
, 4, AF_INET
, net_data
);
389 *error_num
= net_data
->res
->res_h_errno
;
392 he2
= copyandmerge(he1
, NULL
, af
, error_num
);
396 * Restore original address if mapped/compatible.
399 memcpy(he1
->h_addr
, src
, len
);
404 * Lookup IPv6 address.
406 if (memcmp((const struct in6_addr
*)src
, &in6addr_any
, 16) == 0) {
407 *error_num
= HOST_NOT_FOUND
;
411 he1
= gethostbyaddr_p(src
, 16, AF_INET6
, net_data
);
413 *error_num
= net_data
->res
->res_h_errno
;
416 return (copyandmerge(he1
, NULL
, af
, error_num
));
420 freehostent(struct hostent
*he
) {
425 memput(he
->h_name
, strlen(he
->h_name
) + 1);
427 cpp
= he
->h_addr_list
;
428 while (*cpp
!= NULL
) {
429 memput(*cpp
, (he
->h_addrtype
== AF_INET
) ?
430 INADDRSZ
: IN6ADDRSZ
);
437 while (*cpp
!= NULL
) {
438 memput(*cpp
, strlen(*cpp
) + 1);
443 memput(he
->h_aliases
, sizeof(char *) * (names
));
444 memput(he
->h_addr_list
, sizeof(char *) * (addresses
));
445 memput(he
, sizeof *he
);
453 * Scan the interface table and set have_v4 and have_v6 depending
454 * upon whether there are IPv4 and IPv6 interface addresses.
461 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
462 !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF)
465 #define lifc_len iflc_len
466 #define lifc_buf iflc_buf
467 #define lifc_req iflc_req
468 #define LIFCONF if_laddrconf
470 #define SETFAMILYFLAGS
471 #define LIFCONF lifconf
475 #define lifr_addr iflr_addr
476 #define lifr_name iflr_name
477 #define lifr_dstaddr iflr_dstaddr
478 #define lifr_flags iflr_flags
479 #define ss_family sa_family
480 #define LIFREQ if_laddrreq
482 #define LIFREQ lifreq
486 scan_interfaces6(int *have_v4
, int *have_v6
) {
488 struct LIFREQ lifreq
;
491 char *buf
= NULL
, *cp
, *cplim
;
492 static unsigned int bufsiz
= 4095;
495 /* Get interface list from system. */
496 if ((s
= socket(AF_INET6
, SOCK_DGRAM
, 0)) == -1)
500 * Grow buffer until large enough to contain all interface
504 buf
= memget(bufsiz
);
507 #ifdef SETFAMILYFLAGS
508 lifc
.lifc_family
= AF_UNSPEC
; /*%< request all families */
511 lifc
.lifc_len
= bufsiz
;
513 if ((n
= ioctl(s
, SIOCGLIFCONF
, (char *)&lifc
)) != -1) {
515 * Some OS's just return what will fit rather
516 * than set EINVAL if the buffer is too small
517 * to fit all the interfaces in. If
518 * lifc.lifc_len is too near to the end of the
519 * buffer we will grow it just in case and
522 if (lifc
.lifc_len
+ 2 * sizeof(lifreq
) < bufsiz
)
525 if ((n
== -1) && errno
!= EINVAL
)
528 if (bufsiz
> 1000000)
535 /* Parse system's interface list. */
536 cplim
= buf
+ lifc
.lifc_len
; /*%< skip over if's with big ifr_addr's */
538 (*have_v4
== 0 || *have_v6
== 0) && cp
< cplim
;
540 memcpy(&lifreq
, cp
, sizeof lifreq
);
542 #ifdef FIX_ZERO_SA_LEN
543 if (lifreq
.lifr_addr
.sa_len
== 0)
544 lifreq
.lifr_addr
.sa_len
= 16;
546 #ifdef HAVE_MINIMUM_IFREQ
547 cpsize
= sizeof lifreq
;
548 if (lifreq
.lifr_addr
.sa_len
> sizeof (struct sockaddr
))
549 cpsize
+= (int)lifreq
.lifr_addr
.sa_len
-
550 (int)(sizeof (struct sockaddr
));
552 cpsize
= sizeof lifreq
.lifr_name
+ lifreq
.lifr_addr
.sa_len
;
553 #endif /* HAVE_MINIMUM_IFREQ */
554 #elif defined SIOCGIFCONF_ADDR
555 cpsize
= sizeof lifreq
;
557 cpsize
= sizeof lifreq
.lifr_name
;
558 /* XXX maybe this should be a hard error? */
559 if (ioctl(s
, SIOCGLIFADDR
, (char *)&lifreq
) < 0)
562 switch (lifreq
.lifr_addr
.ss_family
) {
566 &((struct sockaddr_in
*)
567 &lifreq
.lifr_addr
)->sin_addr
,
569 if (in4
.s_addr
== INADDR_ANY
)
571 n
= ioctl(s
, SIOCGLIFFLAGS
, (char *)&lifreq
);
574 if ((lifreq
.lifr_flags
& IFF_UP
) == 0)
582 &((struct sockaddr_in6
*)
583 &lifreq
.lifr_addr
)->sin6_addr
, sizeof in6
);
584 if (memcmp(&in6
, &in6addr_any
, sizeof in6
) == 0)
586 n
= ioctl(s
, SIOCGLIFFLAGS
, (char *)&lifreq
);
589 if ((lifreq
.lifr_flags
& IFF_UP
) == 0)
599 /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */
606 /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */
611 #if ( defined(__linux__) || defined(__linux) || defined(LINUX) )
614 # define IF_NAMESIZE IFNAMSIZ
616 # define IF_NAMESIZE 16
620 scan_linux6(int *have_v6
) {
623 char name
[IF_NAMESIZE
+1];
624 int ifindex
, prefix
, flag3
, flag4
;
626 proc
= fopen("/proc/net/if_inet6", "r");
630 if (fscanf(proc
, "%32[a-f0-9] %x %x %x %x %16s\n",
631 address
, &ifindex
, &prefix
, &flag3
, &flag4
, name
) == 6)
639 scan_interfaces(int *have_v4
, int *have_v6
) {
642 char _pad
[256]; /*%< leave space for IPv6 addresses */
647 char *buf
= NULL
, *cp
, *cplim
;
648 static unsigned int bufsiz
= 4095;
652 /* Set to zero. Used as loop terminators below. */
653 *have_v4
= *have_v6
= 0;
655 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
656 !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF)
658 * Try to scan the interfaces using IPv6 ioctls().
660 scan_interfaces6(have_v4
, have_v6
);
661 if (*have_v4
!= 0 && *have_v6
!= 0)
665 scan_linux6(have_v6
);
668 /* Get interface list from system. */
669 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
673 * Grow buffer until large enough to contain all interface
677 buf
= memget(bufsiz
);
680 ifc
.ifc_len
= bufsiz
;
682 #ifdef IRIX_EMUL_IOCTL_SIOCGIFCONF
684 * This is a fix for IRIX OS in which the call to ioctl with
685 * the flag SIOCGIFCONF may not return an entry for all the
686 * interfaces like most flavors of Unix.
688 if (emul_ioctl(&ifc
) >= 0)
691 if ((n
= ioctl(s
, SIOCGIFCONF
, (char *)&ifc
)) != -1) {
693 * Some OS's just return what will fit rather
694 * than set EINVAL if the buffer is too small
695 * to fit all the interfaces in. If
696 * ifc.ifc_len is too near to the end of the
697 * buffer we will grow it just in case and
700 if (ifc
.ifc_len
+ 2 * sizeof(u
.ifreq
) < bufsiz
)
704 if ((n
== -1) && errno
!= EINVAL
)
707 if (bufsiz
> 1000000)
714 /* Parse system's interface list. */
715 cplim
= buf
+ ifc
.ifc_len
; /*%< skip over if's with big ifr_addr's */
717 (*have_v4
== 0 || *have_v6
== 0) && cp
< cplim
;
719 memcpy(&u
.ifreq
, cp
, sizeof u
.ifreq
);
721 #ifdef FIX_ZERO_SA_LEN
722 if (u
.ifreq
.ifr_addr
.sa_len
== 0)
723 u
.ifreq
.ifr_addr
.sa_len
= 16;
725 #ifdef HAVE_MINIMUM_IFREQ
726 cpsize
= sizeof u
.ifreq
;
727 if (u
.ifreq
.ifr_addr
.sa_len
> sizeof (struct sockaddr
))
728 cpsize
+= (int)u
.ifreq
.ifr_addr
.sa_len
-
729 (int)(sizeof (struct sockaddr
));
731 cpsize
= sizeof u
.ifreq
.ifr_name
+ u
.ifreq
.ifr_addr
.sa_len
;
732 #endif /* HAVE_MINIMUM_IFREQ */
733 if (cpsize
> sizeof u
.ifreq
&& cpsize
<= sizeof u
)
734 memcpy(&u
.ifreq
, cp
, cpsize
);
735 #elif defined SIOCGIFCONF_ADDR
736 cpsize
= sizeof u
.ifreq
;
738 cpsize
= sizeof u
.ifreq
.ifr_name
;
739 /* XXX maybe this should be a hard error? */
740 if (ioctl(s
, SIOCGIFADDR
, (char *)&u
.ifreq
) < 0)
743 switch (u
.ifreq
.ifr_addr
.sa_family
) {
747 &((struct sockaddr_in
*)
748 &u
.ifreq
.ifr_addr
)->sin_addr
,
750 if (in4
.s_addr
== INADDR_ANY
)
752 n
= ioctl(s
, SIOCGIFFLAGS
, (char *)&u
.ifreq
);
755 if ((u
.ifreq
.ifr_flags
& IFF_UP
) == 0)
763 &((struct sockaddr_in6
*)
764 &u
.ifreq
.ifr_addr
)->sin6_addr
,
766 if (memcmp(&in6
, &in6addr_any
, sizeof in6
) == 0)
768 n
= ioctl(s
, SIOCGIFFLAGS
, (char *)&u
.ifreq
);
771 if ((u
.ifreq
.ifr_flags
& IFF_UP
) == 0)
781 /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */
788 /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */
792 static struct hostent
*
793 copyandmerge(struct hostent
*he1
, struct hostent
*he2
, int af
, int *error_num
) {
794 struct hostent
*he
= NULL
;
795 int addresses
= 1; /*%< NULL terminator */
796 int names
= 1; /*%< NULL terminator */
801 * Work out array sizes;
804 cpp
= he1
->h_addr_list
;
805 while (*cpp
!= NULL
) {
809 cpp
= he1
->h_aliases
;
810 while (*cpp
!= NULL
) {
817 cpp
= he2
->h_addr_list
;
818 while (*cpp
!= NULL
) {
823 cpp
= he2
->h_aliases
;
824 while (*cpp
!= NULL
) {
831 if (addresses
== 1) {
832 *error_num
= NO_ADDRESS
;
836 he
= memget(sizeof *he
);
840 he
->h_addr_list
= memget(sizeof(char *) * (addresses
));
841 if (he
->h_addr_list
== NULL
)
843 memset(he
->h_addr_list
, 0, sizeof(char *) * (addresses
));
846 npp
= he
->h_addr_list
;
848 cpp
= he1
->h_addr_list
;
849 while (*cpp
!= NULL
) {
850 *npp
= memget((af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
853 /* convert to mapped if required */
854 if (af
== AF_INET6
&& he1
->h_addrtype
== AF_INET
) {
855 memcpy(*npp
, in6addr_mapped
,
856 sizeof in6addr_mapped
);
857 memcpy(*npp
+ sizeof in6addr_mapped
, *cpp
,
861 (af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
869 cpp
= he2
->h_addr_list
;
870 while (*cpp
!= NULL
) {
871 *npp
= memget((af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
874 /* convert to mapped if required */
875 if (af
== AF_INET6
&& he2
->h_addrtype
== AF_INET
) {
876 memcpy(*npp
, in6addr_mapped
,
877 sizeof in6addr_mapped
);
878 memcpy(*npp
+ sizeof in6addr_mapped
, *cpp
,
882 (af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
889 he
->h_aliases
= memget(sizeof(char *) * (names
));
890 if (he
->h_aliases
== NULL
)
892 memset(he
->h_aliases
, 0, sizeof(char *) * (names
));
896 cpp
= (he1
!= NULL
) ? he1
->h_aliases
: he2
->h_aliases
;
897 while (*cpp
!= NULL
) {
898 len
= strlen (*cpp
) + 1;
908 he
->h_name
= memget(strlen((he1
!= NULL
) ?
909 he1
->h_name
: he2
->h_name
) + 1);
910 if (he
->h_name
== NULL
)
912 strcpy(he
->h_name
, (he1
!= NULL
) ? he1
->h_name
: he2
->h_name
);
914 /* set address type and length */
916 he
->h_length
= (af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
;
921 while (*cpp
!= NULL
) {
922 memput(*cpp
, strlen(*cpp
) + 1);
925 memput(he
->h_aliases
, sizeof(char *) * (names
));
928 cpp
= he
->h_addr_list
;
929 while (*cpp
!= NULL
) {
930 memput(*cpp
, (af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
934 memput(he
->h_addr_list
, sizeof(char *) * (addresses
));
937 memput(he
, sizeof *he
);
940 *error_num
= NO_RECOVERY
;
944 static struct net_data
*
946 struct net_data
*net_data
;
948 if (!(net_data
= net_data_init(NULL
)))
951 net_data
->ho
= (*net_data
->irs
->ho_map
)(net_data
->irs
);
952 if (!net_data
->ho
|| !net_data
->res
) {
955 if (net_data
&& net_data
->res
)
956 RES_SET_H_ERRNO(net_data
->res
, NETDB_INTERNAL
);
960 (*net_data
->ho
->res_set
)(net_data
->ho
, net_data
->res
, NULL
);
967 freepvt(struct net_data
*net_data
) {
968 if (net_data
->ho_data
) {
969 free(net_data
->ho_data
);
970 net_data
->ho_data
= NULL
;
974 static struct hostent
*
975 fakeaddr(const char *name
, int af
, struct net_data
*net_data
) {
979 net_data
->ho_data
= malloc(sizeof (struct pvt
));
980 if (!net_data
->ho_data
) {
982 RES_SET_H_ERRNO(net_data
->res
, NETDB_INTERNAL
);
985 pvt
= net_data
->ho_data
;
988 * Unlike its forebear(inet_aton), our friendly inet_pton() is strict
989 * in its interpretation of its input, and it will only return "1" if
990 * the input string is a formally valid(and thus unambiguous with
991 * respect to host names) internet address specification for this AF.
993 * This means "telnet 0xdeadbeef" and "telnet 127.1" are dead now.
995 if (inet_pton(af
, name
, pvt
->addr
) != 1) {
998 * We put this back to inet_aton -- we really want the old behavior
1001 if ((af
!= AF_INET
||
1002 inet_aton(name
, (struct in_addr
*)pvt
->addr
) != 1) &&
1003 inet_pton(af
, name
, pvt
->addr
) != 1) {
1005 RES_SET_H_ERRNO(net_data
->res
, HOST_NOT_FOUND
);
1008 strncpy(pvt
->name
, name
, NS_MAXDNAME
);
1009 pvt
->name
[NS_MAXDNAME
] = '\0';
1010 if (af
== AF_INET
&& (net_data
->res
->options
& RES_USE_INET6
) != 0U) {
1011 map_v4v6_address(pvt
->addr
, pvt
->addr
);
1014 pvt
->host
.h_addrtype
= af
;
1017 pvt
->host
.h_length
= NS_INADDRSZ
;
1020 pvt
->host
.h_length
= NS_IN6ADDRSZ
;
1023 errno
= EAFNOSUPPORT
;
1024 RES_SET_H_ERRNO(net_data
->res
, NETDB_INTERNAL
);
1027 pvt
->host
.h_name
= pvt
->name
;
1028 pvt
->host
.h_aliases
= pvt
->aliases
;
1029 pvt
->aliases
[0] = NULL
;
1030 pvt
->addrs
[0] = (char *)pvt
->addr
;
1031 pvt
->addrs
[1] = NULL
;
1032 pvt
->host
.h_addr_list
= pvt
->addrs
;
1033 RES_SET_H_ERRNO(net_data
->res
, NETDB_SUCCESS
);
1034 return (&pvt
->host
);
1037 #ifdef grot /*%< for future use in gethostbyaddr(), for "SUNSECURITY" */
1038 struct hostent
*rhp
;
1041 char hname2
[MAXDNAME
+1];
1043 if (af
== AF_INET
) {
1045 * turn off search as the name should be absolute,
1046 * 'localhost' should be matched by defnames
1048 strncpy(hname2
, hp
->h_name
, MAXDNAME
);
1049 hname2
[MAXDNAME
] = '\0';
1050 old_options
= net_data
->res
->options
;
1051 net_data
->res
->options
&= ~RES_DNSRCH
;
1052 net_data
->res
->options
|= RES_DEFNAMES
;
1053 if (!(rhp
= gethostbyname(hname2
))) {
1054 net_data
->res
->options
= old_options
;
1055 RES_SET_H_ERRNO(net_data
->res
, HOST_NOT_FOUND
);
1058 net_data
->res
->options
= old_options
;
1059 for (haddr
= rhp
->h_addr_list
; *haddr
; haddr
++)
1060 if (!memcmp(*haddr
, addr
, INADDRSZ
))
1063 RES_SET_H_ERRNO(net_data
->res
, HOST_NOT_FOUND
);
1068 #endif /*__BIND_NOSTATIC*/