getipnode.c revision 37d266d288410d1ead241c02a8a1dbcb0160be46
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley * Copyright (C) 1999, 2000 Internet Software Consortium.
1ccbfca64ae86ace521053773001cb995352f96fBob Halley * Permission to use, copy, modify, and distribute this software for any
1ccbfca64ae86ace521053773001cb995352f96fBob Halley * purpose with or without fee is hereby granted, provided that the above
1ccbfca64ae86ace521053773001cb995352f96fBob Halley * copyright notice and this permission notice appear in all copies.
1ccbfca64ae86ace521053773001cb995352f96fBob Halley * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
1ccbfca64ae86ace521053773001cb995352f96fBob Halley * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
1ccbfca64ae86ace521053773001cb995352f96fBob Halley * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
1ccbfca64ae86ace521053773001cb995352f96fBob Halley * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
1ccbfca64ae86ace521053773001cb995352f96fBob Halley * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
1ccbfca64ae86ace521053773001cb995352f96fBob Halley * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
1ccbfca64ae86ace521053773001cb995352f96fBob Halley * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
d549c3734869b48e740c64e80890bcb6f3ce672cJames Brister#include <lwres/netdb.h> /* XXX #include <netdb.h> */
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffstatic const unsigned char in6addr_compat[12] = {
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
0e3ad060581e366d3e682caf2dd5d9ea2e0f4893Bob Halley#define IN6_IS_ADDR_V4COMPAT(x) (!memcmp((x)->s6_addr, in6addr_compat, 12) && \
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley#define IN6_IS_ADDR_V4MAPPED(x) (!memcmp((x)->s6_addr, in6addr_mapped, 12))
1ccbfca64ae86ace521053773001cb995352f96fBob Halley *** Forward declarations.
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halleystatic int scan_interfaces(int *, int *);
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halleystatic struct hostent * copyandmerge(struct hostent *, struct hostent *,
0e3ad060581e366d3e682caf2dd5d9ea2e0f4893Bob Halley int, int *);
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halleystatic struct hostent * hostfromaddr(lwres_gnbaresponse_t *addr, int af,
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley const void *src);
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halleystatic struct hostent * hostfromname(lwres_gabnresponse_t *name, int af);
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley *** Public functions.
0e3ad060581e366d3e682caf2dd5d9ea2e0f4893Bob Halley * AI_V4MAPPED + AF_INET6
1ccbfca64ae86ace521053773001cb995352f96fBob Halley * If no IPv6 address then a query for IPv4 and map returned values.
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley * AI_ALL + AI_V4MAPPED + AF_INET6
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley * Return IPv6 and IPv4 mapped.
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley * AI_ADDRCONFIG
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley * Only return IPv6 / IPv4 address if there is an interface of that
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley * type active.
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halleygetipnodebyname(const char *name, int af, int flags, int *error_num) {
1ccbfca64ae86ace521053773001cb995352f96fBob Halley struct hostent he, *he1 = NULL, *he2 = NULL, *he3 = NULL;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley /* If we care about active interfaces then check. */
1ccbfca64ae86ace521053773001cb995352f96fBob Halley /* Check for literal address. */
1ccbfca64ae86ace521053773001cb995352f96fBob Halley /* Impossible combination? */
1ccbfca64ae86ace521053773001cb995352f96fBob Halley if ((af == AF_INET6 && (flags & AI_V4MAPPED) == 0 && v4 == 1) ||
1ccbfca64ae86ace521053773001cb995352f96fBob Halley /* Literal address? */
d549c3734869b48e740c64e80890bcb6f3ce672cJames Brister he.h_addr_list[0] = (v4 == 1) ? (char *)&in4 : (char *)&in6;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley n = lwres_context_create(&lwrctx, NULL, NULL, NULL);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley if (n != 0) {
1ccbfca64ae86ace521053773001cb995352f96fBob Halley n = lwres_getaddrsbyname(lwrctx, name, LWRES_ADDRTYPE_V6, &by);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley if (n == 0) {
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halley n = lwres_getaddrsbyname(lwrctx, name, LWRES_ADDRTYPE_V4, &by);
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halley if (n == 0) {
48481c9b6e19501457bcbc2995555412f352b99fBob Halleygetipnodebyaddr(const void *src, size_t len, int af, int *error_num) {
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff /* Sanity Checks. */
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley * Lookup IPv4 and IPv4 mapped/compatible addresses
bad8294771671374e811afac79a20cc6927e3e2fBob Halley if ((af == AF_INET6 && IN6_IS_ADDR_V4COMPAT((struct in6_addr *)src)) ||
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff (af == AF_INET6 && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)src)) ||
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley n = lwres_context_create(&lwrctx, NULL, NULL, NULL);
b03b67a6f1ea2966367e7beb2ef276ed6a1d3f92Bob Halley n = lwres_getnamebyaddr(lwrctx, LWRES_ADDRTYPE_V4,
b03b67a6f1ea2966367e7beb2ef276ed6a1d3f92Bob Halley if (n != 0) {
27ffc5a69779c3c7224580a89aa2bf0a3ff8c16dBob Halley /* Convert from AF_INET to AF_INET6 */
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley * Restore original address.
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff * Lookup IPv6 address.
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson if (memcmp((struct in6_addr *)src, &in6addr_any, IN6ADDRSZ) == 0) {
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson n = lwres_context_create(&lwrctx, NULL, NULL, NULL);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson n = lwres_getnamebyaddr(lwrctx, LWRES_ADDRTYPE_V6, IN6ADDRSZ,
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley if (n != 0) {
b8862d5130b88e7b1a257997d7909f769716d51cBob Halley * Scan the interface table and set have_v4 and have_v6 depending
b8862d5130b88e7b1a257997d7909f769716d51cBob Halley * upon whether there are IPv4 and IPv6 interface addresses.
b8862d5130b88e7b1a257997d7909f769716d51cBob Halley * 0 on success
1ccbfca64ae86ace521053773001cb995352f96fBob Halley * -1 on failure.
1ccbfca64ae86ace521053773001cb995352f96fBob Halley /* Set to zero. Used as loop terminators below. */
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley /* Get interface list from system. */
1ccbfca64ae86ace521053773001cb995352f96fBob Halley * Grow buffer until large enough to contain all interface
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley * descriptions.
1ccbfca64ae86ace521053773001cb995352f96fBob Halley * This is a fix for IRIX OS in which the call to ioctl with
1ccbfca64ae86ace521053773001cb995352f96fBob Halley * the flag SIOCGIFCONF may not return an entry for all the
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff * interfaces like most flavors of Unix.
d2615909402705135d0560ad9d11f4302053c17cBob Halley if ((n = ioctl(s, SIOCGIFCONF, (char *)&ifc)) != -1) {
e7e2e948e37a0eeb93b0d4f2390f38ed2d9dcd82Bob Halley * Some OS's just return what will fit rather
e7e2e948e37a0eeb93b0d4f2390f38ed2d9dcd82Bob Halley * than set EINVAL if the buffer is too small
e7e2e948e37a0eeb93b0d4f2390f38ed2d9dcd82Bob Halley * to fit all the interfaces in. If
e7e2e948e37a0eeb93b0d4f2390f38ed2d9dcd82Bob Halley * ifc.ifc_len is too near to the end of the
e7e2e948e37a0eeb93b0d4f2390f38ed2d9dcd82Bob Halley * buffer we will grow it just in case and
9acbfdb6a2f70d84107ccd99b24a2e523a48259bBob Halley /* Parse system's interface list. */
9acbfdb6a2f70d84107ccd99b24a2e523a48259bBob Halley cplim = buf + ifc.ifc_len; /* skip over if's with big ifr_addr's */
9acbfdb6a2f70d84107ccd99b24a2e523a48259bBob Halley if (ifreq.ifr_addr.sa_len > sizeof (struct sockaddr))
9acbfdb6a2f70d84107ccd99b24a2e523a48259bBob Halley (int)(sizeof (struct sockaddr));
9acbfdb6a2f70d84107ccd99b24a2e523a48259bBob Halley cpsize = sizeof ifreq.ifr_name + ifreq.ifr_addr.sa_len;
9acbfdb6a2f70d84107ccd99b24a2e523a48259bBob Halley#endif /* HAVE_MINIMUM_IFREQ */
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley /* XXX maybe this should be a hard error? */
097c31fdea44383b7ce95345a66489040ad5e333Bob Halley if (s != -1)
097c31fdea44383b7ce95345a66489040ad5e333Bob Halley return (-1);
097c31fdea44383b7ce95345a66489040ad5e333Bob Halleystatic struct hostent *
097c31fdea44383b7ce95345a66489040ad5e333Bob Halleycopyandmerge(struct hostent *he1, struct hostent *he2, int af, int *error_num) {
8c65ae482a50bed3184026301c6f99f32a683dbfBob Halley * Work out array sizes;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley he->h_addr_list = malloc(sizeof(char *) * (addresses));
efe6d8f0665b466052910e8efd4b031dc048f196Bob Halley memset(he->h_addr_list, 0, sizeof(char *) * (addresses));
efe6d8f0665b466052910e8efd4b031dc048f196Bob Halley /* copy addresses */
efe6d8f0665b466052910e8efd4b031dc048f196Bob Halley *npp = malloc((af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
efe6d8f0665b466052910e8efd4b031dc048f196Bob Halley /* convert to mapped if required */
63e6086ef99eca768a4cd69871038181251905bbBob Halley if (af == AF_INET6 && he1->h_addrtype == AF_INET) {
64e829fffb8d95e7507079767ef68327b4a7b4caBob Halley *npp = malloc((af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
302d9bebb54ad8c5a3e2108698215a0e98e06a32Bob Halley /* convert to mapped if required */
7f705ac9a20e82264113e561a515d54dde5bcea3Bob Halley if (af == AF_INET6 && he2->h_addrtype == AF_INET) {
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley he->h_aliases = malloc(sizeof(char *) * (names));
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley memset(he->h_aliases, 0, sizeof(char *) * (names));
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley /* copy aliases */
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley cpp = (he1 != NULL) ? he1->h_aliases : he2->h_aliases;
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff /* copy hostname */
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley strcpy(he->h_name, (he1 != NULL) ? he1->h_name : he2->h_name);
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley /* set address type and length */
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley he->h_length = (af == AF_INET) ? INADDRSZ : IN6ADDRSZ;
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;
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);