4 * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or 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 WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: getipnode.c,v 1.47 2009/09/01 23:47:45 tbox Exp */
25 * These functions perform thread safe, protocol independent
26 * nodename-to-address and address-to-nodename translation as defined in
27 * RFC2553. This use a struct hostent which is defined in namedb.h:
31 * char *h_name; // official name of host
32 * char **h_aliases; // alias list
33 * int h_addrtype; // host address type
34 * int h_length; // length of address
35 * char **h_addr_list; // list of addresses from name server
37 * #define h_addr h_addr_list[0] // address, for backward compatibility
40 * The members of this structure are:
43 * The official (canonical) name of the host.
46 * A NULL-terminated array of alternate names (nicknames) for the
50 * The type of address being returned - usually PF_INET or
54 * The length of the address in bytes.
57 * A NULL terminated array of network addresses for the host. Host
58 * addresses are returned in network byte order.
60 * lwres_getipnodebyname() looks up addresses of protocol family af for
61 * the hostname name. The flags parameter contains ORed flag bits to
62 * specify the types of addresses that are searched for, and the types of
63 * addresses that are returned. The flag bits are:
66 * This is used with an af of #AF_INET6, and causes IPv4 addresses
67 * to be returned as IPv4-mapped IPv6 addresses.
70 * This is used with an af of #AF_INET6, and causes all known
71 * addresses (IPv6 and IPv4) to be returned. If #AI_V4MAPPED is
72 * also set, the IPv4 addresses are return as mapped IPv6
76 * Only return an IPv6 or IPv4 address if here is an active
77 * network interface of that type. This is not currently
78 * implemented in the BIND 9 lightweight resolver, and the flag is
82 * This default sets the #AI_V4MAPPED and #AI_ADDRCONFIG flag bits.
84 * lwres_getipnodebyaddr() performs a reverse lookup of address src which
85 * is len bytes long. af denotes the protocol family, typically PF_INET
88 * lwres_freehostent() releases all the memory associated with the struct
89 * hostent pointer. Any memory allocated for the h_name, h_addr_list
90 * and h_aliases is freed, as is the memory for the hostent structure
93 * \section getipnode_return Return Values
95 * If an error occurs, lwres_getipnodebyname() and
96 * lwres_getipnodebyaddr() set *error_num to an appropriate error code
97 * and the function returns a NULL pointer. The error codes and their
98 * meanings are defined in \link netdb.h <lwres/netdb.h>\endlink:
100 * \li #HOST_NOT_FOUND:
101 * No such host is known.
104 * The server recognised the request and the name but no address
105 * is available. Another type of request to the name server for
106 * the domain might return an answer.
109 * A temporary and possibly transient error occurred, such as a
110 * failure of a server to respond. The request may succeed if
114 * An unexpected failure occurred, and retrying the request is
117 * lwres_hstrerror() translates these error codes to suitable error
120 * \section getipnode_see See Also
122 * getaddrinfo.c, gethost.c, getnameinfo.c, herror.c, RFC2553
132 #include <lwres/lwres.h>
133 #include <lwres/net.h>
134 #include <lwres/netdb.h> /* XXX #include <netdb.h> */
136 #include "assert_p.h"
145 #ifdef LWRES_PLATFORM_NEEDIN6ADDRANY
146 LIBLWRES_EXTERNAL_DATA
const struct in6_addr in6addr_any
= IN6ADDR_ANY_INIT
;
149 #ifndef IN6_IS_ADDR_V4COMPAT
150 static const unsigned char in6addr_compat
[12] = {
151 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
153 #define IN6_IS_ADDR_V4COMPAT(x) (!memcmp((x)->s6_addr, in6addr_compat, 12) && \
154 ((x)->s6_addr[12] != 0 || \
155 (x)->s6_addr[13] != 0 || \
156 (x)->s6_addr[14] != 0 || \
157 ((x)->s6_addr[15] != 0 && \
158 (x)->s6_addr[15] != 1)))
160 #ifndef IN6_IS_ADDR_V4MAPPED
161 #define IN6_IS_ADDR_V4MAPPED(x) (!memcmp((x)->s6_addr, in6addr_mapped, 12))
164 static const unsigned char in6addr_mapped
[12] = {
165 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff
169 *** Forward declarations.
173 scan_interfaces(int *, int *);
175 static struct hostent
*
176 copyandmerge(struct hostent
*, struct hostent
*, int, int *);
178 static struct hostent
*
179 hostfromaddr(lwres_gnbaresponse_t
*addr
, int af
, const void *src
);
181 static struct hostent
*
182 hostfromname(lwres_gabnresponse_t
*name
, int af
);
185 *** Public functions.
189 * AI_V4MAPPED + AF_INET6
190 * If no IPv6 address then a query for IPv4 and map returned values.
192 * AI_ALL + AI_V4MAPPED + AF_INET6
193 * Return IPv6 and IPv4 mapped.
196 * Only return IPv6 / IPv4 address if there is an interface of that
201 lwres_getipnodebyname(const char *name
, int af
, int flags
, int *error_num
) {
202 int have_v4
= 1, have_v6
= 1;
205 struct hostent he
, *he1
= NULL
, *he2
= NULL
, *he3
= NULL
;
208 lwres_context_t
*lwrctx
= NULL
;
209 lwres_gabnresponse_t
*by
= NULL
;
213 * If we care about active interfaces then check.
215 if ((flags
& AI_ADDRCONFIG
) != 0)
216 if (scan_interfaces(&have_v4
, &have_v6
) == -1) {
217 *error_num
= NO_RECOVERY
;
221 /* Check for literal address. */
222 if ((v4
= lwres_net_pton(AF_INET
, name
, &in4
)) != 1)
223 v6
= lwres_net_pton(AF_INET6
, name
, &in6
);
226 * Impossible combination?
228 if ((af
== AF_INET6
&& (flags
& AI_V4MAPPED
) == 0 && v4
== 1) ||
229 (af
== AF_INET
&& v6
== 1) ||
230 (have_v4
== 0 && v4
== 1) ||
231 (have_v6
== 0 && v6
== 1) ||
232 (have_v4
== 0 && af
== AF_INET
) ||
233 (have_v6
== 0 && af
== AF_INET6
&&
234 (((flags
& AI_V4MAPPED
) != 0 && have_v4
) ||
235 (flags
& AI_V4MAPPED
) == 0))) {
236 *error_num
= HOST_NOT_FOUND
;
243 if (v4
== 1 || v6
== 1) {
246 char mappedname
[sizeof("::ffff:123.123.123.123")];
248 const char *const_name
;
253 if (v4
== 1 && af
== AF_INET6
) {
254 strcpy(mappedname
, "::ffff:");
255 lwres_net_ntop(AF_INET
, (char *)&in4
,
256 mappedname
+ sizeof("::ffff:") - 1,
257 sizeof(mappedname
) - sizeof("::ffff:")
259 he
.h_name
= mappedname
;
261 he
.h_name
= u
.deconst_name
;
262 he
.h_addr_list
= addr_list
;
263 he
.h_addr_list
[0] = (v4
== 1) ? (char *)&in4
: (char *)&in6
;
264 he
.h_addr_list
[1] = NULL
;
265 he
.h_aliases
= aliases
;
266 he
.h_aliases
[0] = NULL
;
267 he
.h_length
= (v4
== 1) ? INADDRSZ
: IN6ADDRSZ
;
268 he
.h_addrtype
= (v4
== 1) ? AF_INET
: AF_INET6
;
269 return (copyandmerge(&he
, NULL
, af
, error_num
));
272 n
= lwres_context_create(&lwrctx
, NULL
, NULL
, NULL
, 0);
274 *error_num
= NO_RECOVERY
;
277 (void) lwres_conf_parse(lwrctx
, lwres_resolv_conf
);
278 tmp_err
= NO_RECOVERY
;
279 if (have_v6
&& af
== AF_INET6
) {
280 n
= lwres_getaddrsbyname(lwrctx
, name
, LWRES_ADDRTYPE_V6
, &by
);
282 he1
= hostfromname(by
, AF_INET6
);
283 lwres_gabnresponse_free(lwrctx
, &by
);
285 *error_num
= NO_RECOVERY
;
289 if (n
== LWRES_R_NOTFOUND
)
290 tmp_err
= HOST_NOT_FOUND
;
292 *error_num
= NO_RECOVERY
;
300 (af
== AF_INET6
&& (flags
& AI_V4MAPPED
) != 0 &&
301 (he1
== NULL
|| (flags
& AI_ALL
) != 0)))) {
302 n
= lwres_getaddrsbyname(lwrctx
, name
, LWRES_ADDRTYPE_V4
, &by
);
304 he2
= hostfromname(by
, AF_INET
);
305 lwres_gabnresponse_free(lwrctx
, &by
);
307 *error_num
= NO_RECOVERY
;
310 } else if (he1
== NULL
) {
311 if (n
== LWRES_R_NOTFOUND
)
312 *error_num
= HOST_NOT_FOUND
;
314 *error_num
= NO_RECOVERY
;
318 *error_num
= tmp_err
;
320 he3
= copyandmerge(he1
, he2
, af
, error_num
);
324 lwres_freehostent(he1
);
326 lwres_freehostent(he2
);
327 if (lwrctx
!= NULL
) {
328 lwres_conf_clear(lwrctx
);
329 lwres_context_destroy(&lwrctx
);
334 /*% performs a reverse lookup of address src which is len bytes long. af denotes the protocol family, typically #PF_INET or PF_INET6. */
336 lwres_getipnodebyaddr(const void *src
, size_t len
, int af
, int *error_num
) {
337 struct hostent
*he1
, *he2
;
338 lwres_context_t
*lwrctx
= NULL
;
339 lwres_gnbaresponse_t
*by
= NULL
;
343 struct in6_addr
*in6
;
350 *error_num
= NO_RECOVERY
;
356 if (len
!= (unsigned int)INADDRSZ
) {
357 *error_num
= NO_RECOVERY
;
362 if (len
!= (unsigned int)IN6ADDRSZ
) {
363 *error_num
= NO_RECOVERY
;
368 *error_num
= NO_RECOVERY
;
373 * The de-"const"-ing game is done because at least one
374 * vendor's system (RedHat 6.0) defines the IN6_IS_ADDR_*
375 * macros in such a way that they discard the const with
376 * internal casting, and gcc ends up complaining. Rather
377 * than replacing their own (possibly optimized) definitions
378 * with our own, cleanly discarding the const is the easiest
384 * Look up IPv4 and IPv4 mapped/compatible addresses.
386 if ((af
== AF_INET6
&& IN6_IS_ADDR_V4COMPAT(u
.in6
)) ||
387 (af
== AF_INET6
&& IN6_IS_ADDR_V4MAPPED(u
.in6
)) ||
389 const unsigned char *cp
= src
;
393 n
= lwres_context_create(&lwrctx
, NULL
, NULL
, NULL
, 0);
394 if (n
== LWRES_R_SUCCESS
)
395 (void) lwres_conf_parse(lwrctx
, lwres_resolv_conf
);
396 if (n
== LWRES_R_SUCCESS
)
397 n
= lwres_getnamebyaddr(lwrctx
, LWRES_ADDRTYPE_V4
,
399 if (n
!= LWRES_R_SUCCESS
) {
400 lwres_conf_clear(lwrctx
);
401 lwres_context_destroy(&lwrctx
);
402 if (n
== LWRES_R_NOTFOUND
)
403 *error_num
= HOST_NOT_FOUND
;
405 *error_num
= NO_RECOVERY
;
408 he1
= hostfromaddr(by
, AF_INET
, cp
);
409 lwres_gnbaresponse_free(lwrctx
, &by
);
410 lwres_conf_clear(lwrctx
);
411 lwres_context_destroy(&lwrctx
);
416 * Convert from AF_INET to AF_INET6.
418 he2
= copyandmerge(he1
, NULL
, af
, error_num
);
419 lwres_freehostent(he1
);
423 * Restore original address.
425 memcpy(he2
->h_addr
, src
, len
);
430 * Lookup IPv6 address.
432 if (memcmp(src
, &in6addr_any
, IN6ADDRSZ
) == 0) {
433 *error_num
= HOST_NOT_FOUND
;
437 n
= lwres_context_create(&lwrctx
, NULL
, NULL
, NULL
, 0);
438 if (n
== LWRES_R_SUCCESS
)
439 (void) lwres_conf_parse(lwrctx
, lwres_resolv_conf
);
440 if (n
== LWRES_R_SUCCESS
)
441 n
= lwres_getnamebyaddr(lwrctx
, LWRES_ADDRTYPE_V6
, IN6ADDRSZ
,
444 lwres_conf_clear(lwrctx
);
445 lwres_context_destroy(&lwrctx
);
447 if (n
== LWRES_R_NOTFOUND
)
448 *error_num
= HOST_NOT_FOUND
;
450 *error_num
= NO_RECOVERY
;
455 he1
= hostfromaddr(by
, AF_INET6
, src
);
456 lwres_gnbaresponse_free(lwrctx
, &by
);
458 *error_num
= NO_RECOVERY
;
459 lwres_conf_clear(lwrctx
);
460 lwres_context_destroy(&lwrctx
);
464 /*% releases all the memory associated with the struct hostent pointer */
466 lwres_freehostent(struct hostent
*he
) {
473 cpp
= he
->h_addr_list
;
474 while (*cpp
!= NULL
) {
482 while (*cpp
!= NULL
) {
489 free(he
->h_addr_list
);
498 * Scan the interface table and set have_v4 and have_v6 depending
499 * upon whether there are IPv4 and IPv6 interface addresses.
506 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
507 !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF)
510 #define lifc_len iflc_len
511 #define lifc_buf iflc_buf
512 #define lifc_req iflc_req
513 #define LIFCONF if_laddrconf
515 #define ISC_HAVE_LIFC_FAMILY 1
516 #define ISC_HAVE_LIFC_FLAGS 1
517 #define LIFCONF lifconf
521 #define lifr_addr iflr_addr
522 #define lifr_name iflr_name
523 #define lifr_dstaddr iflr_dstaddr
524 #define lifr_flags iflr_flags
525 #define ss_family sa_family
526 #define LIFREQ if_laddrreq
528 #define LIFREQ lifreq
532 scan_interfaces6(int *have_v4
, int *have_v6
) {
534 struct LIFREQ lifreq
;
537 char *buf
= NULL
, *cp
, *cplim
;
538 static unsigned int bufsiz
= 4095;
542 * Set to zero. Used as loop terminators below.
544 *have_v4
= *have_v6
= 0;
547 * Get interface list from system.
549 if ((s
= socket(AF_INET6
, SOCK_DGRAM
, 0)) == -1)
553 * Grow buffer until large enough to contain all interface
557 buf
= malloc(bufsiz
);
560 #ifdef ISC_HAVE_LIFC_FAMILY
561 lifc
.lifc_family
= AF_UNSPEC
; /* request all families */
563 #ifdef ISC_HAVE_LIFC_FLAGS
566 lifc
.lifc_len
= bufsiz
;
568 if ((n
= ioctl(s
, SIOCGLIFCONF
, (char *)&lifc
)) != -1) {
570 * Some OS's just return what will fit rather
571 * than set EINVAL if the buffer is too small
572 * to fit all the interfaces in. If
573 * lifc.lifc_len is too near to the end of the
574 * buffer we will grow it just in case and
577 if (lifc
.lifc_len
+ 2 * sizeof(lifreq
) < bufsiz
)
580 if ((n
== -1) && errno
!= EINVAL
)
583 if (bufsiz
> 1000000)
591 * Parse system's interface list.
593 cplim
= buf
+ lifc
.lifc_len
; /* skip over if's with big ifr_addr's */
595 (*have_v4
== 0 || *have_v6
== 0) && cp
< cplim
;
597 memcpy(&lifreq
, cp
, sizeof(lifreq
));
598 #ifdef LWRES_PLATFORM_HAVESALEN
599 #ifdef FIX_ZERO_SA_LEN
600 if (lifreq
.lifr_addr
.sa_len
== 0)
601 lifreq
.lifr_addr
.sa_len
= 16;
603 #ifdef HAVE_MINIMUM_IFREQ
604 cpsize
= sizeof(lifreq
);
605 if (lifreq
.lifr_addr
.sa_len
> sizeof(struct sockaddr
))
606 cpsize
+= (int)lifreq
.lifr_addr
.sa_len
-
607 (int)(sizeof(struct sockaddr
));
609 cpsize
= sizeof(lifreq
.lifr_name
) + lifreq
.lifr_addr
.sa_len
;
610 #endif /* HAVE_MINIMUM_IFREQ */
611 #elif defined SIOCGIFCONF_ADDR
612 cpsize
= sizeof(lifreq
);
614 cpsize
= sizeof(lifreq
.lifr_name
);
615 /* XXX maybe this should be a hard error? */
616 if (ioctl(s
, SIOCGLIFADDR
, (char *)&lifreq
) < 0)
619 switch (lifreq
.lifr_addr
.ss_family
) {
623 &((struct sockaddr_in
*)
624 &lifreq
.lifr_addr
)->sin_addr
,
626 if (in4
.s_addr
== INADDR_ANY
)
628 n
= ioctl(s
, SIOCGLIFFLAGS
, (char *)&lifreq
);
631 if ((lifreq
.lifr_flags
& IFF_UP
) == 0)
639 &((struct sockaddr_in6
*)
640 &lifreq
.lifr_addr
)->sin6_addr
,
642 if (memcmp(&in6
, &in6addr_any
,
645 n
= ioctl(s
, SIOCGLIFFLAGS
, (char *)&lifreq
);
648 if ((lifreq
.lifr_flags
& IFF_UP
) == 0)
669 scan_interfaces(int *have_v4
, int *have_v6
) {
670 #if !defined(SIOCGIFCONF) || !defined(SIOCGIFADDR)
671 *have_v4
= *have_v6
= 1;
676 char _pad
[256]; /* leave space for IPv6 addresses */
681 char *buf
= NULL
, *cp
, *cplim
;
682 static unsigned int bufsiz
= 4095;
689 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
690 !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF)
692 * Try to scan the interfaces using IPv6 ioctls().
694 if (!scan_interfaces6(have_v4
, have_v6
)) {
703 * Set to zero. Used as loop terminators below.
705 *have_v4
= *have_v6
= 0;
708 * Get interface list from system.
710 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
714 * Grow buffer until large enough to contain all interface
718 buf
= malloc(bufsiz
);
721 ifc
.ifc_len
= bufsiz
;
723 #ifdef IRIX_EMUL_IOCTL_SIOCGIFCONF
725 * This is a fix for IRIX OS in which the call to ioctl with
726 * the flag SIOCGIFCONF may not return an entry for all the
727 * interfaces like most flavors of Unix.
729 if (emul_ioctl(&ifc
) >= 0)
732 if ((n
= ioctl(s
, SIOCGIFCONF
, (char *)&ifc
)) != -1) {
734 * Some OS's just return what will fit rather
735 * than set EINVAL if the buffer is too small
736 * to fit all the interfaces in. If
737 * ifc.ifc_len is too near to the end of the
738 * buffer we will grow it just in case and
741 if (ifc
.ifc_len
+ 2 * sizeof(u
.ifreq
) < bufsiz
)
745 if ((n
== -1) && errno
!= EINVAL
)
748 if (bufsiz
> 1000000)
756 * Parse system's interface list.
758 cplim
= buf
+ ifc
.ifc_len
; /* skip over if's with big ifr_addr's */
760 (*have_v4
== 0 || *have_v6
== 0) && cp
< cplim
;
762 memcpy(&u
.ifreq
, cp
, sizeof(u
.ifreq
));
763 #ifdef LWRES_PLATFORM_HAVESALEN
764 #ifdef FIX_ZERO_SA_LEN
765 if (u
.ifreq
.ifr_addr
.sa_len
== 0)
766 u
.ifreq
.ifr_addr
.sa_len
= 16;
768 #ifdef HAVE_MINIMUM_IFREQ
769 cpsize
= sizeof(u
.ifreq
);
770 if (u
.ifreq
.ifr_addr
.sa_len
> sizeof(struct sockaddr
))
771 cpsize
+= (int)u
.ifreq
.ifr_addr
.sa_len
-
772 (int)(sizeof(struct sockaddr
));
774 cpsize
= sizeof(u
.ifreq
.ifr_name
) + u
.ifreq
.ifr_addr
.sa_len
;
775 #endif /* HAVE_MINIMUM_IFREQ */
776 if (cpsize
> sizeof(u
.ifreq
) && cpsize
<= sizeof(u
))
777 memcpy(&u
.ifreq
, cp
, cpsize
);
778 #elif defined SIOCGIFCONF_ADDR
779 cpsize
= sizeof(u
.ifreq
);
781 cpsize
= sizeof(u
.ifreq
.ifr_name
);
782 /* XXX maybe this should be a hard error? */
783 if (ioctl(s
, SIOCGIFADDR
, (char *)&u
.ifreq
) < 0)
786 switch (u
.ifreq
.ifr_addr
.sa_family
) {
790 &((struct sockaddr_in
*)
791 &u
.ifreq
.ifr_addr
)->sin_addr
,
793 if (in4
.s_addr
== INADDR_ANY
)
795 n
= ioctl(s
, SIOCGIFFLAGS
, (char *)&u
.ifreq
);
798 if ((u
.ifreq
.ifr_flags
& IFF_UP
) == 0)
806 &((struct sockaddr_in6
*)
807 &u
.ifreq
.ifr_addr
)->sin6_addr
,
809 if (memcmp(&in6
, &in6addr_any
,
812 n
= ioctl(s
, SIOCGIFFLAGS
, (char *)&u
.ifreq
);
815 if ((u
.ifreq
.ifr_flags
& IFF_UP
) == 0)
842 static struct hostent
*
843 copyandmerge(struct hostent
*he1
, struct hostent
*he2
, int af
, int *error_num
)
845 struct hostent
*he
= NULL
;
846 int addresses
= 1; /* NULL terminator */
847 int names
= 1; /* NULL terminator */
852 * Work out array sizes.
855 cpp
= he1
->h_addr_list
;
856 while (*cpp
!= NULL
) {
860 cpp
= he1
->h_aliases
;
861 while (*cpp
!= NULL
) {
868 cpp
= he2
->h_addr_list
;
869 while (*cpp
!= NULL
) {
874 cpp
= he2
->h_aliases
;
875 while (*cpp
!= NULL
) {
882 if (addresses
== 1) {
883 *error_num
= NO_ADDRESS
;
887 he
= malloc(sizeof(*he
));
891 he
->h_addr_list
= malloc(sizeof(char *) * (addresses
));
892 if (he
->h_addr_list
== NULL
)
894 memset(he
->h_addr_list
, 0, sizeof(char *) * (addresses
));
899 npp
= he
->h_addr_list
;
901 cpp
= he1
->h_addr_list
;
902 while (*cpp
!= NULL
) {
903 *npp
= malloc((af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
907 * Convert to mapped if required.
909 if (af
== AF_INET6
&& he1
->h_addrtype
== AF_INET
) {
910 memcpy(*npp
, in6addr_mapped
,
911 sizeof(in6addr_mapped
));
912 memcpy(*npp
+ sizeof(in6addr_mapped
), *cpp
,
916 (af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
924 cpp
= he2
->h_addr_list
;
925 while (*cpp
!= NULL
) {
926 *npp
= malloc((af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
930 * Convert to mapped if required.
932 if (af
== AF_INET6
&& he2
->h_addrtype
== AF_INET
) {
933 memcpy(*npp
, in6addr_mapped
,
934 sizeof(in6addr_mapped
));
935 memcpy(*npp
+ sizeof(in6addr_mapped
), *cpp
,
939 (af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
946 he
->h_aliases
= malloc(sizeof(char *) * (names
));
947 if (he
->h_aliases
== NULL
)
949 memset(he
->h_aliases
, 0, sizeof(char *) * (names
));
955 cpp
= (he1
!= NULL
) ? he1
->h_aliases
: he2
->h_aliases
;
956 while (*cpp
!= NULL
) {
957 len
= strlen (*cpp
) + 1;
969 he
->h_name
= malloc(strlen((he1
!= NULL
) ?
970 he1
->h_name
: he2
->h_name
) + 1);
971 if (he
->h_name
== NULL
)
973 strcpy(he
->h_name
, (he1
!= NULL
) ? he1
->h_name
: he2
->h_name
);
976 * Set address type and length.
979 he
->h_length
= (af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
;
984 while (*cpp
!= NULL
) {
991 cpp
= he
->h_addr_list
;
992 while (*cpp
!= NULL
) {
997 free(he
->h_addr_list
);
1003 *error_num
= NO_RECOVERY
;
1007 static struct hostent
*
1008 hostfromaddr(lwres_gnbaresponse_t
*addr
, int af
, const void *src
) {
1012 he
= malloc(sizeof(*he
));
1015 memset(he
, 0, sizeof(*he
));
1018 * Set family and length.
1020 he
->h_addrtype
= af
;
1023 he
->h_length
= INADDRSZ
;
1026 he
->h_length
= IN6ADDRSZ
;
1035 he
->h_name
= strdup(addr
->realname
);
1036 if (he
->h_name
== NULL
)
1042 he
->h_aliases
= malloc(sizeof(char *) * (addr
->naliases
+ 1));
1043 if (he
->h_aliases
== NULL
)
1045 for (i
= 0; i
< addr
->naliases
; i
++) {
1046 he
->h_aliases
[i
] = strdup(addr
->aliases
[i
]);
1047 if (he
->h_aliases
[i
] == NULL
)
1050 he
->h_aliases
[i
] = NULL
;
1055 he
->h_addr_list
= malloc(sizeof(char *) * 2);
1056 if (he
->h_addr_list
== NULL
)
1058 he
->h_addr_list
[0] = malloc(he
->h_length
);
1059 if (he
->h_addr_list
[0] == NULL
)
1061 memcpy(he
->h_addr_list
[0], src
, he
->h_length
);
1062 he
->h_addr_list
[1] = NULL
;
1066 if (he
!= NULL
&& he
->h_addr_list
!= NULL
) {
1067 for (i
= 0; he
->h_addr_list
[i
] != NULL
; i
++)
1068 free(he
->h_addr_list
[i
]);
1069 free(he
->h_addr_list
);
1071 if (he
!= NULL
&& he
->h_aliases
!= NULL
) {
1072 for (i
= 0; he
->h_aliases
[i
] != NULL
; i
++)
1073 free(he
->h_aliases
[i
]);
1074 free(he
->h_aliases
);
1076 if (he
!= NULL
&& he
->h_name
!= NULL
)
1083 static struct hostent
*
1084 hostfromname(lwres_gabnresponse_t
*name
, int af
) {
1089 he
= malloc(sizeof(*he
));
1092 memset(he
, 0, sizeof(*he
));
1095 * Set family and length.
1097 he
->h_addrtype
= af
;
1100 he
->h_length
= INADDRSZ
;
1103 he
->h_length
= IN6ADDRSZ
;
1112 he
->h_name
= strdup(name
->realname
);
1113 if (he
->h_name
== NULL
)
1119 he
->h_aliases
= malloc(sizeof(char *) * (name
->naliases
+ 1));
1120 for (i
= 0; i
< name
->naliases
; i
++) {
1121 he
->h_aliases
[i
] = strdup(name
->aliases
[i
]);
1122 if (he
->h_aliases
[i
] == NULL
)
1125 he
->h_aliases
[i
] = NULL
;
1130 he
->h_addr_list
= malloc(sizeof(char *) * (name
->naddrs
+ 1));
1131 addr
= LWRES_LIST_HEAD(name
->addrs
);
1133 while (addr
!= NULL
) {
1134 he
->h_addr_list
[i
] = malloc(he
->h_length
);
1135 if (he
->h_addr_list
[i
] == NULL
)
1137 memcpy(he
->h_addr_list
[i
], addr
->address
, he
->h_length
);
1138 addr
= LWRES_LIST_NEXT(addr
, link
);
1141 he
->h_addr_list
[i
] = NULL
;
1145 if (he
!= NULL
&& he
->h_addr_list
!= NULL
) {
1146 for (i
= 0; he
->h_addr_list
[i
] != NULL
; i
++)
1147 free(he
->h_addr_list
[i
]);
1148 free(he
->h_addr_list
);
1150 if (he
!= NULL
&& he
->h_aliases
!= NULL
) {
1151 for (i
= 0; he
->h_aliases
[i
] != NULL
; i
++)
1152 free(he
->h_aliases
[i
]);
1153 free(he
->h_aliases
);
1155 if (he
!= NULL
&& he
->h_name
!= NULL
)