getipnode.c revision 91cd0f93ad34d23e8b09dca337120f64fbe8f0a1
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * Copyright (C) 1999-2001 Internet Software Consortium.
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * Permission to use, copy, modify, and distribute this software for any
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * purpose with or without fee is hereby granted, provided that the above
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * copyright notice and this permission notice appear in all copies.
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt/* $Id: getipnode.c,v 1.32 2001/11/27 01:56:28 gson Exp $ */
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt#include <lwres/netdb.h> /* XXX #include <netdb.h> */
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan HuntLIBLWRES_EXTERNAL_DATA const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt#define IN6_IS_ADDR_V4COMPAT(x) (!memcmp((x)->s6_addr, in6addr_compat, 12) && \
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt#define IN6_IS_ADDR_V4MAPPED(x) (!memcmp((x)->s6_addr, in6addr_mapped, 12))
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt *** Forward declarations.
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Huntstatic struct hostent *
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Huntcopyandmerge(struct hostent *, struct hostent *, int, int *);
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Huntstatic struct hostent *
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunthostfromaddr(lwres_gnbaresponse_t *addr, int af, const void *src);
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Huntstatic struct hostent *
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt *** Public functions.
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * AI_V4MAPPED + AF_INET6
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * If no IPv6 address then a query for IPv4 and map returned values.
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * AI_ALL + AI_V4MAPPED + AF_INET6
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * Return IPv6 and IPv4 mapped.
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * AI_ADDRCONFIG
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * Only return IPv6 / IPv4 address if there is an interface of that
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * type active.
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Huntlwres_getipnodebyname(const char *name, int af, int flags, int *error_num) {
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt struct hostent he, *he1 = NULL, *he2 = NULL, *he3 = NULL;
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * If we care about active interfaces then check.
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt /* Check for literal address. */
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt if ((v4 = lwres_net_pton(AF_INET, name, &in4)) != 1)
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * Impossible combination?
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt if ((af == AF_INET6 && (flags & AI_V4MAPPED) == 0 && v4 == 1) ||
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * Literal address?
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt he.h_addr_list[0] = (v4 == 1) ? (char *)&in4 : (char *)&in6;
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt if (n != 0) {
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt (void) lwres_conf_parse(lwrctx, lwres_resolv_conf);
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt n = lwres_getaddrsbyname(lwrctx, name, LWRES_ADDRTYPE_V6, &by);
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt if (n == 0) {
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt n = lwres_getaddrsbyname(lwrctx, name, LWRES_ADDRTYPE_V4, &by);
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt if (n == 0) {
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Huntlwres_getipnodebyaddr(const void *src, size_t len, int af, int *error_num) {
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt const void *konst;
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * Sanity checks.
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * The de-"const"-ing game is done because at least one
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * vendor's system (RedHat 6.0) defines the IN6_IS_ADDR_*
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * macros in such a way that they discard the const with
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * internal casting, and gcc ends up complaining. Rather
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * than replacing their own (possibly optimized) definitions
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * with our own, cleanly discarding the const is the easiest
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * thing to do.
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * Look up IPv4 and IPv4 mapped/compatible addresses.
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt if ((af == AF_INET6 && IN6_IS_ADDR_V4COMPAT(u.in6)) ||
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt (af == AF_INET6 && IN6_IS_ADDR_V4MAPPED(u.in6)) ||
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt (void) lwres_conf_parse(lwrctx, lwres_resolv_conf);
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt n = lwres_getnamebyaddr(lwrctx, LWRES_ADDRTYPE_V4,
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * Convert from AF_INET to AF_INET6.
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * Restore original address.
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * Lookup IPv6 address.
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt (void) lwres_conf_parse(lwrctx, lwres_resolv_conf);
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt n = lwres_getnamebyaddr(lwrctx, LWRES_ADDRTYPE_V6, IN6ADDRSZ,
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt if (n != 0) {
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * Scan the interface table and set have_v4 and have_v6 depending
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * upon whether there are IPv4 and IPv6 interface addresses.
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews * 0 on success
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews * -1 on failure.
int s, cpsize, n;
goto err_ret;
goto err_ret;
#ifdef IRIX_EMUL_IOCTL_SIOCGIFCONF
goto err_ret;
goto err_ret;
#ifdef LWRES_PLATFORM_HAVESALEN
#ifdef FIX_ZERO_SA_LEN
#ifdef HAVE_MINIMUM_IFREQ
(int)(sizeof(struct sockaddr));
case AF_INET:
if (*have_v4 == 0) {
&((struct sockaddr_in *)
sizeof(in4));
case AF_INET6:
if (*have_v6 == 0) {
&((struct sockaddr_in6 *)
sizeof(in6));
sizeof(in6)) == 0)
close(s);
close(s);
static struct hostent *
int len = 0;
addresses++;
cpp++;
names++;
cpp++;
addresses++;
cpp++;
names++;
cpp++;
return (NULL);
goto no_recovery;
goto cleanup0;
goto cleanup1;
sizeof(in6addr_mapped));
INADDRSZ);
cpp++;
npp++;
goto cleanup1;
sizeof(in6addr_mapped));
INADDRSZ);
cpp++;
npp++;
goto cleanup1;
goto cleanup2;
npp++;
cpp++;
goto cleanup2;
return (he);
cpp++;
cpp++;
return (NULL);
static struct hostent *
goto cleanup;
switch (af) {
case AF_INET:
case AF_INET6:
INSIST(0);
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
return (he);
return (NULL);
static struct hostent *
goto cleanup;
switch (af) {
case AF_INET:
case AF_INET6:
INSIST(0);
goto cleanup;
goto cleanup;
goto cleanup;
return (he);
return (NULL);