1 /* $NetBSD: getipnode.c,v 1.6 2014/12/10 04:38:02 christos Exp $ */
4 * Copyright (C) 2004, 2005, 2007, 2009, 2012, 2014 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 memmove(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
) {
476 cpp
= he
->h_addr_list
;
477 while (*cpp
!= NULL
) {
485 while (*cpp
!= NULL
) {
492 free(he
->h_addr_list
);
501 * Scan the interface table and set have_v4 and have_v6 depending
502 * upon whether there are IPv4 and IPv6 interface addresses.
509 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
510 !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF)
513 #define lifc_len iflc_len
514 #define lifc_buf iflc_buf
515 #define lifc_req iflc_req
516 #define LIFCONF if_laddrconf
518 #define ISC_HAVE_LIFC_FAMILY 1
519 #define ISC_HAVE_LIFC_FLAGS 1
520 #define LIFCONF lifconf
524 #define lifr_addr iflr_addr
525 #define lifr_name iflr_name
526 #define lifr_dstaddr iflr_dstaddr
527 #define lifr_flags iflr_flags
528 #define ss_family sa_family
529 #define LIFREQ if_laddrreq
531 #define LIFREQ lifreq
535 scan_interfaces6(int *have_v4
, int *have_v6
) {
537 struct LIFREQ lifreq
;
540 char *buf
= NULL
, *cp
, *cplim
;
541 static unsigned int bufsiz
= 4095;
545 * Set to zero. Used as loop terminators below.
547 *have_v4
= *have_v6
= 0;
550 * Get interface list from system.
552 if ((s
= socket(AF_INET6
, SOCK_DGRAM
, 0)) == -1)
556 * Grow buffer until large enough to contain all interface
560 buf
= malloc(bufsiz
);
563 #ifdef ISC_HAVE_LIFC_FAMILY
564 lifc
.lifc_family
= AF_UNSPEC
; /* request all families */
566 #ifdef ISC_HAVE_LIFC_FLAGS
569 lifc
.lifc_len
= bufsiz
;
571 if ((n
= ioctl(s
, SIOCGLIFCONF
, (char *)&lifc
)) != -1) {
573 * Some OS's just return what will fit rather
574 * than set EINVAL if the buffer is too small
575 * to fit all the interfaces in. If
576 * lifc.lifc_len is too near to the end of the
577 * buffer we will grow it just in case and
580 if (lifc
.lifc_len
+ 2 * sizeof(lifreq
) < bufsiz
)
583 if ((n
== -1) && errno
!= EINVAL
)
586 if (bufsiz
> 1000000)
594 * Parse system's interface list.
596 cplim
= buf
+ lifc
.lifc_len
; /* skip over if's with big ifr_addr's */
598 (*have_v4
== 0 || *have_v6
== 0) && cp
< cplim
;
600 memmove(&lifreq
, cp
, sizeof(lifreq
));
601 #ifdef LWRES_PLATFORM_HAVESALEN
602 #ifdef FIX_ZERO_SA_LEN
603 if (lifreq
.lifr_addr
.sa_len
== 0)
604 lifreq
.lifr_addr
.sa_len
= 16;
606 #ifdef HAVE_MINIMUM_IFREQ
607 cpsize
= sizeof(lifreq
);
608 if (lifreq
.lifr_addr
.sa_len
> sizeof(struct sockaddr
))
609 cpsize
+= (int)lifreq
.lifr_addr
.sa_len
-
610 (int)(sizeof(struct sockaddr
));
612 cpsize
= sizeof(lifreq
.lifr_name
) + lifreq
.lifr_addr
.sa_len
;
613 #endif /* HAVE_MINIMUM_IFREQ */
614 #elif defined SIOCGIFCONF_ADDR
615 cpsize
= sizeof(lifreq
);
617 cpsize
= sizeof(lifreq
.lifr_name
);
618 /* XXX maybe this should be a hard error? */
619 if (ioctl(s
, SIOCGLIFADDR
, (char *)&lifreq
) < 0)
622 switch (lifreq
.lifr_addr
.ss_family
) {
626 &((struct sockaddr_in
*)
627 &lifreq
.lifr_addr
)->sin_addr
,
629 if (in4
.s_addr
== INADDR_ANY
)
631 n
= ioctl(s
, SIOCGLIFFLAGS
, (char *)&lifreq
);
634 if ((lifreq
.lifr_flags
& IFF_UP
) == 0)
642 &((struct sockaddr_in6
*)
643 &lifreq
.lifr_addr
)->sin6_addr
,
645 if (memcmp(&in6
, &in6addr_any
,
648 n
= ioctl(s
, SIOCGLIFFLAGS
, (char *)&lifreq
);
651 if ((lifreq
.lifr_flags
& IFF_UP
) == 0)
672 scan_interfaces(int *have_v4
, int *have_v6
) {
673 #if !defined(SIOCGIFCONF) || !defined(SIOCGIFADDR)
674 *have_v4
= *have_v6
= 1;
679 char _pad
[256]; /* leave space for IPv6 addresses */
684 char *buf
= NULL
, *cp
, *cplim
;
685 static unsigned int bufsiz
= 4095;
692 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
693 !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF)
695 * Try to scan the interfaces using IPv6 ioctls().
697 if (!scan_interfaces6(have_v4
, have_v6
)) {
706 * Set to zero. Used as loop terminators below.
708 *have_v4
= *have_v6
= 0;
711 * Get interface list from system.
713 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
717 * Grow buffer until large enough to contain all interface
721 buf
= malloc(bufsiz
);
724 ifc
.ifc_len
= bufsiz
;
726 #ifdef IRIX_EMUL_IOCTL_SIOCGIFCONF
728 * This is a fix for IRIX OS in which the call to ioctl with
729 * the flag SIOCGIFCONF may not return an entry for all the
730 * interfaces like most flavors of Unix.
732 if (emul_ioctl(&ifc
) >= 0)
735 if ((n
= ioctl(s
, SIOCGIFCONF
, (char *)&ifc
)) != -1) {
737 * Some OS's just return what will fit rather
738 * than set EINVAL if the buffer is too small
739 * to fit all the interfaces in. If
740 * ifc.ifc_len is too near to the end of the
741 * buffer we will grow it just in case and
744 if (ifc
.ifc_len
+ 2 * sizeof(u
.ifreq
) < bufsiz
)
748 if ((n
== -1) && errno
!= EINVAL
)
751 if (bufsiz
> 1000000)
759 * Parse system's interface list.
761 cplim
= buf
+ ifc
.ifc_len
; /* skip over if's with big ifr_addr's */
763 (*have_v4
== 0 || *have_v6
== 0) && cp
< cplim
;
765 memmove(&u
.ifreq
, cp
, sizeof(u
.ifreq
));
766 #ifdef LWRES_PLATFORM_HAVESALEN
767 #ifdef FIX_ZERO_SA_LEN
768 if (u
.ifreq
.ifr_addr
.sa_len
== 0)
769 u
.ifreq
.ifr_addr
.sa_len
= 16;
771 #ifdef HAVE_MINIMUM_IFREQ
772 cpsize
= sizeof(u
.ifreq
);
773 if (u
.ifreq
.ifr_addr
.sa_len
> sizeof(struct sockaddr
))
774 cpsize
+= (int)u
.ifreq
.ifr_addr
.sa_len
-
775 (int)(sizeof(struct sockaddr
));
777 cpsize
= sizeof(u
.ifreq
.ifr_name
) + u
.ifreq
.ifr_addr
.sa_len
;
778 #endif /* HAVE_MINIMUM_IFREQ */
779 if (cpsize
> sizeof(u
.ifreq
) && cpsize
<= sizeof(u
))
780 memmove(&u
.ifreq
, cp
, cpsize
);
781 #elif defined SIOCGIFCONF_ADDR
782 cpsize
= sizeof(u
.ifreq
);
784 cpsize
= sizeof(u
.ifreq
.ifr_name
);
785 /* XXX maybe this should be a hard error? */
786 if (ioctl(s
, SIOCGIFADDR
, (char *)&u
.ifreq
) < 0)
789 switch (u
.ifreq
.ifr_addr
.sa_family
) {
793 &((struct sockaddr_in
*)
794 &u
.ifreq
.ifr_addr
)->sin_addr
,
796 if (in4
.s_addr
== INADDR_ANY
)
798 n
= ioctl(s
, SIOCGIFFLAGS
, (char *)&u
.ifreq
);
801 if ((u
.ifreq
.ifr_flags
& IFF_UP
) == 0)
809 &((struct sockaddr_in6
*)
810 &u
.ifreq
.ifr_addr
)->sin6_addr
,
812 if (memcmp(&in6
, &in6addr_any
,
815 n
= ioctl(s
, SIOCGIFFLAGS
, (char *)&u
.ifreq
);
818 if ((u
.ifreq
.ifr_flags
& IFF_UP
) == 0)
845 static struct hostent
*
846 copyandmerge(struct hostent
*he1
, struct hostent
*he2
, int af
, int *error_num
)
848 struct hostent
*he
= NULL
;
849 int addresses
= 1; /* NULL terminator */
850 int names
= 1; /* NULL terminator */
855 * Work out array sizes.
858 cpp
= he1
->h_addr_list
;
859 while (*cpp
!= NULL
) {
863 cpp
= he1
->h_aliases
;
864 while (*cpp
!= NULL
) {
871 cpp
= he2
->h_addr_list
;
872 while (*cpp
!= NULL
) {
877 cpp
= he2
->h_aliases
;
878 while (*cpp
!= NULL
) {
885 if (addresses
== 1) {
886 *error_num
= NO_ADDRESS
;
890 he
= malloc(sizeof(*he
));
894 he
->h_addr_list
= malloc(sizeof(char *) * (addresses
));
895 if (he
->h_addr_list
== NULL
)
897 memset(he
->h_addr_list
, 0, sizeof(char *) * (addresses
));
902 npp
= he
->h_addr_list
;
904 cpp
= he1
->h_addr_list
;
905 while (*cpp
!= NULL
) {
906 *npp
= malloc((af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
910 * Convert to mapped if required.
912 if (af
== AF_INET6
&& he1
->h_addrtype
== AF_INET
) {
913 memmove(*npp
, in6addr_mapped
,
914 sizeof(in6addr_mapped
));
915 memmove(*npp
+ sizeof(in6addr_mapped
), *cpp
,
919 (af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
927 cpp
= he2
->h_addr_list
;
928 while (*cpp
!= NULL
) {
929 *npp
= malloc((af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
933 * Convert to mapped if required.
935 if (af
== AF_INET6
&& he2
->h_addrtype
== AF_INET
) {
936 memmove(*npp
, in6addr_mapped
,
937 sizeof(in6addr_mapped
));
938 memmove(*npp
+ sizeof(in6addr_mapped
), *cpp
,
942 (af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
949 he
->h_aliases
= malloc(sizeof(char *) * (names
));
950 if (he
->h_aliases
== NULL
)
952 memset(he
->h_aliases
, 0, sizeof(char *) * (names
));
958 cpp
= (he1
!= NULL
) ? he1
->h_aliases
959 : ((he2
!= NULL
) ? he2
->h_aliases
: NULL
);
960 while (cpp
!= NULL
&& *cpp
!= NULL
) {
961 len
= strlen (*cpp
) + 1;
973 he
->h_name
= malloc(strlen((he1
!= NULL
) ?
974 he1
->h_name
: he2
->h_name
) + 1);
975 if (he
->h_name
== NULL
)
977 strcpy(he
->h_name
, (he1
!= NULL
) ? he1
->h_name
: he2
->h_name
);
980 * Set address type and length.
983 he
->h_length
= (af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
;
988 while (*cpp
!= NULL
) {
995 cpp
= he
->h_addr_list
;
996 while (*cpp
!= NULL
) {
1001 free(he
->h_addr_list
);
1007 *error_num
= NO_RECOVERY
;
1011 static struct hostent
*
1012 hostfromaddr(lwres_gnbaresponse_t
*addr
, int af
, const void *src
) {
1016 he
= malloc(sizeof(*he
));
1019 memset(he
, 0, sizeof(*he
));
1022 * Set family and length.
1024 he
->h_addrtype
= af
;
1027 he
->h_length
= INADDRSZ
;
1030 he
->h_length
= IN6ADDRSZ
;
1039 he
->h_name
= strdup(addr
->realname
);
1040 if (he
->h_name
== NULL
)
1046 he
->h_aliases
= malloc(sizeof(char *) * (addr
->naliases
+ 1));
1047 if (he
->h_aliases
== NULL
)
1049 for (i
= 0; i
< addr
->naliases
; i
++) {
1050 he
->h_aliases
[i
] = strdup(addr
->aliases
[i
]);
1051 if (he
->h_aliases
[i
] == NULL
)
1054 he
->h_aliases
[i
] = NULL
;
1059 he
->h_addr_list
= malloc(sizeof(char *) * 2);
1060 if (he
->h_addr_list
== NULL
)
1062 he
->h_addr_list
[0] = malloc(he
->h_length
);
1063 if (he
->h_addr_list
[0] == NULL
)
1065 memmove(he
->h_addr_list
[0], src
, he
->h_length
);
1066 he
->h_addr_list
[1] = NULL
;
1070 if (he
!= NULL
&& he
->h_addr_list
!= NULL
) {
1071 for (i
= 0; he
->h_addr_list
[i
] != NULL
; i
++)
1072 free(he
->h_addr_list
[i
]);
1073 free(he
->h_addr_list
);
1075 if (he
!= NULL
&& he
->h_aliases
!= NULL
) {
1076 for (i
= 0; he
->h_aliases
[i
] != NULL
; i
++)
1077 free(he
->h_aliases
[i
]);
1078 free(he
->h_aliases
);
1080 if (he
!= NULL
&& he
->h_name
!= NULL
)
1087 static struct hostent
*
1088 hostfromname(lwres_gabnresponse_t
*name
, int af
) {
1093 he
= malloc(sizeof(*he
));
1096 memset(he
, 0, sizeof(*he
));
1099 * Set family and length.
1101 he
->h_addrtype
= af
;
1104 he
->h_length
= INADDRSZ
;
1107 he
->h_length
= IN6ADDRSZ
;
1116 he
->h_name
= strdup(name
->realname
);
1117 if (he
->h_name
== NULL
)
1123 he
->h_aliases
= malloc(sizeof(char *) * (name
->naliases
+ 1));
1124 if (he
->h_aliases
== NULL
)
1126 for (i
= 0; i
< name
->naliases
; i
++) {
1127 he
->h_aliases
[i
] = strdup(name
->aliases
[i
]);
1128 if (he
->h_aliases
[i
] == NULL
)
1131 he
->h_aliases
[i
] = NULL
;
1136 he
->h_addr_list
= malloc(sizeof(char *) * (name
->naddrs
+ 1));
1137 if (he
->h_addr_list
== NULL
)
1139 addr
= LWRES_LIST_HEAD(name
->addrs
);
1141 while (addr
!= NULL
) {
1142 he
->h_addr_list
[i
] = malloc(he
->h_length
);
1143 if (he
->h_addr_list
[i
] == NULL
)
1145 memmove(he
->h_addr_list
[i
], addr
->address
, he
->h_length
);
1146 addr
= LWRES_LIST_NEXT(addr
, link
);
1149 he
->h_addr_list
[i
] = NULL
;
1153 if (he
!= NULL
&& he
->h_addr_list
!= NULL
) {
1154 for (i
= 0; he
->h_addr_list
[i
] != NULL
; i
++)
1155 free(he
->h_addr_list
[i
]);
1156 free(he
->h_addr_list
);
1158 if (he
!= NULL
&& he
->h_aliases
!= NULL
) {
1159 for (i
= 0; he
->h_aliases
[i
] != NULL
; i
++)
1160 free(he
->h_aliases
[i
]);
1161 free(he
->h_aliases
);
1163 if (he
!= NULL
&& he
->h_name
!= NULL
)