getipnode.c revision 0c27b3fe77ac1d5094ba3521e8142d9e7973133f
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Copyright (C) 1999-2005, 2007, 2009, 2012, 2014, 2016 Internet Systems Consortium, Inc. ("ISC")
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
823ca3c14f1596341bdd50707c01f3b529b75b4aAutomatic Updater/* $Id: getipnode.c,v 1.47 2009/09/01 23:47:45 tbox Exp $ */
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * These functions perform thread safe, protocol independent
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * nodename-to-address and address-to-nodename translation as defined in
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * RFC2553. This use a struct hostent which is defined in namedb.h:
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * struct hostent {
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * char *h_name; // official name of host
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * char **h_aliases; // alias list
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * int h_addrtype; // host address type
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * int h_length; // length of address
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * char **h_addr_list; // list of addresses from name server
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * #define h_addr h_addr_list[0] // address, for backward compatibility
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * The members of this structure are:
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \li h_name:
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * The official (canonical) name of the host.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \li h_aliases:
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * A NULL-terminated array of alternate names (nicknames) for the
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \li h_addrtype:
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * The type of address being returned - usually PF_INET or
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \li h_length:
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * The length of the address in bytes.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \li h_addr_list:
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * A NULL terminated array of network addresses for the host. Host
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * addresses are returned in network byte order.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * lwres_getipnodebyname() looks up addresses of protocol family af for
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * the hostname name. The flags parameter contains ORed flag bits to
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * specify the types of addresses that are searched for, and the types of
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * addresses that are returned. The flag bits are:
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \li #AI_V4MAPPED:
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * This is used with an af of #AF_INET6, and causes IPv4 addresses
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * to be returned as IPv4-mapped IPv6 addresses.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \li #AI_ALL:
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * This is used with an af of #AF_INET6, and causes all known
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * addresses (IPv6 and IPv4) to be returned. If #AI_V4MAPPED is
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * also set, the IPv4 addresses are return as mapped IPv6
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * addresses.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \li #AI_ADDRCONFIG:
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * Only return an IPv6 or IPv4 address if here is an active
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * network interface of that type. This is not currently
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * implemented in the BIND 9 lightweight resolver, and the flag is
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \li #AI_DEFAULT:
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * This default sets the #AI_V4MAPPED and #AI_ADDRCONFIG flag bits.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * lwres_getipnodebyaddr() performs a reverse lookup of address src which
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * is len bytes long. af denotes the protocol family, typically PF_INET
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * or PF_INET6.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * lwres_freehostent() releases all the memory associated with the struct
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * hostent pointer. Any memory allocated for the h_name, h_addr_list
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * and h_aliases is freed, as is the memory for the hostent structure
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \section getipnode_return Return Values
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * If an error occurs, lwres_getipnodebyname() and
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * lwres_getipnodebyaddr() set *error_num to an appropriate error code
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * and the function returns a NULL pointer. The error codes and their
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * meanings are defined in \link netdb.h <lwres/netdb.h>\endlink:
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \li #HOST_NOT_FOUND:
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * No such host is known.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \li #NO_ADDRESS:
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * The server recognised the request and the name but no address
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * is available. Another type of request to the name server for
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * the domain might return an answer.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \li #TRY_AGAIN:
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * A temporary and possibly transient error occurred, such as a
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * failure of a server to respond. The request may succeed if
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \li #NO_RECOVERY:
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * An unexpected failure occurred, and retrying the request is
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * pointless.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * lwres_hstrerror() translates these error codes to suitable error
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \section getipnode_see See Also
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater * getaddrinfo.c, gethost.c, getnameinfo.c, herror.c, RFC2553
37d266d288410d1ead241c02a8a1dbcb0160be46Michael Graff#include <lwres/netdb.h> /* XXX #include <netdb.h> */
5236050c0f819b727dfc4850133f5194f346f76fDanny MayerLIBLWRES_EXTERNAL_DATA const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsstatic const unsigned char in6addr_compat[12] = {
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#define IN6_IS_ADDR_V4COMPAT(x) (!memcmp((x)->s6_addr, in6addr_compat, 12) && \
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#define IN6_IS_ADDR_V4MAPPED(x) (!memcmp((x)->s6_addr, in6addr_mapped, 12))
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsstatic const unsigned char in6addr_mapped[12] = {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *** Forward declarations.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrencestatic struct hostent *
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrencecopyandmerge(struct hostent *, struct hostent *, int, int *);
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrencestatic struct hostent *
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrencehostfromaddr(lwres_gnbaresponse_t *addr, int af, const void *src);
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrencestatic struct hostent *
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrencehostfromname(lwres_gabnresponse_t *name, int af);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *** Public functions.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * AI_V4MAPPED + AF_INET6
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * If no IPv6 address then a query for IPv4 and map returned values.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * AI_ALL + AI_V4MAPPED + AF_INET6
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * Return IPv6 and IPv4 mapped.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * AI_ADDRCONFIG
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * Only return IPv6 / IPv4 address if there is an interface of that
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * type active.
af9cfbc64363b61aa5903dd916e9fbc152084d4cMark Andrewslwres_getipnodebyname(const char *name, int af, int flags, int *error_num) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews struct hostent he, *he1 = NULL, *he2 = NULL, *he3 = NULL;
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * If we care about active interfaces then check.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (scan_interfaces(&have_v4, &have_v6) == -1) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /* Check for literal address. */
35c842e05dc6382ce1d9161a658d3ff4b2c3d4c9Bob Halley if ((v4 = lwres_net_pton(AF_INET, name, &in4)) != 1)
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Impossible combination?
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if ((af == AF_INET6 && (flags & AI_V4MAPPED) == 0 && v4 == 1) ||
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Literal address?
bb6936058eb88eadff030462a347c10895c61a9aMark Andrews char mappedname[sizeof("::ffff:123.123.123.123")];
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he.h_addr_list[0] = (v4 == 1) ? (char *)&in4 : (char *)&in6;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he.h_length = (v4 == 1) ? INADDRSZ : IN6ADDRSZ;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he.h_addrtype = (v4 == 1) ? AF_INET : AF_INET6;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (copyandmerge(&he, NULL, af, error_num));
efe2f579ba6fbec4229129015780f2d925085b04Michael Graff n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
6add3af8397580475ab9fa10ac8c1269465cff87Mark Andrews if (n != 0) {
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington (void) lwres_conf_parse(lwrctx, lwres_resolv_conf);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews n = lwres_getaddrsbyname(lwrctx, name, LWRES_ADDRTYPE_V6, &by);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (n == 0) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews (af == AF_INET6 && (flags & AI_V4MAPPED) != 0 &&
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews n = lwres_getaddrsbyname(lwrctx, name, LWRES_ADDRTYPE_V4, &by);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (n == 0) {
823ca3c14f1596341bdd50707c01f3b529b75b4aAutomatic Updater he3 = copyandmerge(he1, he2, af, error_num);
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*% performs a reverse lookup of address src which is len bytes long. af denotes the protocol family, typically #PF_INET or PF_INET6. */
af9cfbc64363b61aa5903dd916e9fbc152084d4cMark Andrewslwres_getipnodebyaddr(const void *src, size_t len, int af, int *error_num) {
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Sanity checks.
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence * The de-"const"-ing game is done because at least one
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence * vendor's system (RedHat 6.0) defines the IN6_IS_ADDR_*
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence * macros in such a way that they discard the const with
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence * internal casting, and gcc ends up complaining. Rather
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence * than replacing their own (possibly optimized) definitions
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence * with our own, cleanly discarding the const is the easiest
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence * thing to do.
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence * Look up IPv4 and IPv4 mapped/compatible addresses.
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence if ((af == AF_INET6 && IN6_IS_ADDR_V4COMPAT(u.in6)) ||
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence (af == AF_INET6 && IN6_IS_ADDR_V4MAPPED(u.in6)) ||
efe2f579ba6fbec4229129015780f2d925085b04Michael Graff n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington (void) lwres_conf_parse(lwrctx, lwres_resolv_conf);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews n = lwres_getnamebyaddr(lwrctx, LWRES_ADDRTYPE_V4,
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Convert from AF_INET to AF_INET6.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * Restore original address.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * Lookup IPv6 address.
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence if (memcmp(src, &in6addr_any, IN6ADDRSZ) == 0) {
efe2f579ba6fbec4229129015780f2d925085b04Michael Graff n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington (void) lwres_conf_parse(lwrctx, lwres_resolv_conf);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews n = lwres_getnamebyaddr(lwrctx, LWRES_ADDRTYPE_V6, IN6ADDRSZ,
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (n != 0) {
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*% releases all the memory associated with the struct hostent pointer */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * Scan the interface table and set have_v4 and have_v6 depending
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * upon whether there are IPv4 and IPv6 interface addresses.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * 0 on success
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * -1 on failure.
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews * Set to zero. Used as loop terminators below.
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews * Get interface list from system.
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) == -1)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews * Grow buffer until large enough to contain all interface
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews * descriptions.
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews lifc.lifc_family = AF_UNSPEC; /* request all families */
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if ((n = ioctl(s, SIOCGLIFCONF, (char *)&lifc)) != -1) {
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews * Some OS's just return what will fit rather
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews * than set EINVAL if the buffer is too small
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater * to fit all the interfaces in. If
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews * lifc.lifc_len is too near to the end of the
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews * buffer we will grow it just in case and
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (lifc.lifc_len + 2 * sizeof(lifreq) < bufsiz)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews * Parse system's interface list.
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews cplim = buf + lifc.lifc_len; /* skip over if's with big ifr_addr's */
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews (*have_v4 == 0 || *have_v6 == 0) && cp < cplim;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (lifreq.lifr_addr.sa_len > sizeof(struct sockaddr))
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews (int)(sizeof(struct sockaddr));
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews cpsize = sizeof(lifreq.lifr_name) + lifreq.lifr_addr.sa_len;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#endif /* HAVE_MINIMUM_IFREQ */
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews /* XXX maybe this should be a hard error? */
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (ioctl(s, SIOCGLIFADDR, (char *)&lifreq) < 0)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews sizeof(in6)) == 0)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (s != -1)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews return (-1);
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#if !defined(SIOCGIFCONF) || !defined(SIOCGIFADDR)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews char _pad[256]; /* leave space for IPv6 addresses */
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews * Try to scan the interfaces using IPv6 ioctls().
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Set to zero. Used as loop terminators below.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Get interface list from system.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * Grow buffer until large enough to contain all interface
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * descriptions.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * This is a fix for IRIX OS in which the call to ioctl with
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * the flag SIOCGIFCONF may not return an entry for all the
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * interfaces like most flavors of Unix.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if ((n = ioctl(s, SIOCGIFCONF, (char *)&ifc)) != -1) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * Some OS's just return what will fit rather
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * than set EINVAL if the buffer is too small
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater * to fit all the interfaces in. If
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * ifc.ifc_len is too near to the end of the
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * buffer we will grow it just in case and
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (ifc.ifc_len + 2 * sizeof(u.ifreq) < bufsiz)
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Parse system's interface list.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cplim = buf + ifc.ifc_len; /* skip over if's with big ifr_addr's */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews (*have_v4 == 0 || *have_v6 == 0) && cp < cplim;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (u.ifreq.ifr_addr.sa_len > sizeof(struct sockaddr))
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence (int)(sizeof(struct sockaddr));
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews cpsize = sizeof(u.ifreq.ifr_name) + u.ifreq.ifr_addr.sa_len;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#endif /* HAVE_MINIMUM_IFREQ */
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (cpsize > sizeof(u.ifreq) && cpsize <= sizeof(u))
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /* XXX maybe this should be a hard error? */
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (ioctl(s, SIOCGIFADDR, (char *)&u.ifreq) < 0)
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence sizeof(in6)) == 0)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (s != -1)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (-1);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsstatic struct hostent *
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrencecopyandmerge(struct hostent *he1, struct hostent *he2, int af, int *error_num)
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Work out array sizes.
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews he->h_addr_list = malloc(sizeof(char *) * (addresses));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews memset(he->h_addr_list, 0, sizeof(char *) * (addresses));
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Copy addresses.
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews *npp = malloc((af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Convert to mapped if required.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (af == AF_INET6 && he1->h_addrtype == AF_INET) {
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews *npp = malloc((af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Convert to mapped if required.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (af == AF_INET6 && he2->h_addrtype == AF_INET) {
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews he->h_aliases = malloc(sizeof(char *) * (names));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews memset(he->h_aliases, 0, sizeof(char *) * (names));
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Copy aliases.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Copy hostname.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews strcpy(he->h_name, (he1 != NULL) ? he1->h_name : he2->h_name);
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Set address type and length.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he->h_length = (af == AF_INET) ? INADDRSZ : IN6ADDRSZ;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsstatic struct hostent *
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrewshostfromaddr(lwres_gnbaresponse_t *addr, int af, const void *src) {
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Set family and length.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Copy aliases.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he->h_aliases = malloc(sizeof(char *) * (addr->naliases + 1));
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Copy address.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsstatic struct hostent *
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrencehostfromname(lwres_gabnresponse_t *name, int af) {
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Set family and length.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Copy aliases.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he->h_aliases = malloc(sizeof(char *) * (name->naliases + 1));
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Copy addresses.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he->h_addr_list = malloc(sizeof(char *) * (name->naddrs + 1));