getipnode.c revision d0783e645b149fcea7e7f22cd43f87b5d188b055
#include <isc/assertions.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef INADDRSZ
#define INADDRSZ 4
#endif
#ifndef IN6ADDRSZ
#define IN6ADDRSZ 16
#endif
#ifndef IN6_IS_ADDR_V4COMPAT
static const unsigned char in6addr_compat[12] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
((x)->s6_addr[12] != 0 || \
(x)->s6_addr[13] != 0 || \
(x)->s6_addr[14] != 0 || \
((x)->s6_addr[15] != 0 && \
#endif
#ifndef IN6_IS_ADDR_V4MAPPED
#endif
static const unsigned char in6addr_mapped[12] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
/***
*** Forward declarations.
***/
static int scan_interfaces(int *, int *);
int, int *);
const void *src);
/***
*** Public functions.
***/
/*
* AI_V4MAPPED + AF_INET6
* If no IPv6 address then a query for IPv4 and map returned values.
*
* AI_ALL + AI_V4MAPPED + AF_INET6
* Return IPv6 and IPv4 mapped.
*
* AI_ADDRCONFIG
* Only return IPv6 / IPv4 address if there is an interface of that
* type active.
*/
struct hostent *
int tmp_err;
int n;
/* If we care about active interfaces then check. */
if ((flags & AI_ADDRCONFIG) != 0)
*error_num = NO_RECOVERY;
return (NULL);
}
/* Check for literal address. */
/* Impossible combination? */
(flags & AI_V4MAPPED) == 0))) {
return (NULL);
}
/* Literal address? */
char *addr_list[2];
char *aliases[1];
}
if (n == 0) {
*error_num = NO_RECOVERY;
goto cleanup;
}
} else {
}
}
if (have_v4 &&
if (n == 0) {
*error_num = NO_RECOVERY;
goto cleanup;
}
goto cleanup;
}
} else
return (he3);
}
struct hostent *
int n;
/* Sanity Checks. */
*error_num = NO_RECOVERY;
return (NULL);
}
switch (af) {
case AF_INET:
*error_num = NO_RECOVERY;
return (NULL);
}
break;
case AF_INET6:
*error_num = NO_RECOVERY;
return (NULL);
}
break;
default:
*error_num = NO_RECOVERY;
return (NULL);
}
/*
* Lookup IPv4 and IPv4 mapped/compatible addresses
*/
cp += 12;
if (n == 0)
if (n != 0) {
return (NULL);
}
return (he1);
/* Convert from AF_INET to AF_INET6 */
return (NULL);
/*
* Restore original address.
*/
return (he2);
}
/*
* Lookup IPv6 address.
*/
return (NULL);
}
if (n == 0)
if (n != 0) {
return (NULL);
}
*error_num = NO_RECOVERY;
return (he1);
}
void
char **cpp;
int names = 1;
int addresses = 1;
cpp++;
addresses++;
}
cpp++;
names++;
}
}
/*
* Private
*/
/*
* Scan the interface table and set have_v4 and have_v6 depending
* upon whether there are IPv4 and IPv6 interface addresses.
*
* Returns:
* 0 on success
* -1 on failure.
*/
static int
#if 1
return (0);
#else
static int bufsiz = 4095;
int s, cpsize, n;
/* Set to zero. Used as loop terminators below. */
/* Get interface list from system. */
goto err_ret;
/*
* Grow buffer until large enough to contain all interface
* descriptions.
*/
for (;;) {
goto err_ret;
#ifdef IRIX_EMUL_IOCTL_SIOCGIFCONF
/*
* This is a fix for IRIX OS in which the call to ioctl with
* the flag SIOCGIFCONF may not return an entry for all the
* interfaces like most flavors of Unix.
*/
if (emul_ioctl(&ifc) >= 0)
break;
#else
/*
* Some OS's just return what will fit rather
* than set EINVAL if the buffer is too small
* to fit all the interfaces in. If
* ifc.ifc_len is too near to the end of the
* buffer we will grow it just in case and
* retry.
*/
break;
}
#endif
goto err_ret;
if (bufsiz > 1000000)
goto err_ret;
bufsiz += 4096;
}
/* Parse system's interface list. */
#ifdef HAVE_SA_LEN
#ifdef FIX_ZERO_SA_LEN
#endif
#ifdef HAVE_MINIMUM_IFREQ
(int)(sizeof (struct sockaddr));
#else
#endif /* HAVE_MINIMUM_IFREQ */
#elif defined SIOCGIFCONF_ADDR
#else
/* XXX maybe this should be a hard error? */
continue;
#endif
case AF_INET:
if (*have_v4 == 0) {
&((struct sockaddr_in *)
break;
if (n < 0)
break;
break;
*have_v4 = 1;
}
break;
case AF_INET6:
if (*have_v6 == 0) {
&((struct sockaddr_in6 *)
break;
if (n < 0)
break;
break;
*have_v6 = 1;
}
break;
}
}
close(s);
return (0);
if (s != -1)
close(s);
return (-1);
#endif
}
static struct hostent *
int len = 0;
/*
* Work out array sizes;
*/
addresses++;
cpp++;
}
names++;
cpp++;
}
}
addresses++;
cpp++;
}
names++;
cpp++;
}
}
}
if (addresses == 1) {
*error_num = NO_ADDRESS;
return (NULL);
}
goto no_recovery;
goto cleanup0;
/* copy addresses */
goto cleanup1;
/* convert to mapped if required */
sizeof in6addr_mapped);
INADDRSZ);
} else {
}
cpp++;
npp++;
}
}
goto cleanup1;
/* convert to mapped if required */
sizeof in6addr_mapped);
INADDRSZ);
} else {
}
cpp++;
npp++;
}
}
goto cleanup1;
/* copy aliases */
goto cleanup2;
npp++;
cpp++;
}
/* copy hostname */
goto cleanup2;
/* set address type and length */
return(he);
cpp++;
}
cpp++;
}
*error_num = NO_RECOVERY;
return (NULL);
}
static struct hostent *
int i;
goto cleanup;
/* Set family and length */
switch (af) {
case AF_INET:
break;
case AF_INET6:
break;
default:
INSIST(0);
}
/* copy name */
goto cleanup;
/* copy aliases */
goto cleanup;
}
/* copy address */
goto cleanup;
return (he);
}
}
return (NULL);
}
static struct hostent *
int i;
goto cleanup;
/* Set family and length */
switch (af) {
case AF_INET:
break;
case AF_INET6:
break;
default:
INSIST(0);
}
/* copy name */
goto cleanup;
/* copy aliases */
goto cleanup;
}
/* copy addresses */
goto cleanup;
}
return (he);
}
}
return (NULL);
}