7e4d75a5daeaaf8a7f559f9bd7fbf540184e235cMark Andrews/*
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Copyright (C) 1999-2005, 2007, 2009, 2012, 2014, 2016 Internet Systems Consortium, Inc. ("ISC")
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
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/.
7e4d75a5daeaaf8a7f559f9bd7fbf540184e235cMark Andrews */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
823ca3c14f1596341bdd50707c01f3b529b75b4aAutomatic Updater/* $Id: getipnode.c,v 1.47 2009/09/01 23:47:45 tbox Exp $ */
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*! \file */
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/**
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:
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater *
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \code
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 * };
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * #define h_addr h_addr_list[0] // address, for backward compatibility
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \endcode
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater *
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * The members of this structure are:
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater *
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \li h_name:
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * The official (canonical) name of the host.
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater *
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \li h_aliases:
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * A NULL-terminated array of alternate names (nicknames) for the
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * host.
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater *
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \li h_addrtype:
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * The type of address being returned - usually PF_INET or
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * PF_INET6.
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater *
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \li h_length:
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * The length of the address in bytes.
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater *
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.
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater *
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:
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater *
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.
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater *
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.
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater *
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 * ignored.
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater *
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \li #AI_DEFAULT:
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * This default sets the #AI_V4MAPPED and #AI_ADDRCONFIG flag bits.
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater *
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.
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater *
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 * itself.
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater *
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \section getipnode_return Return Values
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater *
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:
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater *
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \li #HOST_NOT_FOUND:
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * No such host is known.
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater *
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.
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater *
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 * retried.
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater *
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \li #NO_RECOVERY:
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * An unexpected failure occurred, and retrying the request is
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * pointless.
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater *
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * lwres_hstrerror() translates these error codes to suitable error
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * messages.
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater *
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * \section getipnode_see See Also
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater *
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater * getaddrinfo.c, gethost.c, getnameinfo.c, herror.c, RFC2553
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein */
9c3531d72aeaad6c5f01efe6a1c82023e1379e4dDavid Lawrence
6b7257f756eb0530cdf54df9a7fab8d51a5001c3David Lawrence#include <config.h>
6b7257f756eb0530cdf54df9a7fab8d51a5001c3David Lawrence
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#include <stdio.h>
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#include <stdlib.h>
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#include <string.h>
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#include <errno.h>
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
37d266d288410d1ead241c02a8a1dbcb0160be46Michael Graff#include <lwres/lwres.h>
35c842e05dc6382ce1d9161a658d3ff4b2c3d4c9Bob Halley#include <lwres/net.h>
37d266d288410d1ead241c02a8a1dbcb0160be46Michael Graff#include <lwres/netdb.h> /* XXX #include <netdb.h> */
37d266d288410d1ead241c02a8a1dbcb0160be46Michael Graff
37d266d288410d1ead241c02a8a1dbcb0160be46Michael Graff#include "assert_p.h"
37d266d288410d1ead241c02a8a1dbcb0160be46Michael Graff
d0783e645b149fcea7e7f22cd43f87b5d188b055Mark Andrews#ifndef INADDRSZ
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#define INADDRSZ 4
d0783e645b149fcea7e7f22cd43f87b5d188b055Mark Andrews#endif
d0783e645b149fcea7e7f22cd43f87b5d188b055Mark Andrews#ifndef IN6ADDRSZ
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#define IN6ADDRSZ 16
d0783e645b149fcea7e7f22cd43f87b5d188b055Mark Andrews#endif
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence#ifdef LWRES_PLATFORM_NEEDIN6ADDRANY
5236050c0f819b727dfc4850133f5194f346f76fDanny MayerLIBLWRES_EXTERNAL_DATA const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence#endif
35c842e05dc6382ce1d9161a658d3ff4b2c3d4c9Bob Halley
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#ifndef IN6_IS_ADDR_V4COMPAT
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsstatic const unsigned char in6addr_compat[12] = {
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence};
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#define IN6_IS_ADDR_V4COMPAT(x) (!memcmp((x)->s6_addr, in6addr_compat, 12) && \
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater ((x)->s6_addr[12] != 0 || \
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater (x)->s6_addr[13] != 0 || \
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater (x)->s6_addr[14] != 0 || \
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater ((x)->s6_addr[15] != 0 && \
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater (x)->s6_addr[15] != 1)))
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#endif
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#ifndef IN6_IS_ADDR_V4MAPPED
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#define IN6_IS_ADDR_V4MAPPED(x) (!memcmp((x)->s6_addr, in6addr_mapped, 12))
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#endif
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsstatic const unsigned char in6addr_mapped[12] = {
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence};
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews/***
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *** Forward declarations.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews ***/
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrencestatic int
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrencescan_interfaces(int *, int *);
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrencestatic struct hostent *
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrencecopyandmerge(struct hostent *, struct hostent *, int, int *);
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrencestatic struct hostent *
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrencehostfromaddr(lwres_gnbaresponse_t *addr, int af, const void *src);
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrencestatic struct hostent *
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrencehostfromname(lwres_gabnresponse_t *name, int af);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews/***
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *** Public functions.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews ***/
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*!
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * AI_V4MAPPED + AF_INET6
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * If no IPv6 address then a query for IPv4 and map returned values.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * AI_ALL + AI_V4MAPPED + AF_INET6
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * Return IPv6 and IPv4 mapped.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * AI_ADDRCONFIG
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * Only return IPv6 / IPv4 address if there is an interface of that
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * type active.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsstruct hostent *
af9cfbc64363b61aa5903dd916e9fbc152084d4cMark Andrewslwres_getipnodebyname(const char *name, int af, int flags, int *error_num) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int have_v4 = 1, have_v6 = 1;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews struct in_addr in4;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews struct in6_addr in6;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews struct hostent he, *he1 = NULL, *he2 = NULL, *he3 = NULL;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int v4 = 0, v6 = 0;
ef22fffeebffacbcbce1f8d68d0c3f29a7d4a59eEvan Hunt int tmp_err = 0;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews lwres_context_t *lwrctx = NULL;
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews lwres_gabnresponse_t *by = NULL;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int n;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence /*
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * If we care about active interfaces then check.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if ((flags & AI_ADDRCONFIG) != 0)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (scan_interfaces(&have_v4, &have_v6) == -1) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *error_num = NO_RECOVERY;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /* Check for literal address. */
35c842e05dc6382ce1d9161a658d3ff4b2c3d4c9Bob Halley if ((v4 = lwres_net_pton(AF_INET, name, &in4)) != 1)
35c842e05dc6382ce1d9161a658d3ff4b2c3d4c9Bob Halley v6 = lwres_net_pton(AF_INET6, name, &in6);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence /*
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Impossible combination?
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if ((af == AF_INET6 && (flags & AI_V4MAPPED) == 0 && v4 == 1) ||
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews (af == AF_INET && v6 == 1) ||
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews (have_v4 == 0 && v4 == 1) ||
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews (have_v6 == 0 && v6 == 1) ||
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews (have_v4 == 0 && af == AF_INET) ||
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews (have_v6 == 0 && af == AF_INET6 &&
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews (((flags & AI_V4MAPPED) != 0 && have_v4) ||
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews (flags & AI_V4MAPPED) == 0))) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *error_num = HOST_NOT_FOUND;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence /*
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Literal address?
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (v4 == 1 || v6 == 1) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews char *addr_list[2];
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews char *aliases[1];
bb6936058eb88eadff030462a347c10895c61a9aMark Andrews char mappedname[sizeof("::ffff:123.123.123.123")];
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence union {
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence const char *const_name;
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence char *deconst_name;
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence } u;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence u.const_name = name;
bb6936058eb88eadff030462a347c10895c61a9aMark Andrews if (v4 == 1 && af == AF_INET6) {
bb6936058eb88eadff030462a347c10895c61a9aMark Andrews strcpy(mappedname, "::ffff:");
49d69bbad82b53219cce3599b84ba3057f7daad3Mark Andrews lwres_net_ntop(AF_INET, (char *)&in4,
49d69bbad82b53219cce3599b84ba3057f7daad3Mark Andrews mappedname + sizeof("::ffff:") - 1,
49d69bbad82b53219cce3599b84ba3057f7daad3Mark Andrews sizeof(mappedname) - sizeof("::ffff:")
49d69bbad82b53219cce3599b84ba3057f7daad3Mark Andrews + 1);
bb6936058eb88eadff030462a347c10895c61a9aMark Andrews he.h_name = mappedname;
bb6936058eb88eadff030462a347c10895c61a9aMark Andrews } else
bb6936058eb88eadff030462a347c10895c61a9aMark Andrews he.h_name = u.deconst_name;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he.h_addr_list = addr_list;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he.h_addr_list[0] = (v4 == 1) ? (char *)&in4 : (char *)&in6;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he.h_addr_list[1] = NULL;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he.h_aliases = aliases;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he.h_aliases[0] = NULL;
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));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
efe2f579ba6fbec4229129015780f2d925085b04Michael Graff n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
6add3af8397580475ab9fa10ac8c1269465cff87Mark Andrews if (n != 0) {
6add3af8397580475ab9fa10ac8c1269465cff87Mark Andrews *error_num = NO_RECOVERY;
6add3af8397580475ab9fa10ac8c1269465cff87Mark Andrews goto cleanup;
6add3af8397580475ab9fa10ac8c1269465cff87Mark Andrews }
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington (void) lwres_conf_parse(lwrctx, lwres_resolv_conf);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews tmp_err = NO_RECOVERY;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (have_v6 && af == AF_INET6) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews n = lwres_getaddrsbyname(lwrctx, name, LWRES_ADDRTYPE_V6, &by);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (n == 0) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he1 = hostfromname(by, AF_INET6);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews lwres_gabnresponse_free(lwrctx, &by);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews if (he1 == NULL) {
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews *error_num = NO_RECOVERY;
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews goto cleanup;
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews } else {
ef22fffeebffacbcbce1f8d68d0c3f29a7d4a59eEvan Hunt if (n == LWRES_R_NOTFOUND)
ef22fffeebffacbcbce1f8d68d0c3f29a7d4a59eEvan Hunt tmp_err = HOST_NOT_FOUND;
ef22fffeebffacbcbce1f8d68d0c3f29a7d4a59eEvan Hunt else {
ef22fffeebffacbcbce1f8d68d0c3f29a7d4a59eEvan Hunt *error_num = NO_RECOVERY;
ef22fffeebffacbcbce1f8d68d0c3f29a7d4a59eEvan Hunt goto cleanup;
823ca3c14f1596341bdd50707c01f3b529b75b4aAutomatic Updater }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (have_v4 &&
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews ((af == AF_INET) ||
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews (af == AF_INET6 && (flags & AI_V4MAPPED) != 0 &&
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews (he1 == NULL || (flags & AI_ALL) != 0)))) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews n = lwres_getaddrsbyname(lwrctx, name, LWRES_ADDRTYPE_V4, &by);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (n == 0) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he2 = hostfromname(by, AF_INET);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews lwres_gabnresponse_free(lwrctx, &by);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews if (he2 == NULL) {
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews *error_num = NO_RECOVERY;
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews goto cleanup;
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews } else if (he1 == NULL) {
171d0db7f93bf796f870713d6208b21893401cfcBrian Wellington if (n == LWRES_R_NOTFOUND)
171d0db7f93bf796f870713d6208b21893401cfcBrian Wellington *error_num = HOST_NOT_FOUND;
171d0db7f93bf796f870713d6208b21893401cfcBrian Wellington else
171d0db7f93bf796f870713d6208b21893401cfcBrian Wellington *error_num = NO_RECOVERY;
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews goto cleanup;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews } else
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *error_num = tmp_err;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
823ca3c14f1596341bdd50707c01f3b529b75b4aAutomatic Updater he3 = copyandmerge(he1, he2, af, error_num);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cleanup:
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he1 != NULL)
af9cfbc64363b61aa5903dd916e9fbc152084d4cMark Andrews lwres_freehostent(he1);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he2 != NULL)
af9cfbc64363b61aa5903dd916e9fbc152084d4cMark Andrews lwres_freehostent(he2);
03084608809afbaf570093a14d2dc4ad507336a0Brian Wellington if (lwrctx != NULL) {
03084608809afbaf570093a14d2dc4ad507336a0Brian Wellington lwres_conf_clear(lwrctx);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews lwres_context_destroy(&lwrctx);
03084608809afbaf570093a14d2dc4ad507336a0Brian Wellington }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (he3);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
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. */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsstruct hostent *
af9cfbc64363b61aa5903dd916e9fbc152084d4cMark Andrewslwres_getipnodebyaddr(const void *src, size_t len, int af, int *error_num) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews struct hostent *he1, *he2;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews lwres_context_t *lwrctx = NULL;
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews lwres_gnbaresponse_t *by = NULL;
347ccc2716b45b8c72a1021d7a74faab49d3eefaBrian Wellington lwres_result_t n;
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence union {
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence const void *konst;
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence struct in6_addr *in6;
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence } u;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence /*
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Sanity checks.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (src == NULL) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *error_num = NO_RECOVERY;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews switch (af) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews case AF_INET:
5eb91bd90e3ad3426e5e3213031556a737cf3809Mark Andrews if (len != (unsigned int)INADDRSZ) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *error_num = NO_RECOVERY;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews break;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews case AF_INET6:
5eb91bd90e3ad3426e5e3213031556a737cf3809Mark Andrews if (len != (unsigned int)IN6ADDRSZ) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *error_num = NO_RECOVERY;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews break;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews default:
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *error_num = NO_RECOVERY;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /*
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 */
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence u.konst = src;
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence /*
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence * Look up IPv4 and IPv4 mapped/compatible addresses.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews */
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence if ((af == AF_INET6 && IN6_IS_ADDR_V4COMPAT(u.in6)) ||
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence (af == AF_INET6 && IN6_IS_ADDR_V4MAPPED(u.in6)) ||
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews (af == AF_INET)) {
ea023072092112a831ca7c2943387ccbb422a3f2Mark Andrews const unsigned char *cp = src;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (af == AF_INET6)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cp += 12;
efe2f579ba6fbec4229129015780f2d925085b04Michael Graff n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
03084608809afbaf570093a14d2dc4ad507336a0Brian Wellington if (n == LWRES_R_SUCCESS)
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington (void) lwres_conf_parse(lwrctx, lwres_resolv_conf);
347ccc2716b45b8c72a1021d7a74faab49d3eefaBrian Wellington if (n == LWRES_R_SUCCESS)
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews n = lwres_getnamebyaddr(lwrctx, LWRES_ADDRTYPE_V4,
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews INADDRSZ, cp, &by);
347ccc2716b45b8c72a1021d7a74faab49d3eefaBrian Wellington if (n != LWRES_R_SUCCESS) {
03084608809afbaf570093a14d2dc4ad507336a0Brian Wellington lwres_conf_clear(lwrctx);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews lwres_context_destroy(&lwrctx);
171d0db7f93bf796f870713d6208b21893401cfcBrian Wellington if (n == LWRES_R_NOTFOUND)
171d0db7f93bf796f870713d6208b21893401cfcBrian Wellington *error_num = HOST_NOT_FOUND;
171d0db7f93bf796f870713d6208b21893401cfcBrian Wellington else
171d0db7f93bf796f870713d6208b21893401cfcBrian Wellington *error_num = NO_RECOVERY;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he1 = hostfromaddr(by, AF_INET, cp);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews lwres_gnbaresponse_free(lwrctx, &by);
03084608809afbaf570093a14d2dc4ad507336a0Brian Wellington lwres_conf_clear(lwrctx);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews lwres_context_destroy(&lwrctx);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (af != AF_INET6)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (he1);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence /*
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Convert from AF_INET to AF_INET6.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he2 = copyandmerge(he1, NULL, af, error_num);
af9cfbc64363b61aa5903dd916e9fbc152084d4cMark Andrews lwres_freehostent(he1);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he2 == NULL)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /*
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * Restore original address.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews */
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(he2->h_addr, src, len);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (he2);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /*
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * Lookup IPv6 address.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews */
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence if (memcmp(src, &in6addr_any, IN6ADDRSZ) == 0) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *error_num = HOST_NOT_FOUND;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
efe2f579ba6fbec4229129015780f2d925085b04Michael Graff n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
03084608809afbaf570093a14d2dc4ad507336a0Brian Wellington if (n == LWRES_R_SUCCESS)
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington (void) lwres_conf_parse(lwrctx, lwres_resolv_conf);
347ccc2716b45b8c72a1021d7a74faab49d3eefaBrian Wellington if (n == LWRES_R_SUCCESS)
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews n = lwres_getnamebyaddr(lwrctx, LWRES_ADDRTYPE_V6, IN6ADDRSZ,
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews src, &by);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (n != 0) {
1cb73c69f76c8c2c66b767a8b9ad04f3988cf6a9Mark Andrews lwres_conf_clear(lwrctx);
1cb73c69f76c8c2c66b767a8b9ad04f3988cf6a9Mark Andrews lwres_context_destroy(&lwrctx);
ef22fffeebffacbcbce1f8d68d0c3f29a7d4a59eEvan Hunt
ef22fffeebffacbcbce1f8d68d0c3f29a7d4a59eEvan Hunt if (n == LWRES_R_NOTFOUND)
ef22fffeebffacbcbce1f8d68d0c3f29a7d4a59eEvan Hunt *error_num = HOST_NOT_FOUND;
ef22fffeebffacbcbce1f8d68d0c3f29a7d4a59eEvan Hunt else
ef22fffeebffacbcbce1f8d68d0c3f29a7d4a59eEvan Hunt *error_num = NO_RECOVERY;
ef22fffeebffacbcbce1f8d68d0c3f29a7d4a59eEvan Hunt
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
ef22fffeebffacbcbce1f8d68d0c3f29a7d4a59eEvan Hunt
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he1 = hostfromaddr(by, AF_INET6, src);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews lwres_gnbaresponse_free(lwrctx, &by);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews if (he1 == NULL)
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews *error_num = NO_RECOVERY;
1cb73c69f76c8c2c66b767a8b9ad04f3988cf6a9Mark Andrews lwres_conf_clear(lwrctx);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews lwres_context_destroy(&lwrctx);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (he1);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*% releases all the memory associated with the struct hostent pointer */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsvoid
af9cfbc64363b61aa5903dd916e9fbc152084d4cMark Andrewslwres_freehostent(struct hostent *he) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews char **cpp;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int names = 1;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int addresses = 1;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
611dc8876869036ab5e981e53ae7a446145d9354Mark Andrews if (he == NULL)
611dc8876869036ab5e981e53ae7a446145d9354Mark Andrews return;
611dc8876869036ab5e981e53ae7a446145d9354Mark Andrews
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews free(he->h_name);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cpp = he->h_addr_list;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews while (*cpp != NULL) {
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews free(*cpp);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *cpp = NULL;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cpp++;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews addresses++;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cpp = he->h_aliases;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews while (*cpp != NULL) {
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews free(*cpp);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cpp++;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews names++;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews free(he->h_aliases);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews free(he->h_addr_list);
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews free(he);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews/*
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * Private
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews/*
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 *
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * Returns:
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * 0 on success
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * -1 on failure.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#ifdef __hpux
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#define lifc_len iflc_len
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#define lifc_buf iflc_buf
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#define lifc_req iflc_req
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#define LIFCONF if_laddrconf
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#else
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#define ISC_HAVE_LIFC_FAMILY 1
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#define ISC_HAVE_LIFC_FLAGS 1
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#define LIFCONF lifconf
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#endif
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#ifdef __hpux
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#define lifr_addr iflr_addr
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#define lifr_name iflr_name
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#define lifr_dstaddr iflr_dstaddr
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#define lifr_flags iflr_flags
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#define ss_family sa_family
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#define LIFREQ if_laddrreq
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#else
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#define LIFREQ lifreq
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#endif
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrewsstatic int
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrewsscan_interfaces6(int *have_v4, int *have_v6) {
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews struct LIFCONF lifc;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews struct LIFREQ lifreq;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews struct in_addr in4;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews struct in6_addr in6;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews char *buf = NULL, *cp, *cplim;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews static unsigned int bufsiz = 4095;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews int s, cpsize, n;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews /*
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews * Set to zero. Used as loop terminators below.
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews */
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews *have_v4 = *have_v6 = 0;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews /*
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews * Get interface list from system.
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews */
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) == -1)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews goto err_ret;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews /*
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews * Grow buffer until large enough to contain all interface
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews * descriptions.
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews */
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews for (;;) {
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews buf = malloc(bufsiz);
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (buf == NULL)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews goto err_ret;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#ifdef ISC_HAVE_LIFC_FAMILY
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews lifc.lifc_family = AF_UNSPEC; /* request all families */
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#endif
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#ifdef ISC_HAVE_LIFC_FLAGS
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews lifc.lifc_flags = 0;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#endif
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews lifc.lifc_len = bufsiz;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews lifc.lifc_buf = buf;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if ((n = ioctl(s, SIOCGLIFCONF, (char *)&lifc)) != -1) {
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews /*
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 * retry.
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews */
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (lifc.lifc_len + 2 * sizeof(lifreq) < bufsiz)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews break;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews }
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if ((n == -1) && errno != EINVAL)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews goto err_ret;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (bufsiz > 1000000)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews goto err_ret;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews free(buf);
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews bufsiz += 4096;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews }
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews /*
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews * Parse system's interface list.
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews */
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews cplim = buf + lifc.lifc_len; /* skip over if's with big ifr_addr's */
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews for (cp = buf;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews (*have_v4 == 0 || *have_v6 == 0) && cp < cplim;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews cp += cpsize) {
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(&lifreq, cp, sizeof(lifreq));
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#ifdef LWRES_PLATFORM_HAVESALEN
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#ifdef FIX_ZERO_SA_LEN
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (lifreq.lifr_addr.sa_len == 0)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews lifreq.lifr_addr.sa_len = 16;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#endif
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#ifdef HAVE_MINIMUM_IFREQ
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews cpsize = sizeof(lifreq);
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (lifreq.lifr_addr.sa_len > sizeof(struct sockaddr))
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews cpsize += (int)lifreq.lifr_addr.sa_len -
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews (int)(sizeof(struct sockaddr));
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#else
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews cpsize = sizeof(lifreq.lifr_name) + lifreq.lifr_addr.sa_len;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#endif /* HAVE_MINIMUM_IFREQ */
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#elif defined SIOCGIFCONF_ADDR
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews cpsize = sizeof(lifreq);
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#else
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews cpsize = sizeof(lifreq.lifr_name);
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews /* XXX maybe this should be a hard error? */
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (ioctl(s, SIOCGLIFADDR, (char *)&lifreq) < 0)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews continue;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#endif
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews switch (lifreq.lifr_addr.ss_family) {
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews case AF_INET:
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (*have_v4 == 0) {
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(&in4,
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt &((struct sockaddr_in *)
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt &lifreq.lifr_addr)->sin_addr,
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt sizeof(in4));
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (in4.s_addr == INADDR_ANY)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews break;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews n = ioctl(s, SIOCGLIFFLAGS, (char *)&lifreq);
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (n < 0)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews break;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if ((lifreq.lifr_flags & IFF_UP) == 0)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews break;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews *have_v4 = 1;
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater }
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews break;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews case AF_INET6:
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (*have_v6 == 0) {
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(&in6,
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt &((struct sockaddr_in6 *)
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt &lifreq.lifr_addr)->sin6_addr,
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt sizeof(in6));
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (memcmp(&in6, &in6addr_any,
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews sizeof(in6)) == 0)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews break;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews n = ioctl(s, SIOCGLIFFLAGS, (char *)&lifreq);
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (n < 0)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews break;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if ((lifreq.lifr_flags & IFF_UP) == 0)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews break;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews *have_v6 = 1;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews }
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews break;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews }
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews }
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (buf != NULL)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews free(buf);
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews close(s);
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews return (0);
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews err_ret:
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (buf != NULL)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews free(buf);
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (s != -1)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews close(s);
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews return (-1);
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews}
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#endif
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsstatic int
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsscan_interfaces(int *have_v4, int *have_v6) {
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#if !defined(SIOCGIFCONF) || !defined(SIOCGIFADDR)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *have_v4 = *have_v6 = 1;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (0);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#else
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews struct ifconf ifc;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews union {
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews char _pad[256]; /* leave space for IPv6 addresses */
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews struct ifreq ifreq;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews } u;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews struct in_addr in4;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews struct in6_addr in6;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews char *buf = NULL, *cp, *cplim;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews static unsigned int bufsiz = 4095;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews int s, n;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews size_t cpsize;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews#ifdef WIN32
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews InitSockets();
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews#endif
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews /*
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews * Try to scan the interfaces using IPv6 ioctls().
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews */
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews if (!scan_interfaces6(have_v4, have_v6)) {
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews#ifdef WIN32
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews DestroySockets();
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews#endif
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews return (0);
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews }
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#endif
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence /*
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Set to zero. Used as loop terminators below.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *have_v4 = *have_v6 = 0;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence /*
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Get interface list from system.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews goto err_ret;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /*
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * Grow buffer until large enough to contain all interface
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * descriptions.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews for (;;) {
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews buf = malloc(bufsiz);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (buf == NULL)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews goto err_ret;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews ifc.ifc_len = bufsiz;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews ifc.ifc_buf = buf;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#ifdef IRIX_EMUL_IOCTL_SIOCGIFCONF
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /*
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 */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (emul_ioctl(&ifc) >= 0)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews break;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#else
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if ((n = ioctl(s, SIOCGIFCONF, (char *)&ifc)) != -1) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /*
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
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews * retry.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews */
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (ifc.ifc_len + 2 * sizeof(u.ifreq) < bufsiz)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews break;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#endif
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if ((n == -1) && errno != EINVAL)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews goto err_ret;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (bufsiz > 1000000)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews goto err_ret;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews free(buf);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews bufsiz += 4096;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence /*
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Parse system's interface list.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cplim = buf + ifc.ifc_len; /* skip over if's with big ifr_addr's */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews for (cp = buf;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews (*have_v4 == 0 || *have_v6 == 0) && cp < cplim;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cp += cpsize) {
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(&u.ifreq, cp, sizeof(u.ifreq));
fa5a42fbad42f4e033376d5d4624e29d018d97b7Brian Wellington#ifdef LWRES_PLATFORM_HAVESALEN
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#ifdef FIX_ZERO_SA_LEN
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (u.ifreq.ifr_addr.sa_len == 0)
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews u.ifreq.ifr_addr.sa_len = 16;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#endif
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#ifdef HAVE_MINIMUM_IFREQ
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews cpsize = sizeof(u.ifreq);
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (u.ifreq.ifr_addr.sa_len > sizeof(struct sockaddr))
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews cpsize += (int)u.ifreq.ifr_addr.sa_len -
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence (int)(sizeof(struct sockaddr));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#else
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))
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(&u.ifreq, cp, cpsize);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#elif defined SIOCGIFCONF_ADDR
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews cpsize = sizeof(u.ifreq);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#else
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews cpsize = sizeof(u.ifreq.ifr_name);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /* XXX maybe this should be a hard error? */
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if (ioctl(s, SIOCGIFADDR, (char *)&u.ifreq) < 0)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews continue;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews#endif
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews switch (u.ifreq.ifr_addr.sa_family) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews case AF_INET:
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (*have_v4 == 0) {
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(&in4,
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt &((struct sockaddr_in *)
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt &u.ifreq.ifr_addr)->sin_addr,
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt sizeof(in4));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (in4.s_addr == INADDR_ANY)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews break;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews n = ioctl(s, SIOCGIFFLAGS, (char *)&u.ifreq);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (n < 0)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews break;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if ((u.ifreq.ifr_flags & IFF_UP) == 0)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews break;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *have_v4 = 1;
800fb35bf0c1cfcd82b542944b0d29e1837d8a09Automatic Updater }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews break;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews case AF_INET6:
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (*have_v6 == 0) {
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(&in6,
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt &((struct sockaddr_in6 *)
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt &u.ifreq.ifr_addr)->sin6_addr,
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt sizeof(in6));
ed71ea51c6ecb5d7d659b6e6a20f6b3f5c2678c6David Lawrence if (memcmp(&in6, &in6addr_any,
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence sizeof(in6)) == 0)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews break;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews n = ioctl(s, SIOCGIFFLAGS, (char *)&u.ifreq);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (n < 0)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews break;
bdb1394788a677d0b6e8499ba1ece17a73f476c7Mark Andrews if ((u.ifreq.ifr_flags & IFF_UP) == 0)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews break;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *have_v6 = 1;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews break;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (buf != NULL)
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews free(buf);
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews#ifdef WIN32
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews DestroySockets();
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews#endif
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews close(s);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (0);
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews err_ret:
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (buf != NULL)
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews free(buf);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (s != -1)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews close(s);
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews#ifdef WIN32
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews DestroySockets();
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews#endif
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (-1);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews#endif
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsstatic struct hostent *
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrencecopyandmerge(struct hostent *he1, struct hostent *he2, int af, int *error_num)
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence{
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews struct hostent *he = NULL;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int addresses = 1; /* NULL terminator */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int names = 1; /* NULL terminator */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int len = 0;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews char **cpp, **npp;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews /*
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Work out array sizes.
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he1 != NULL) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cpp = he1->h_addr_list;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews while (*cpp != NULL) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews addresses++;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cpp++;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cpp = he1->h_aliases;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews while (*cpp != NULL) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews names++;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cpp++;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he2 != NULL) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cpp = he2->h_addr_list;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews while (*cpp != NULL) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews addresses++;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cpp++;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he1 == NULL) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cpp = he2->h_aliases;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews while (*cpp != NULL) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews names++;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cpp++;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (addresses == 1) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *error_num = NO_ADDRESS;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
91cd0f93ad34d23e8b09dca337120f64fbe8f0a1Andreas Gustafsson he = malloc(sizeof(*he));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he == NULL)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews goto no_recovery;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews he->h_addr_list = malloc(sizeof(char *) * (addresses));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he->h_addr_list == NULL)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews goto cleanup0;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews memset(he->h_addr_list, 0, sizeof(char *) * (addresses));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence /*
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Copy addresses.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews npp = he->h_addr_list;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he1 != NULL) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cpp = he1->h_addr_list;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews while (*cpp != NULL) {
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews *npp = malloc((af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (*npp == NULL)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews goto cleanup1;
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence /*
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Convert to mapped if required.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (af == AF_INET6 && he1->h_addrtype == AF_INET) {
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(*npp, in6addr_mapped,
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt sizeof(in6addr_mapped));
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(*npp + sizeof(in6addr_mapped), *cpp,
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt INADDRSZ);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews } else {
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(*npp, *cpp,
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt (af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cpp++;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews npp++;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he2 != NULL) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cpp = he2->h_addr_list;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews while (*cpp != NULL) {
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews *npp = malloc((af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (*npp == NULL)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews goto cleanup1;
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence /*
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Convert to mapped if required.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (af == AF_INET6 && he2->h_addrtype == AF_INET) {
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(*npp, in6addr_mapped,
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt sizeof(in6addr_mapped));
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(*npp + sizeof(in6addr_mapped), *cpp,
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt INADDRSZ);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews } else {
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(*npp, *cpp,
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt (af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cpp++;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews npp++;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews he->h_aliases = malloc(sizeof(char *) * (names));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he->h_aliases == NULL)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews goto cleanup1;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews memset(he->h_aliases, 0, sizeof(char *) * (names));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence /*
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Copy aliases.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews npp = he->h_aliases;
41bbb34bc20f189af62e7047ce42822615417f15Evan Hunt cpp = (he1 != NULL) ? he1->h_aliases
41bbb34bc20f189af62e7047ce42822615417f15Evan Hunt : ((he2 != NULL) ? he2->h_aliases : NULL);
47c5b8af920a93763c97d9a93ea1fd766961a5b3Evan Hunt while (cpp != NULL && *cpp != NULL) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews len = strlen (*cpp) + 1;
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews *npp = malloc(len);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (*npp == NULL)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews goto cleanup2;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews strcpy(*npp, *cpp);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews npp++;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cpp++;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence /*
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Copy hostname.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews he->h_name = malloc(strlen((he1 != NULL) ?
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he1->h_name : he2->h_name) + 1);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he->h_name == NULL)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews goto cleanup2;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews strcpy(he->h_name, (he1 != NULL) ? he1->h_name : he2->h_name);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence /*
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Set address type and length.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he->h_addrtype = af;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he->h_length = (af == AF_INET) ? INADDRSZ : IN6ADDRSZ;
5236050c0f819b727dfc4850133f5194f346f76fDanny Mayer return (he);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cleanup2:
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cpp = he->h_aliases;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews while (*cpp != NULL) {
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews free(*cpp);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cpp++;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews free(he->h_aliases);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cleanup1:
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cpp = he->h_addr_list;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews while (*cpp != NULL) {
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews free(*cpp);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *cpp = NULL;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cpp++;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews free(he->h_addr_list);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cleanup0:
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews free(he);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews no_recovery:
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews *error_num = NO_RECOVERY;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsstatic struct hostent *
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrewshostfromaddr(lwres_gnbaresponse_t *addr, int af, const void *src) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews struct hostent *he;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int i;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
91cd0f93ad34d23e8b09dca337120f64fbe8f0a1Andreas Gustafsson he = malloc(sizeof(*he));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he == NULL)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews goto cleanup;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews memset(he, 0, sizeof(*he));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence /*
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Set family and length.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he->h_addrtype = af;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews switch (af) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews case AF_INET:
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews he->h_length = INADDRSZ;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews break;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews case AF_INET6:
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews he->h_length = IN6ADDRSZ;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews break;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews default:
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews INSIST(0);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence /*
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Copy name.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
88ed7381f16a72409061875ddeda598f477e5ef6Michael Graff he->h_name = strdup(addr->realname);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he->h_name == NULL)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews goto cleanup;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence /*
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Copy aliases.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he->h_aliases = malloc(sizeof(char *) * (addr->naliases + 1));
347ccc2716b45b8c72a1021d7a74faab49d3eefaBrian Wellington if (he->h_aliases == NULL)
347ccc2716b45b8c72a1021d7a74faab49d3eefaBrian Wellington goto cleanup;
f1b68725503ff3e46001eee5a1751e29a43a09d1Andreas Gustafsson for (i = 0; i < addr->naliases; i++) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he->h_aliases[i] = strdup(addr->aliases[i]);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he->h_aliases[i] == NULL)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews goto cleanup;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he->h_aliases[i] = NULL;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence /*
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Copy address.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he->h_addr_list = malloc(sizeof(char *) * 2);
c4cc75482fd6846163cafa79e98abb11bcfaf3d3Mark Andrews if (he->h_addr_list == NULL)
c4cc75482fd6846163cafa79e98abb11bcfaf3d3Mark Andrews goto cleanup;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he->h_addr_list[0] = malloc(he->h_length);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he->h_addr_list[0] == NULL)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews goto cleanup;
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(he->h_addr_list[0], src, he->h_length);
c4cc75482fd6846163cafa79e98abb11bcfaf3d3Mark Andrews he->h_addr_list[1] = NULL;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (he);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cleanup:
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he != NULL && he->h_addr_list != NULL) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews for (i = 0; he->h_addr_list[i] != NULL; i++)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews free(he->h_addr_list[i]);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews free(he->h_addr_list);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he != NULL && he->h_aliases != NULL) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews for (i = 0; he->h_aliases[i] != NULL; i++)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews free(he->h_aliases[i]);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews free(he->h_aliases);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he != NULL && he->h_name != NULL)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews free(he->h_name);
347ccc2716b45b8c72a1021d7a74faab49d3eefaBrian Wellington if (he != NULL)
347ccc2716b45b8c72a1021d7a74faab49d3eefaBrian Wellington free(he);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrewsstatic struct hostent *
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrencehostfromname(lwres_gabnresponse_t *name, int af) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews struct hostent *he;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews int i;
d736db6dc53e615e3f2d66d1ddbe28473694d107Michael Graff lwres_addr_t *addr;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
91cd0f93ad34d23e8b09dca337120f64fbe8f0a1Andreas Gustafsson he = malloc(sizeof(*he));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he == NULL)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews goto cleanup;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews memset(he, 0, sizeof(*he));
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence /*
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Set family and length.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he->h_addrtype = af;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews switch (af) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews case AF_INET:
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews he->h_length = INADDRSZ;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews break;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews case AF_INET6:
1a03b5e68553c37e9cc0097368909dfc37fb8cefMark Andrews he->h_length = IN6ADDRSZ;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews break;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews default:
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews INSIST(0);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence /*
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Copy name.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
88ed7381f16a72409061875ddeda598f477e5ef6Michael Graff he->h_name = strdup(name->realname);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he->h_name == NULL)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews goto cleanup;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence /*
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Copy aliases.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he->h_aliases = malloc(sizeof(char *) * (name->naliases + 1));
45f36932943c02159a8907380fc79dd70e2184f1Evan Hunt if (he->h_aliases == NULL)
45f36932943c02159a8907380fc79dd70e2184f1Evan Hunt goto cleanup;
f1b68725503ff3e46001eee5a1751e29a43a09d1Andreas Gustafsson for (i = 0; i < name->naliases; i++) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he->h_aliases[i] = strdup(name->aliases[i]);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he->h_aliases[i] == NULL)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews goto cleanup;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he->h_aliases[i] = NULL;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence /*
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence * Copy addresses.
ca81c3971cd0c9cfd830c0a18289d4d1b0f9de01David Lawrence */
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he->h_addr_list = malloc(sizeof(char *) * (name->naddrs + 1));
45f36932943c02159a8907380fc79dd70e2184f1Evan Hunt if (he->h_addr_list == NULL)
45f36932943c02159a8907380fc79dd70e2184f1Evan Hunt goto cleanup;
d736db6dc53e615e3f2d66d1ddbe28473694d107Michael Graff addr = LWRES_LIST_HEAD(name->addrs);
d736db6dc53e615e3f2d66d1ddbe28473694d107Michael Graff i = 0;
d736db6dc53e615e3f2d66d1ddbe28473694d107Michael Graff while (addr != NULL) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he->h_addr_list[i] = malloc(he->h_length);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he->h_addr_list[i] == NULL)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews goto cleanup;
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(he->h_addr_list[i], addr->address, he->h_length);
d736db6dc53e615e3f2d66d1ddbe28473694d107Michael Graff addr = LWRES_LIST_NEXT(addr, link);
d736db6dc53e615e3f2d66d1ddbe28473694d107Michael Graff i++;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews he->h_addr_list[i] = NULL;
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (he);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews cleanup:
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he != NULL && he->h_addr_list != NULL) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews for (i = 0; he->h_addr_list[i] != NULL; i++)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews free(he->h_addr_list[i]);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews free(he->h_addr_list);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he != NULL && he->h_aliases != NULL) {
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews for (i = 0; he->h_aliases[i] != NULL; i++)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews free(he->h_aliases[i]);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews free(he->h_aliases);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews }
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews if (he != NULL && he->h_name != NULL)
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews free(he->h_name);
347ccc2716b45b8c72a1021d7a74faab49d3eefaBrian Wellington if (he != NULL)
347ccc2716b45b8c72a1021d7a74faab49d3eefaBrian Wellington free(he);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews return (NULL);
7d2b275f7e9238e2c709737601f6260b5a9a4ee1Mark Andrews}