2 * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or 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 WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: getipnode.c,v 1.42.128.3 2009/09/01 23:46:36 tbox Exp $ */
23 * These functions perform thread safe, protocol independent
24 * nodename-to-address and address-to-nodename translation as defined in
25 * RFC2553. This use a struct hostent which is defined in namedb.h:
29 * char *h_name; // official name of host
30 * char **h_aliases; // alias list
31 * int h_addrtype; // host address type
32 * int h_length; // length of address
33 * char **h_addr_list; // list of addresses from name server
35 * #define h_addr h_addr_list[0] // address, for backward compatibility
38 * The members of this structure are:
41 * The official (canonical) name of the host.
44 * A NULL-terminated array of alternate names (nicknames) for the
48 * The type of address being returned - usually PF_INET or
52 * The length of the address in bytes.
55 * A NULL terminated array of network addresses for the host. Host
56 * addresses are returned in network byte order.
58 * lwres_getipnodebyname() looks up addresses of protocol family af for
59 * the hostname name. The flags parameter contains ORed flag bits to
60 * specify the types of addresses that are searched for, and the types of
61 * addresses that are returned. The flag bits are:
64 * This is used with an af of #AF_INET6, and causes IPv4 addresses
65 * to be returned as IPv4-mapped IPv6 addresses.
68 * This is used with an af of #AF_INET6, and causes all known
69 * addresses (IPv6 and IPv4) to be returned. If #AI_V4MAPPED is
70 * also set, the IPv4 addresses are return as mapped IPv6
74 * Only return an IPv6 or IPv4 address if here is an active
75 * network interface of that type. This is not currently
76 * implemented in the BIND 9 lightweight resolver, and the flag is
80 * This default sets the #AI_V4MAPPED and #AI_ADDRCONFIG flag bits.
82 * lwres_getipnodebyaddr() performs a reverse lookup of address src which
83 * is len bytes long. af denotes the protocol family, typically PF_INET
86 * lwres_freehostent() releases all the memory associated with the struct
87 * hostent pointer. Any memory allocated for the h_name, h_addr_list
88 * and h_aliases is freed, as is the memory for the hostent structure
91 * \section getipnode_return Return Values
93 * If an error occurs, lwres_getipnodebyname() and
94 * lwres_getipnodebyaddr() set *error_num to an appropriate error code
95 * and the function returns a NULL pointer. The error codes and their
96 * meanings are defined in \link netdb.h <lwres/netdb.h>\endlink:
98 * \li #HOST_NOT_FOUND:
99 * No such host is known.
102 * The server recognised the request and the name but no address
103 * is available. Another type of request to the name server for
104 * the domain might return an answer.
107 * A temporary and possibly transient error occurred, such as a
108 * failure of a server to respond. The request may succeed if
112 * An unexpected failure occurred, and retrying the request is
115 * lwres_hstrerror() translates these error codes to suitable error
118 * \section getipnode_see See Also
120 * getaddrinfo.c, gethost.c, getnameinfo.c, herror.c, RFC2553
130 #include <lwres/lwres.h>
131 #include <lwres/net.h>
132 #include <lwres/netdb.h> /* XXX #include <netdb.h> */
134 #include "assert_p.h"
143 #ifdef LWRES_PLATFORM_NEEDIN6ADDRANY
144 LIBLWRES_EXTERNAL_DATA
const struct in6_addr in6addr_any
= IN6ADDR_ANY_INIT
;
147 #ifndef IN6_IS_ADDR_V4COMPAT
148 static const unsigned char in6addr_compat
[12] = {
149 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
151 #define IN6_IS_ADDR_V4COMPAT(x) (!memcmp((x)->s6_addr, in6addr_compat, 12) && \
152 ((x)->s6_addr[12] != 0 || \
153 (x)->s6_addr[13] != 0 || \
154 (x)->s6_addr[14] != 0 || \
155 ((x)->s6_addr[15] != 0 && \
156 (x)->s6_addr[15] != 1)))
158 #ifndef IN6_IS_ADDR_V4MAPPED
159 #define IN6_IS_ADDR_V4MAPPED(x) (!memcmp((x)->s6_addr, in6addr_mapped, 12))
162 static const unsigned char in6addr_mapped
[12] = {
163 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff
167 *** Forward declarations.
171 scan_interfaces(int *, int *);
173 static struct hostent
*
174 copyandmerge(struct hostent
*, struct hostent
*, int, int *);
176 static struct hostent
*
177 hostfromaddr(lwres_gnbaresponse_t
*addr
, int af
, const void *src
);
179 static struct hostent
*
180 hostfromname(lwres_gabnresponse_t
*name
, int af
);
183 *** Public functions.
187 * AI_V4MAPPED + AF_INET6
188 * If no IPv6 address then a query for IPv4 and map returned values.
190 * AI_ALL + AI_V4MAPPED + AF_INET6
191 * Return IPv6 and IPv4 mapped.
194 * Only return IPv6 / IPv4 address if there is an interface of that
199 lwres_getipnodebyname(const char *name
, int af
, int flags
, int *error_num
) {
200 int have_v4
= 1, have_v6
= 1;
203 struct hostent he
, *he1
= NULL
, *he2
= NULL
, *he3
= NULL
;
206 lwres_context_t
*lwrctx
= NULL
;
207 lwres_gabnresponse_t
*by
= NULL
;
211 * If we care about active interfaces then check.
213 if ((flags
& AI_ADDRCONFIG
) != 0)
214 if (scan_interfaces(&have_v4
, &have_v6
) == -1) {
215 *error_num
= NO_RECOVERY
;
219 /* Check for literal address. */
220 if ((v4
= lwres_net_pton(AF_INET
, name
, &in4
)) != 1)
221 v6
= lwres_net_pton(AF_INET6
, name
, &in6
);
224 * Impossible combination?
226 if ((af
== AF_INET6
&& (flags
& AI_V4MAPPED
) == 0 && v4
== 1) ||
227 (af
== AF_INET
&& v6
== 1) ||
228 (have_v4
== 0 && v4
== 1) ||
229 (have_v6
== 0 && v6
== 1) ||
230 (have_v4
== 0 && af
== AF_INET
) ||
231 (have_v6
== 0 && af
== AF_INET6
&&
232 (((flags
& AI_V4MAPPED
) != 0 && have_v4
) ||
233 (flags
& AI_V4MAPPED
) == 0))) {
234 *error_num
= HOST_NOT_FOUND
;
241 if (v4
== 1 || v6
== 1) {
244 char mappedname
[sizeof("::ffff:123.123.123.123")];
246 const char *const_name
;
251 if (v4
== 1 && af
== AF_INET6
) {
252 strcpy(mappedname
, "::ffff:");
253 lwres_net_ntop(AF_INET
, (char *)&in4
,
254 mappedname
+ sizeof("::ffff:") - 1,
255 sizeof(mappedname
) - sizeof("::ffff:")
257 he
.h_name
= mappedname
;
259 he
.h_name
= u
.deconst_name
;
260 he
.h_addr_list
= addr_list
;
261 he
.h_addr_list
[0] = (v4
== 1) ? (char *)&in4
: (char *)&in6
;
262 he
.h_addr_list
[1] = NULL
;
263 he
.h_aliases
= aliases
;
264 he
.h_aliases
[0] = NULL
;
265 he
.h_length
= (v4
== 1) ? INADDRSZ
: IN6ADDRSZ
;
266 he
.h_addrtype
= (v4
== 1) ? AF_INET
: AF_INET6
;
267 return (copyandmerge(&he
, NULL
, af
, error_num
));
270 n
= lwres_context_create(&lwrctx
, NULL
, NULL
, NULL
, 0);
272 *error_num
= NO_RECOVERY
;
275 (void) lwres_conf_parse(lwrctx
, lwres_resolv_conf
);
276 tmp_err
= NO_RECOVERY
;
277 if (have_v6
&& af
== AF_INET6
) {
279 n
= lwres_getaddrsbyname(lwrctx
, name
, LWRES_ADDRTYPE_V6
, &by
);
281 he1
= hostfromname(by
, AF_INET6
);
282 lwres_gabnresponse_free(lwrctx
, &by
);
284 *error_num
= NO_RECOVERY
;
288 tmp_err
= HOST_NOT_FOUND
;
294 (af
== AF_INET6
&& (flags
& AI_V4MAPPED
) != 0 &&
295 (he1
== NULL
|| (flags
& AI_ALL
) != 0)))) {
296 n
= lwres_getaddrsbyname(lwrctx
, name
, LWRES_ADDRTYPE_V4
, &by
);
298 he2
= hostfromname(by
, AF_INET
);
299 lwres_gabnresponse_free(lwrctx
, &by
);
301 *error_num
= NO_RECOVERY
;
304 } else if (he1
== NULL
) {
305 if (n
== LWRES_R_NOTFOUND
)
306 *error_num
= HOST_NOT_FOUND
;
308 *error_num
= NO_RECOVERY
;
312 *error_num
= tmp_err
;
314 he3
= copyandmerge(he1
, he2
, af
, error_num
);
318 lwres_freehostent(he1
);
320 lwres_freehostent(he2
);
321 if (lwrctx
!= NULL
) {
322 lwres_conf_clear(lwrctx
);
323 lwres_context_destroy(&lwrctx
);
328 /*% performs a reverse lookup of address src which is len bytes long. af denotes the protocol family, typically #PF_INET or PF_INET6. */
330 lwres_getipnodebyaddr(const void *src
, size_t len
, int af
, int *error_num
) {
331 struct hostent
*he1
, *he2
;
332 lwres_context_t
*lwrctx
= NULL
;
333 lwres_gnbaresponse_t
*by
= NULL
;
337 struct in6_addr
*in6
;
344 *error_num
= NO_RECOVERY
;
350 if (len
!= (unsigned int)INADDRSZ
) {
351 *error_num
= NO_RECOVERY
;
356 if (len
!= (unsigned int)IN6ADDRSZ
) {
357 *error_num
= NO_RECOVERY
;
362 *error_num
= NO_RECOVERY
;
367 * The de-"const"-ing game is done because at least one
368 * vendor's system (RedHat 6.0) defines the IN6_IS_ADDR_*
369 * macros in such a way that they discard the const with
370 * internal casting, and gcc ends up complaining. Rather
371 * than replacing their own (possibly optimized) definitions
372 * with our own, cleanly discarding the const is the easiest
378 * Look up IPv4 and IPv4 mapped/compatible addresses.
380 if ((af
== AF_INET6
&& IN6_IS_ADDR_V4COMPAT(u
.in6
)) ||
381 (af
== AF_INET6
&& IN6_IS_ADDR_V4MAPPED(u
.in6
)) ||
383 const unsigned char *cp
= src
;
387 n
= lwres_context_create(&lwrctx
, NULL
, NULL
, NULL
, 0);
388 if (n
== LWRES_R_SUCCESS
)
389 (void) lwres_conf_parse(lwrctx
, lwres_resolv_conf
);
390 if (n
== LWRES_R_SUCCESS
)
391 n
= lwres_getnamebyaddr(lwrctx
, LWRES_ADDRTYPE_V4
,
393 if (n
!= LWRES_R_SUCCESS
) {
394 lwres_conf_clear(lwrctx
);
395 lwres_context_destroy(&lwrctx
);
396 if (n
== LWRES_R_NOTFOUND
)
397 *error_num
= HOST_NOT_FOUND
;
399 *error_num
= NO_RECOVERY
;
402 he1
= hostfromaddr(by
, AF_INET
, cp
);
403 lwres_gnbaresponse_free(lwrctx
, &by
);
404 lwres_conf_clear(lwrctx
);
405 lwres_context_destroy(&lwrctx
);
410 * Convert from AF_INET to AF_INET6.
412 he2
= copyandmerge(he1
, NULL
, af
, error_num
);
413 lwres_freehostent(he1
);
417 * Restore original address.
419 memcpy(he2
->h_addr
, src
, len
);
424 * Lookup IPv6 address.
426 if (memcmp(src
, &in6addr_any
, IN6ADDRSZ
) == 0) {
427 *error_num
= HOST_NOT_FOUND
;
431 n
= lwres_context_create(&lwrctx
, NULL
, NULL
, NULL
, 0);
432 if (n
== LWRES_R_SUCCESS
)
433 (void) lwres_conf_parse(lwrctx
, lwres_resolv_conf
);
434 if (n
== LWRES_R_SUCCESS
)
435 n
= lwres_getnamebyaddr(lwrctx
, LWRES_ADDRTYPE_V6
, IN6ADDRSZ
,
438 lwres_conf_clear(lwrctx
);
439 lwres_context_destroy(&lwrctx
);
440 *error_num
= HOST_NOT_FOUND
;
443 he1
= hostfromaddr(by
, AF_INET6
, src
);
444 lwres_gnbaresponse_free(lwrctx
, &by
);
446 *error_num
= NO_RECOVERY
;
447 lwres_conf_clear(lwrctx
);
448 lwres_context_destroy(&lwrctx
);
452 /*% releases all the memory associated with the struct hostent pointer */
454 lwres_freehostent(struct hostent
*he
) {
461 cpp
= he
->h_addr_list
;
462 while (*cpp
!= NULL
) {
470 while (*cpp
!= NULL
) {
477 free(he
->h_addr_list
);
486 * Scan the interface table and set have_v4 and have_v6 depending
487 * upon whether there are IPv4 and IPv6 interface addresses.
494 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
495 !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF)
498 #define lifc_len iflc_len
499 #define lifc_buf iflc_buf
500 #define lifc_req iflc_req
501 #define LIFCONF if_laddrconf
503 #define ISC_HAVE_LIFC_FAMILY 1
504 #define ISC_HAVE_LIFC_FLAGS 1
505 #define LIFCONF lifconf
509 #define lifr_addr iflr_addr
510 #define lifr_name iflr_name
511 #define lifr_dstaddr iflr_dstaddr
512 #define lifr_flags iflr_flags
513 #define ss_family sa_family
514 #define LIFREQ if_laddrreq
516 #define LIFREQ lifreq
520 scan_interfaces6(int *have_v4
, int *have_v6
) {
522 struct LIFREQ lifreq
;
525 char *buf
= NULL
, *cp
, *cplim
;
526 static unsigned int bufsiz
= 4095;
530 * Set to zero. Used as loop terminators below.
532 *have_v4
= *have_v6
= 0;
535 * Get interface list from system.
537 if ((s
= socket(AF_INET6
, SOCK_DGRAM
, 0)) == -1)
541 * Grow buffer until large enough to contain all interface
545 buf
= malloc(bufsiz
);
548 #ifdef ISC_HAVE_LIFC_FAMILY
549 lifc
.lifc_family
= AF_UNSPEC
; /* request all families */
551 #ifdef ISC_HAVE_LIFC_FLAGS
554 lifc
.lifc_len
= bufsiz
;
556 if ((n
= ioctl(s
, SIOCGLIFCONF
, (char *)&lifc
)) != -1) {
558 * Some OS's just return what will fit rather
559 * than set EINVAL if the buffer is too small
560 * to fit all the interfaces in. If
561 * lifc.lifc_len is too near to the end of the
562 * buffer we will grow it just in case and
565 if (lifc
.lifc_len
+ 2 * sizeof(lifreq
) < bufsiz
)
568 if ((n
== -1) && errno
!= EINVAL
)
571 if (bufsiz
> 1000000)
579 * Parse system's interface list.
581 cplim
= buf
+ lifc
.lifc_len
; /* skip over if's with big ifr_addr's */
583 (*have_v4
== 0 || *have_v6
== 0) && cp
< cplim
;
585 memcpy(&lifreq
, cp
, sizeof(lifreq
));
586 #ifdef LWRES_PLATFORM_HAVESALEN
587 #ifdef FIX_ZERO_SA_LEN
588 if (lifreq
.lifr_addr
.sa_len
== 0)
589 lifreq
.lifr_addr
.sa_len
= 16;
591 #ifdef HAVE_MINIMUM_IFREQ
592 cpsize
= sizeof(lifreq
);
593 if (lifreq
.lifr_addr
.sa_len
> sizeof(struct sockaddr
))
594 cpsize
+= (int)lifreq
.lifr_addr
.sa_len
-
595 (int)(sizeof(struct sockaddr
));
597 cpsize
= sizeof(lifreq
.lifr_name
) + lifreq
.lifr_addr
.sa_len
;
598 #endif /* HAVE_MINIMUM_IFREQ */
599 #elif defined SIOCGIFCONF_ADDR
600 cpsize
= sizeof(lifreq
);
602 cpsize
= sizeof(lifreq
.lifr_name
);
603 /* XXX maybe this should be a hard error? */
604 if (ioctl(s
, SIOCGLIFADDR
, (char *)&lifreq
) < 0)
607 switch (lifreq
.lifr_addr
.ss_family
) {
611 &((struct sockaddr_in
*)
612 &lifreq
.lifr_addr
)->sin_addr
,
614 if (in4
.s_addr
== INADDR_ANY
)
616 n
= ioctl(s
, SIOCGLIFFLAGS
, (char *)&lifreq
);
619 if ((lifreq
.lifr_flags
& IFF_UP
) == 0)
627 &((struct sockaddr_in6
*)
628 &lifreq
.lifr_addr
)->sin6_addr
,
630 if (memcmp(&in6
, &in6addr_any
,
633 n
= ioctl(s
, SIOCGLIFFLAGS
, (char *)&lifreq
);
636 if ((lifreq
.lifr_flags
& IFF_UP
) == 0)
657 scan_interfaces(int *have_v4
, int *have_v6
) {
658 #if !defined(SIOCGIFCONF) || !defined(SIOCGIFADDR)
659 *have_v4
= *have_v6
= 1;
664 char _pad
[256]; /* leave space for IPv6 addresses */
669 char *buf
= NULL
, *cp
, *cplim
;
670 static unsigned int bufsiz
= 4095;
677 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
678 !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF)
680 * Try to scan the interfaces using IPv6 ioctls().
682 if (!scan_interfaces6(have_v4
, have_v6
)) {
691 * Set to zero. Used as loop terminators below.
693 *have_v4
= *have_v6
= 0;
696 * Get interface list from system.
698 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
702 * Grow buffer until large enough to contain all interface
706 buf
= malloc(bufsiz
);
709 ifc
.ifc_len
= bufsiz
;
711 #ifdef IRIX_EMUL_IOCTL_SIOCGIFCONF
713 * This is a fix for IRIX OS in which the call to ioctl with
714 * the flag SIOCGIFCONF may not return an entry for all the
715 * interfaces like most flavors of Unix.
717 if (emul_ioctl(&ifc
) >= 0)
720 if ((n
= ioctl(s
, SIOCGIFCONF
, (char *)&ifc
)) != -1) {
722 * Some OS's just return what will fit rather
723 * than set EINVAL if the buffer is too small
724 * to fit all the interfaces in. If
725 * ifc.ifc_len is too near to the end of the
726 * buffer we will grow it just in case and
729 if (ifc
.ifc_len
+ 2 * sizeof(u
.ifreq
) < bufsiz
)
733 if ((n
== -1) && errno
!= EINVAL
)
736 if (bufsiz
> 1000000)
744 * Parse system's interface list.
746 cplim
= buf
+ ifc
.ifc_len
; /* skip over if's with big ifr_addr's */
748 (*have_v4
== 0 || *have_v6
== 0) && cp
< cplim
;
750 memcpy(&u
.ifreq
, cp
, sizeof(u
.ifreq
));
751 #ifdef LWRES_PLATFORM_HAVESALEN
752 #ifdef FIX_ZERO_SA_LEN
753 if (u
.ifreq
.ifr_addr
.sa_len
== 0)
754 u
.ifreq
.ifr_addr
.sa_len
= 16;
756 #ifdef HAVE_MINIMUM_IFREQ
757 cpsize
= sizeof(u
.ifreq
);
758 if (u
.ifreq
.ifr_addr
.sa_len
> sizeof(struct sockaddr
))
759 cpsize
+= (int)u
.ifreq
.ifr_addr
.sa_len
-
760 (int)(sizeof(struct sockaddr
));
762 cpsize
= sizeof(u
.ifreq
.ifr_name
) + u
.ifreq
.ifr_addr
.sa_len
;
763 #endif /* HAVE_MINIMUM_IFREQ */
764 if (cpsize
> sizeof(u
.ifreq
) && cpsize
<= sizeof(u
))
765 memcpy(&u
.ifreq
, cp
, cpsize
);
766 #elif defined SIOCGIFCONF_ADDR
767 cpsize
= sizeof(u
.ifreq
);
769 cpsize
= sizeof(u
.ifreq
.ifr_name
);
770 /* XXX maybe this should be a hard error? */
771 if (ioctl(s
, SIOCGIFADDR
, (char *)&u
.ifreq
) < 0)
774 switch (u
.ifreq
.ifr_addr
.sa_family
) {
778 &((struct sockaddr_in
*)
779 &u
.ifreq
.ifr_addr
)->sin_addr
,
781 if (in4
.s_addr
== INADDR_ANY
)
783 n
= ioctl(s
, SIOCGIFFLAGS
, (char *)&u
.ifreq
);
786 if ((u
.ifreq
.ifr_flags
& IFF_UP
) == 0)
794 &((struct sockaddr_in6
*)
795 &u
.ifreq
.ifr_addr
)->sin6_addr
,
797 if (memcmp(&in6
, &in6addr_any
,
800 n
= ioctl(s
, SIOCGIFFLAGS
, (char *)&u
.ifreq
);
803 if ((u
.ifreq
.ifr_flags
& IFF_UP
) == 0)
830 static struct hostent
*
831 copyandmerge(struct hostent
*he1
, struct hostent
*he2
, int af
, int *error_num
)
833 struct hostent
*he
= NULL
;
834 int addresses
= 1; /* NULL terminator */
835 int names
= 1; /* NULL terminator */
840 * Work out array sizes.
843 cpp
= he1
->h_addr_list
;
844 while (*cpp
!= NULL
) {
848 cpp
= he1
->h_aliases
;
849 while (*cpp
!= NULL
) {
856 cpp
= he2
->h_addr_list
;
857 while (*cpp
!= NULL
) {
862 cpp
= he2
->h_aliases
;
863 while (*cpp
!= NULL
) {
870 if (addresses
== 1) {
871 *error_num
= NO_ADDRESS
;
875 he
= malloc(sizeof(*he
));
879 he
->h_addr_list
= malloc(sizeof(char *) * (addresses
));
880 if (he
->h_addr_list
== NULL
)
882 memset(he
->h_addr_list
, 0, sizeof(char *) * (addresses
));
887 npp
= he
->h_addr_list
;
889 cpp
= he1
->h_addr_list
;
890 while (*cpp
!= NULL
) {
891 *npp
= malloc((af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
895 * Convert to mapped if required.
897 if (af
== AF_INET6
&& he1
->h_addrtype
== AF_INET
) {
898 memcpy(*npp
, in6addr_mapped
,
899 sizeof(in6addr_mapped
));
900 memcpy(*npp
+ sizeof(in6addr_mapped
), *cpp
,
904 (af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
912 cpp
= he2
->h_addr_list
;
913 while (*cpp
!= NULL
) {
914 *npp
= malloc((af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
918 * Convert to mapped if required.
920 if (af
== AF_INET6
&& he2
->h_addrtype
== AF_INET
) {
921 memcpy(*npp
, in6addr_mapped
,
922 sizeof(in6addr_mapped
));
923 memcpy(*npp
+ sizeof(in6addr_mapped
), *cpp
,
927 (af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
);
934 he
->h_aliases
= malloc(sizeof(char *) * (names
));
935 if (he
->h_aliases
== NULL
)
937 memset(he
->h_aliases
, 0, sizeof(char *) * (names
));
943 cpp
= (he1
!= NULL
) ? he1
->h_aliases
: he2
->h_aliases
;
944 while (*cpp
!= NULL
) {
945 len
= strlen (*cpp
) + 1;
957 he
->h_name
= malloc(strlen((he1
!= NULL
) ?
958 he1
->h_name
: he2
->h_name
) + 1);
959 if (he
->h_name
== NULL
)
961 strcpy(he
->h_name
, (he1
!= NULL
) ? he1
->h_name
: he2
->h_name
);
964 * Set address type and length.
967 he
->h_length
= (af
== AF_INET
) ? INADDRSZ
: IN6ADDRSZ
;
972 while (*cpp
!= NULL
) {
979 cpp
= he
->h_addr_list
;
980 while (*cpp
!= NULL
) {
985 free(he
->h_addr_list
);
991 *error_num
= NO_RECOVERY
;
995 static struct hostent
*
996 hostfromaddr(lwres_gnbaresponse_t
*addr
, int af
, const void *src
) {
1000 he
= malloc(sizeof(*he
));
1003 memset(he
, 0, sizeof(*he
));
1006 * Set family and length.
1008 he
->h_addrtype
= af
;
1011 he
->h_length
= INADDRSZ
;
1014 he
->h_length
= IN6ADDRSZ
;
1023 he
->h_name
= strdup(addr
->realname
);
1024 if (he
->h_name
== NULL
)
1030 he
->h_aliases
= malloc(sizeof(char *) * (addr
->naliases
+ 1));
1031 if (he
->h_aliases
== NULL
)
1033 for (i
= 0; i
< addr
->naliases
; i
++) {
1034 he
->h_aliases
[i
] = strdup(addr
->aliases
[i
]);
1035 if (he
->h_aliases
[i
] == NULL
)
1038 he
->h_aliases
[i
] = NULL
;
1043 he
->h_addr_list
= malloc(sizeof(char *) * 2);
1044 if (he
->h_addr_list
== NULL
)
1046 he
->h_addr_list
[0] = malloc(he
->h_length
);
1047 if (he
->h_addr_list
[0] == NULL
)
1049 memcpy(he
->h_addr_list
[0], src
, he
->h_length
);
1050 he
->h_addr_list
[1] = NULL
;
1054 if (he
!= NULL
&& he
->h_addr_list
!= NULL
) {
1055 for (i
= 0; he
->h_addr_list
[i
] != NULL
; i
++)
1056 free(he
->h_addr_list
[i
]);
1057 free(he
->h_addr_list
);
1059 if (he
!= NULL
&& he
->h_aliases
!= NULL
) {
1060 for (i
= 0; he
->h_aliases
[i
] != NULL
; i
++)
1061 free(he
->h_aliases
[i
]);
1062 free(he
->h_aliases
);
1064 if (he
!= NULL
&& he
->h_name
!= NULL
)
1071 static struct hostent
*
1072 hostfromname(lwres_gabnresponse_t
*name
, int af
) {
1077 he
= malloc(sizeof(*he
));
1080 memset(he
, 0, sizeof(*he
));
1083 * Set family and length.
1085 he
->h_addrtype
= af
;
1088 he
->h_length
= INADDRSZ
;
1091 he
->h_length
= IN6ADDRSZ
;
1100 he
->h_name
= strdup(name
->realname
);
1101 if (he
->h_name
== NULL
)
1107 he
->h_aliases
= malloc(sizeof(char *) * (name
->naliases
+ 1));
1108 for (i
= 0; i
< name
->naliases
; i
++) {
1109 he
->h_aliases
[i
] = strdup(name
->aliases
[i
]);
1110 if (he
->h_aliases
[i
] == NULL
)
1113 he
->h_aliases
[i
] = NULL
;
1118 he
->h_addr_list
= malloc(sizeof(char *) * (name
->naddrs
+ 1));
1119 addr
= LWRES_LIST_HEAD(name
->addrs
);
1121 while (addr
!= NULL
) {
1122 he
->h_addr_list
[i
] = malloc(he
->h_length
);
1123 if (he
->h_addr_list
[i
] == NULL
)
1125 memcpy(he
->h_addr_list
[i
], addr
->address
, he
->h_length
);
1126 addr
= LWRES_LIST_NEXT(addr
, link
);
1129 he
->h_addr_list
[i
] = NULL
;
1133 if (he
!= NULL
&& he
->h_addr_list
!= NULL
) {
1134 for (i
= 0; he
->h_addr_list
[i
] != NULL
; i
++)
1135 free(he
->h_addr_list
[i
]);
1136 free(he
->h_addr_list
);
1138 if (he
!= NULL
&& he
->h_aliases
!= NULL
) {
1139 for (i
= 0; he
->h_aliases
[i
] != NULL
; i
++)
1140 free(he
->h_aliases
[i
]);
1141 free(he
->h_aliases
);
1143 if (he
!= NULL
&& he
->h_name
!= NULL
)