2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
8 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
9 * Copyright (c) 1996-1999 by Internet Software Consortium.
11 * Permission to use, copy, modify, and distribute this software for any
12 * purpose with or without fee is hereby granted, provided that the above
13 * copyright notice and this permission notice appear in all copies.
15 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
18 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
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
*);
72 #ifdef SUNW_OVERRIDE_RETRY
73 extern int __res_retry(int);
74 extern int __res_retry_reset(void);
75 #endif /* SUNW_OVERRIDE_RETRY */
81 gethostbyname(const char *name
) {
82 struct net_data
*net_data
= init();
84 return (gethostbyname_p(name
, net_data
));
88 gethostbyname2(const char *name
, int af
) {
89 struct net_data
*net_data
= init();
91 return (gethostbyname2_p(name
, af
, net_data
));
95 gethostbyaddr(const char *addr
, int len
, int af
) {
96 struct net_data
*net_data
= init();
98 return (gethostbyaddr_p(addr
, len
, af
, net_data
));
103 struct net_data
*net_data
= init();
105 return (gethostent_p(net_data
));
109 sethostent(int stayopen
) {
110 struct net_data
*net_data
= init();
111 sethostent_p(stayopen
, net_data
);
117 struct net_data
*net_data
= init();
118 endhostent_p(net_data
);
121 /* Shared private. */
124 gethostbyname_p(const char *name
, struct net_data
*net_data
) {
130 if (net_data
->res
->options
& RES_USE_INET6
) {
131 hp
= gethostbyname2_p(name
, AF_INET6
, net_data
);
135 return (gethostbyname2_p(name
, AF_INET
, net_data
));
139 gethostbyname2_p(const char *name
, int af
, struct net_data
*net_data
) {
141 char tmp
[NS_MAXDNAME
];
146 if (!net_data
|| !(ho
= net_data
->ho
))
148 if (net_data
->ho_stayopen
&& net_data
->ho_last
&&
149 net_data
->ho_last
->h_addrtype
== af
) {
150 if (ns_samename(name
, net_data
->ho_last
->h_name
) == 1)
151 return (net_data
->ho_last
);
152 for (hap
= net_data
->ho_last
->h_aliases
; hap
&& *hap
; hap
++)
153 if (ns_samename(name
, *hap
) == 1)
154 return (net_data
->ho_last
);
156 if (!strchr(name
, '.') && (cp
= res_hostalias(net_data
->res
, name
,
159 if ((hp
= fakeaddr(name
, af
, net_data
)) != NULL
)
161 #ifdef SUNW_OVERRIDE_RETRY
162 net_data
->res
->retry
= __res_retry(net_data
->res
->retry
);
163 #endif /* SUNW_OVERRIDE_RETRY */
164 net_data
->ho_last
= (*ho
->byname2
)(ho
, name
, af
);
165 #ifdef SUNW_OVERRIDE_RETRY
166 net_data
->res
->retry
= __res_retry_reset();
167 #endif /* SUNW_OVERRIDE_RETRY */
168 if (!net_data
->ho_stayopen
)
170 return (net_data
->ho_last
);
174 gethostbyaddr_p(const char *addr
, int len
, int af
, struct net_data
*net_data
) {
178 if (!net_data
|| !(ho
= net_data
->ho
))
180 if (net_data
->ho_stayopen
&& net_data
->ho_last
&&
181 net_data
->ho_last
->h_length
== len
)
182 for (hap
= net_data
->ho_last
->h_addr_list
;
185 if (!memcmp(addr
, *hap
, len
))
186 return (net_data
->ho_last
);
187 net_data
->ho_last
= (*ho
->byaddr
)(ho
, addr
, len
, af
);
188 if (!net_data
->ho_stayopen
)
190 return (net_data
->ho_last
);
195 gethostent_p(struct net_data
*net_data
) {
199 if (!net_data
|| !(ho
= net_data
->ho
))
201 while ((hp
= (*ho
->next
)(ho
)) != NULL
&&
202 hp
->h_addrtype
== AF_INET6
&&
203 (net_data
->res
->options
& RES_USE_INET6
) == 0U)
205 net_data
->ho_last
= hp
;
206 return (net_data
->ho_last
);
211 sethostent_p(int stayopen
, struct net_data
*net_data
) {
214 if (!net_data
|| !(ho
= net_data
->ho
))
218 net_data
->ho_stayopen
= (stayopen
!= 0);
220 net_data_minimize(net_data
);
224 endhostent_p(struct net_data
*net_data
) {
227 if ((net_data
!= NULL
) && ((ho
= net_data
->ho
) != NULL
))
231 #ifndef IN6_IS_ADDR_V4COMPAT
232 static const unsigned char in6addr_compat
[12] = {
233 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
234 #define IN6_IS_ADDR_V4COMPAT(x) (!memcmp((x)->s6_addr, in6addr_compat, 12) && \
235 ((x)->s6_addr[12] != 0 || \
236 (x)->s6_addr[13] != 0 || \
237 (x)->s6_addr[14] != 0 || \
238 ((x)->s6_addr[15] != 0 && \
239 (x)->s6_addr[15] != 1)))
241 #ifndef IN6_IS_ADDR_V4MAPPED
242 #define IN6_IS_ADDR_V4MAPPED(x) (!memcmp((x)->s6_addr, in6addr_mapped, 12))
245 static const unsigned char in6addr_mapped
[12] = {
246 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
248 static int scan_interfaces(int *, int *);
249 static struct hostent
*copyandmerge(struct hostent
*, struct hostent
*, int, int *);
256 * AI_V4MAPPED + AF_INET6
257 * If no IPv6 address then a query for IPv4 and map returned values.
259 * AI_ALL + AI_V4MAPPED + AF_INET6
260 * Return IPv6 and IPv4 mapped.
263 * Only return IPv6 / IPv4 address if there is an interface of that
268 getipnodebyname(const char *name
, int af
, int flags
, int *error_num
) {
269 int have_v4
= 1, have_v6
= 1;
272 struct hostent he
, *he1
= NULL
, *he2
= NULL
, *he3
;
274 struct net_data
*net_data
= init();
278 if (net_data
== NULL
) {
279 *error_num
= NO_RECOVERY
;
283 /* If we care about active interfaces then check. */
284 if ((flags
& AI_ADDRCONFIG
) != 0)
285 if (scan_interfaces(&have_v4
, &have_v6
) == -1) {
286 *error_num
= NO_RECOVERY
;
290 /* Check for literal address. */
291 if ((v4
= inet_pton(AF_INET
, name
, &in4
)) != 1)
292 v6
= inet_pton(AF_INET6
, name
, &in6
);
294 /* Impossible combination? */
296 if ((af
== AF_INET6
&& (flags
& AI_V4MAPPED
) == 0 && v4
== 1) ||
297 (af
== AF_INET
&& v6
== 1) ||
298 (have_v4
== 0 && v4
== 1) ||
299 (have_v6
== 0 && v6
== 1) ||
300 (have_v4
== 0 && af
== AF_INET
) ||
301 (have_v6
== 0 && af
== AF_INET6
)) {
302 *error_num
= HOST_NOT_FOUND
;
306 /* Literal address? */
307 if (v4
== 1 || v6
== 1) {
311 DE_CONST(name
, he
.h_name
);
312 he
.h_addr_list
= addr_list
;
313 he
.h_addr_list
[0] = (v4
== 1) ? (char *)&in4
: (char *)&in6
;
314 he
.h_addr_list
[1] = NULL
;
315 he
.h_aliases
= aliases
;
316 he
.h_aliases
[0] = NULL
;
317 he
.h_length
= (v4
== 1) ? INADDRSZ
: IN6ADDRSZ
;
318 he
.h_addrtype
= (v4
== 1) ? AF_INET
: AF_INET6
;
319 return (copyandmerge(&he
, NULL
, af
, error_num
));
322 options
= net_data
->res
->options
;
323 net_data
->res
->options
&= ~RES_USE_INET6
;
325 tmp_err
= NO_RECOVERY
;
326 if (have_v6
&& af
== AF_INET6
) {
327 he2
= gethostbyname2_p(name
, AF_INET6
, net_data
);
329 he1
= copyandmerge(he2
, NULL
, af
, error_num
);
334 tmp_err
= net_data
->res
->res_h_errno
;
340 (af
== AF_INET6
&& (flags
& AI_V4MAPPED
) != 0 &&
341 (he1
== NULL
|| (flags
& AI_ALL
) != 0)))) {
342 he2
= gethostbyname2_p(name
, AF_INET
, net_data
);
343 if (he1
== NULL
&& he2
== NULL
) {
344 *error_num
= net_data
->res
->res_h_errno
;
348 *error_num
= tmp_err
;
350 net_data
->res
->options
= options
;
352 he3
= copyandmerge(he1
, he2
, af
, error_num
);
360 getipnodebyaddr(const void *src
, size_t len
, int af
, int *error_num
) {
361 struct hostent
*he1
, *he2
;
362 struct net_data
*net_data
= init();
365 #ifdef ORIGINAL_ISC_CODE
368 /* this change was added circa May 2009, but not in ISC libbind 6.0 */
369 if (src
== NULL
|| net_data
== NULL
) {
370 #endif /* ORIGINAL_ISC_CODE */
371 *error_num
= NO_RECOVERY
;
377 if (len
!= (size_t)INADDRSZ
) {
378 *error_num
= NO_RECOVERY
;
383 if (len
!= (size_t)IN6ADDRSZ
) {
384 *error_num
= NO_RECOVERY
;
389 *error_num
= NO_RECOVERY
;
394 * Lookup IPv4 and IPv4 mapped/compatible addresses
396 if ((af
== AF_INET6
&&
397 IN6_IS_ADDR_V4COMPAT((const struct in6_addr
*)src
)) ||
399 IN6_IS_ADDR_V4MAPPED((const struct in6_addr
*)src
)) ||
401 const char *cp
= src
;
405 he1
= gethostbyaddr_p(cp
, 4, AF_INET
, net_data
);
407 *error_num
= net_data
->res
->res_h_errno
;
410 he2
= copyandmerge(he1
, NULL
, af
, error_num
);
414 * Restore original address if mapped/compatible.
417 memcpy(he1
->h_addr
, src
, len
);
422 * Lookup IPv6 address.
424 if (memcmp((const struct in6_addr
*)src
, &in6addr_any
, 16) == 0) {
425 *error_num
= HOST_NOT_FOUND
;
429 he1
= gethostbyaddr_p(src
, 16, AF_INET6
, net_data
);
431 *error_num
= net_data
->res
->res_h_errno
;
434 return (copyandmerge(he1
, NULL
, af
, error_num
));
438 freehostent(struct hostent
*he
) {
443 memput(he
->h_name
, strlen(he
->h_name
) + 1);
445 cpp
= he
->h_addr_list
;
446 while (*cpp
!= NULL
) {
447 memput(*cpp
, (he
->h_addrtype
== AF_INET
) ?
448 INADDRSZ
: IN6ADDRSZ
);
455 while (*cpp
!= NULL
) {
456 memput(*cpp
, strlen(*cpp
) + 1);
461 memput(he
->h_aliases
, sizeof(char *) * (names
));
462 memput(he
->h_addr_list
, sizeof(char *) * (addresses
));
463 memput(he
, sizeof *he
);
471 * Scan the interface table and set have_v4 and have_v6 depending
472 * upon whether there are IPv4 and IPv6 interface addresses.
479 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
480 !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF)
483 #define lifc_len iflc_len
484 #define lifc_buf iflc_buf
485 #define lifc_req iflc_req
486 #define LIFCONF if_laddrconf
488 #define SETFAMILYFLAGS
489 #define LIFCONF lifconf
493 #define lifr_addr iflr_addr
494 #define lifr_name iflr_name
495 #define lifr_dstaddr iflr_dstaddr
496 #define lifr_flags iflr_flags
497 #define ss_family sa_family
498 #define LIFREQ if_laddrreq
500 #define LIFREQ lifreq
504 scan_interfaces6(int *have_v4
, int *have_v6
) {
506 struct LIFREQ lifreq
;
509 char *buf
= NULL
, *cp
, *cplim
;
510 static unsigned int bufsiz
= 4095;
513 /* Get interface list from system. */
514 if ((s
= socket(AF_INET6
, SOCK_DGRAM
, 0)) == -1)
518 * Grow buffer until large enough to contain all interface
522 buf
= memget(bufsiz
);
525 #ifdef SETFAMILYFLAGS
526 lifc
.lifc_family
= AF_UNSPEC
; /*%< request all families */
529 lifc
.lifc_len
= bufsiz
;
531 if ((n
= ioctl(s
, SIOCGLIFCONF
, (char *)&lifc
)) != -1) {
533 * Some OS's just return what will fit rather
534 * than set EINVAL if the buffer is too small
535 * to fit all the interfaces in. If
536 * lifc.lifc_len is too near to the end of the
537 * buffer we will grow it just in case and
540 if (lifc
.lifc_len
+ 2 * sizeof(lifreq
) < bufsiz
)
543 if ((n
== -1) && errno
!= EINVAL
)
546 if (bufsiz
> 1000000)
553 /* Parse system's interface list. */
554 cplim
= buf
+ lifc
.lifc_len
; /*%< skip over if's with big ifr_addr's */
556 (*have_v4
== 0 || *have_v6
== 0) && cp
< cplim
;
558 memcpy(&lifreq
, cp
, sizeof lifreq
);
560 #ifdef FIX_ZERO_SA_LEN
561 if (lifreq
.lifr_addr
.sa_len
== 0)
562 lifreq
.lifr_addr
.sa_len
= 16;
564 #ifdef HAVE_MINIMUM_IFREQ
565 cpsize
= sizeof lifreq
;
566 if (lifreq
.lifr_addr
.sa_len
> sizeof (struct sockaddr
))
567 cpsize
+= (int)lifreq
.lifr_addr
.sa_len
-
568 (int)(sizeof (struct sockaddr
));
570 cpsize
= sizeof lifreq
.lifr_name
+ lifreq
.lifr_addr
.sa_len
;
571 #endif /* HAVE_MINIMUM_IFREQ */
572 #elif defined SIOCGIFCONF_ADDR
573 cpsize
= sizeof lifreq
;
575 cpsize
= sizeof lifreq
.lifr_name
;
576 /* XXX maybe this should be a hard error? */
577 if (ioctl(s
, SIOCGLIFADDR
, (char *)&lifreq
) < 0)
580 switch (lifreq
.lifr_addr
.ss_family
) {
584 &((struct sockaddr_in
*)
585 &lifreq
.lifr_addr
)->sin_addr
,
587 if (in4
.s_addr
== INADDR_ANY
)
589 n
= ioctl(s
, SIOCGLIFFLAGS
, (char *)&lifreq
);
592 if ((lifreq
.lifr_flags
& IFF_UP
) == 0)
600 &((struct sockaddr_in6
*)
601 &lifreq
.lifr_addr
)->sin6_addr
, sizeof in6
);
602 if (memcmp(&in6
, &in6addr_any
, sizeof in6
) == 0)
604 n
= ioctl(s
, SIOCGLIFFLAGS
, (char *)&lifreq
);
607 if ((lifreq
.lifr_flags
& IFF_UP
) == 0)
617 /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */
624 /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */
629 #if ( defined(__linux__) || defined(__linux) || defined(LINUX) )
632 # define IF_NAMESIZE IFNAMSIZ
634 # define IF_NAMESIZE 16
638 scan_linux6(int *have_v6
) {
641 char name
[IF_NAMESIZE
+1];
642 int ifindex
, prefix
, flag3
, flag4
;
644 proc
= fopen("/proc/net/if_inet6", "r");
648 if (fscanf(proc
, "%32[a-f0-9] %x %x %x %x %16s\n",
649 address
, &ifindex
, &prefix
, &flag3
, &flag4
, name
) == 6)
657 scan_interfaces(int *have_v4
, int *have_v6
) {
660 char _pad
[256]; /*%< leave space for IPv6 addresses */
665 char *buf
= NULL
, *cp
, *cplim
;
666 static unsigned int bufsiz
= 4095;
670 /* Set to zero. Used as loop terminators below. */
671 *have_v4
= *have_v6
= 0;
673 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
674 !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF)
676 * Try to scan the interfaces using IPv6 ioctls().
678 scan_interfaces6(have_v4
, have_v6
);
679 if (*have_v4
!= 0 && *have_v6
!= 0)
683 scan_linux6(have_v6
);
686 /* Get interface list from system. */
687 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
691 * Grow buffer until large enough to contain all interface
695 buf
= memget(bufsiz
);
698 ifc
.ifc_len
= bufsiz
;
700 #ifdef IRIX_EMUL_IOCTL_SIOCGIFCONF
702 * This is a fix for IRIX OS in which the call to ioctl with
703 * the flag SIOCGIFCONF may not return an entry for all the
704 * interfaces like most flavors of Unix.
706 if (emul_ioctl(&ifc
) >= 0)
709 if ((n
= ioctl(s
, SIOCGIFCONF
, (char *)&ifc
)) != -1) {
711 * Some OS's just return what will fit rather
712 * than set EINVAL if the buffer is too small
713 * to fit all the interfaces in. If
714 * ifc.ifc_len is too near to the end of the
715 * buffer we will grow it just in case and
718 if (ifc
.ifc_len
+ 2 * sizeof(u
.ifreq
) < bufsiz
)
722 if ((n
== -1) && errno
!= EINVAL
)
725 if (bufsiz
> 1000000)
732 /* Parse system's interface list. */
733 cplim
= buf
+ ifc
.ifc_len
; /*%< skip over if's with big ifr_addr's */
735 (*have_v4
== 0 || *have_v6
== 0) && cp
< cplim
;
737 memcpy(&u
.ifreq
, cp
, sizeof u
.ifreq
);
739 #ifdef FIX_ZERO_SA_LEN
740 if (u
.ifreq
.ifr_addr
.sa_len
== 0)
741 u
.ifreq
.ifr_addr
.sa_len
= 16;
743 #ifdef HAVE_MINIMUM_IFREQ
744 cpsize
= sizeof u
.ifreq
;
745 if (u
.ifreq
.ifr_addr
.sa_len
> sizeof (struct sockaddr
))
746 cpsize
+= (int)u
.ifreq
.ifr_addr
.sa_len
-
747 (int)(sizeof (struct sockaddr
));
749 cpsize
= sizeof u
.ifreq
.ifr_name
+ u
.ifreq
.ifr_addr
.sa_len
;
750 #endif /* HAVE_MINIMUM_IFREQ */
751 if (cpsize
> sizeof u
.ifreq
&& cpsize
<= sizeof u
)
752 memcpy(&u
.ifreq
, cp
, cpsize
);
753 #elif defined SIOCGIFCONF_ADDR
754 cpsize
= sizeof u
.ifreq
;
756 cpsize
= sizeof u
.ifreq
.ifr_name
;
757 /* XXX maybe this should be a hard error? */
758 if (ioctl(s
, SIOCGIFADDR
, (char *)&u
.ifreq
) < 0)
761 switch (u
.ifreq
.ifr_addr
.sa_family
) {
765 &((struct sockaddr_in
*)
766 &u
.ifreq
.ifr_addr
)->sin_addr
,
768 if (in4
.s_addr
== INADDR_ANY
)
770 n
= ioctl(s
, SIOCGIFFLAGS
, (char *)&u
.ifreq
);
773 if ((u
.ifreq
.ifr_flags
& IFF_UP
) == 0)
781 &((struct sockaddr_in6
*)
782 &u
.ifreq
.ifr_addr
)->sin6_addr
,
784 if (memcmp(&in6
, &in6addr_any
, sizeof in6
) == 0)
786 n
= ioctl(s
, SIOCGIFFLAGS
, (char *)&u
.ifreq
);
789 if ((u
.ifreq
.ifr_flags
& IFF_UP
) == 0)
799 /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */
806 /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */
810 static struct hostent
*
811 copyandmerge(struct hostent
*he1
, struct hostent
*he2
, int af
, int *error_num
) {
812 struct hostent
*he
= NULL
;
813 int addresses
= 1; /*%< NULL terminator */
814 int names
= 1; /*%< NULL terminator */
819 * Work out array sizes;
822 cpp
= he1
->h_addr_list
;
823 while (*cpp
!= NULL
) {
827 cpp
= he1
->h_aliases
;
828 while (*cpp
!= NULL
) {
835 cpp
= he2
->h_addr_list
;
836 while (*cpp
!= NULL
) {
841 cpp
= he2
->h_aliases
;
842 while (*cpp
!= NULL
) {
849 if (addresses
== 1) {
850 *error_num
= NO_ADDRESS
;
854 he
= memget(sizeof *he
);
858 he
->h_addr_list
= memget(sizeof(char *) * (addresses
));
859 if (he
->h_addr_list
== NULL
)
861 memset(he
->h_addr_list
, 0, sizeof(char *) * (addresses
));
864 npp
= he
->h_addr_list
;
866 cpp
= he1
->h_addr_list
;
867 while (*cpp
!= NULL
) {
868 *npp
= memget((af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
871 /* convert to mapped if required */
872 if (af
== AF_INET6
&& he1
->h_addrtype
== AF_INET
) {
873 memcpy(*npp
, in6addr_mapped
,
874 sizeof in6addr_mapped
);
875 memcpy(*npp
+ sizeof in6addr_mapped
, *cpp
,
879 (af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
887 cpp
= he2
->h_addr_list
;
888 while (*cpp
!= NULL
) {
889 *npp
= memget((af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
892 /* convert to mapped if required */
893 if (af
== AF_INET6
&& he2
->h_addrtype
== AF_INET
) {
894 memcpy(*npp
, in6addr_mapped
,
895 sizeof in6addr_mapped
);
896 memcpy(*npp
+ sizeof in6addr_mapped
, *cpp
,
900 (af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
907 he
->h_aliases
= memget(sizeof(char *) * (names
));
908 if (he
->h_aliases
== NULL
)
910 memset(he
->h_aliases
, 0, sizeof(char *) * (names
));
914 cpp
= (he1
!= NULL
) ? he1
->h_aliases
: he2
->h_aliases
;
915 while (*cpp
!= NULL
) {
916 len
= strlen (*cpp
) + 1;
926 he
->h_name
= memget(strlen((he1
!= NULL
) ?
927 he1
->h_name
: he2
->h_name
) + 1);
928 if (he
->h_name
== NULL
)
930 strcpy(he
->h_name
, (he1
!= NULL
) ? he1
->h_name
: he2
->h_name
);
932 /* set address type and length */
934 he
->h_length
= (af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
;
939 while (*cpp
!= NULL
) {
940 memput(*cpp
, strlen(*cpp
) + 1);
943 memput(he
->h_aliases
, sizeof(char *) * (names
));
946 cpp
= he
->h_addr_list
;
947 while (*cpp
!= NULL
) {
948 memput(*cpp
, (af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
952 memput(he
->h_addr_list
, sizeof(char *) * (addresses
));
955 memput(he
, sizeof *he
);
958 *error_num
= NO_RECOVERY
;
962 static struct net_data
*
964 struct net_data
*net_data
;
966 if (!(net_data
= net_data_init(NULL
)))
969 net_data
->ho
= (*net_data
->irs
->ho_map
)(net_data
->irs
);
970 if (!net_data
->ho
|| !net_data
->res
) {
974 #ifdef SUNW_SETHERRNO
975 h_errno
= NETDB_INTERNAL
;
976 #endif /* SUNW_SETHERRNO */
977 if (net_data
&& net_data
->res
)
978 RES_SET_H_ERRNO(net_data
->res
, NETDB_INTERNAL
);
982 (*net_data
->ho
->res_set
)(net_data
->ho
, net_data
->res
, NULL
);
989 freepvt(struct net_data
*net_data
) {
990 if (net_data
->ho_data
) {
991 free(net_data
->ho_data
);
992 net_data
->ho_data
= NULL
;
996 static struct hostent
*
997 fakeaddr(const char *name
, int af
, struct net_data
*net_data
) {
1001 net_data
->ho_data
= malloc(sizeof (struct pvt
));
1002 if (!net_data
->ho_data
) {
1004 RES_SET_H_ERRNO(net_data
->res
, NETDB_INTERNAL
);
1007 pvt
= net_data
->ho_data
;
1010 * Unlike its forebear(inet_aton), our friendly inet_pton() is strict
1011 * in its interpretation of its input, and it will only return "1" if
1012 * the input string is a formally valid(and thus unambiguous with
1013 * respect to host names) internet address specification for this AF.
1015 * This means "telnet 0xdeadbeef" and "telnet 127.1" are dead now.
1017 if (inet_pton(af
, name
, pvt
->addr
) != 1) {
1020 * We put this back to inet_aton -- we really want the old behavior
1021 * Long live 127.1...
1023 if ((af
!= AF_INET
||
1024 inet_aton(name
, (struct in_addr
*)pvt
->addr
) != 1) &&
1025 inet_pton(af
, name
, pvt
->addr
) != 1) {
1027 RES_SET_H_ERRNO(net_data
->res
, HOST_NOT_FOUND
);
1030 strncpy(pvt
->name
, name
, NS_MAXDNAME
);
1031 pvt
->name
[NS_MAXDNAME
] = '\0';
1032 if (af
== AF_INET
&& (net_data
->res
->options
& RES_USE_INET6
) != 0U) {
1033 map_v4v6_address(pvt
->addr
, pvt
->addr
);
1036 pvt
->host
.h_addrtype
= af
;
1039 pvt
->host
.h_length
= NS_INADDRSZ
;
1042 pvt
->host
.h_length
= NS_IN6ADDRSZ
;
1045 errno
= EAFNOSUPPORT
;
1046 RES_SET_H_ERRNO(net_data
->res
, NETDB_INTERNAL
);
1049 pvt
->host
.h_name
= pvt
->name
;
1050 pvt
->host
.h_aliases
= pvt
->aliases
;
1051 pvt
->aliases
[0] = NULL
;
1052 pvt
->addrs
[0] = (char *)pvt
->addr
;
1053 pvt
->addrs
[1] = NULL
;
1054 pvt
->host
.h_addr_list
= pvt
->addrs
;
1055 RES_SET_H_ERRNO(net_data
->res
, NETDB_SUCCESS
);
1056 return (&pvt
->host
);
1059 #ifdef grot /*%< for future use in gethostbyaddr(), for "SUNSECURITY" */
1060 struct hostent
*rhp
;
1063 char hname2
[MAXDNAME
+1];
1065 if (af
== AF_INET
) {
1067 * turn off search as the name should be absolute,
1068 * 'localhost' should be matched by defnames
1070 strncpy(hname2
, hp
->h_name
, MAXDNAME
);
1071 hname2
[MAXDNAME
] = '\0';
1072 old_options
= net_data
->res
->options
;
1073 net_data
->res
->options
&= ~RES_DNSRCH
;
1074 net_data
->res
->options
|= RES_DEFNAMES
;
1075 if (!(rhp
= gethostbyname(hname2
))) {
1076 net_data
->res
->options
= old_options
;
1077 RES_SET_H_ERRNO(net_data
->res
, HOST_NOT_FOUND
);
1080 net_data
->res
->options
= old_options
;
1081 for (haddr
= rhp
->h_addr_list
; *haddr
; haddr
++)
1082 if (!memcmp(*haddr
, addr
, INADDRSZ
))
1085 RES_SET_H_ERRNO(net_data
->res
, HOST_NOT_FOUND
);
1090 #endif /*__BIND_NOSTATIC*/