diff options
Diffstat (limited to 'lib/liblwres/getipnode.c')
-rw-r--r-- | lib/liblwres/getipnode.c | 839 |
1 files changed, 0 insertions, 839 deletions
diff --git a/lib/liblwres/getipnode.c b/lib/liblwres/getipnode.c deleted file mode 100644 index 94882cbe4..000000000 --- a/lib/liblwres/getipnode.c +++ /dev/null @@ -1,839 +0,0 @@ -/* - * Copyright (C) 1999-2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM - * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL - * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: getipnode.c,v 1.1 2004/03/15 20:35:25 as Exp $ */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <lwres/lwres.h> -#include <lwres/net.h> -#include <lwres/netdb.h> /* XXX #include <netdb.h> */ - -#include "assert_p.h" - -#ifndef INADDRSZ -#define INADDRSZ 4 -#endif -#ifndef IN6ADDRSZ -#define IN6ADDRSZ 16 -#endif - -#ifdef LWRES_PLATFORM_NEEDIN6ADDRANY -LIBLWRES_EXTERNAL_DATA const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; -#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 -}; -#define IN6_IS_ADDR_V4COMPAT(x) (!memcmp((x)->s6_addr, in6addr_compat, 12) && \ - ((x)->s6_addr[12] != 0 || \ - (x)->s6_addr[13] != 0 || \ - (x)->s6_addr[14] != 0 || \ - ((x)->s6_addr[15] != 0 && \ - (x)->s6_addr[15] != 1))) -#endif -#ifndef IN6_IS_ADDR_V4MAPPED -#define IN6_IS_ADDR_V4MAPPED(x) (!memcmp((x)->s6_addr, in6addr_mapped, 12)) -#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 *); - -static struct hostent * -copyandmerge(struct hostent *, struct hostent *, int, int *); - -static struct hostent * -hostfromaddr(lwres_gnbaresponse_t *addr, int af, const void *src); - -static struct hostent * -hostfromname(lwres_gabnresponse_t *name, int af); - -/*** - *** 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 * -lwres_getipnodebyname(const char *name, int af, int flags, int *error_num) { - int have_v4 = 1, have_v6 = 1; - struct in_addr in4; - struct in6_addr in6; - struct hostent he, *he1 = NULL, *he2 = NULL, *he3 = NULL; - int v4 = 0, v6 = 0; - int tmp_err; - lwres_context_t *lwrctx = NULL; - lwres_gabnresponse_t *by = NULL; - int n; - - /* - * If we care about active interfaces then check. - */ - if ((flags & AI_ADDRCONFIG) != 0) - if (scan_interfaces(&have_v4, &have_v6) == -1) { - *error_num = NO_RECOVERY; - return (NULL); - } - - /* Check for literal address. */ - if ((v4 = lwres_net_pton(AF_INET, name, &in4)) != 1) - v6 = lwres_net_pton(AF_INET6, name, &in6); - - /* - * Impossible combination? - */ - if ((af == AF_INET6 && (flags & AI_V4MAPPED) == 0 && v4 == 1) || - (af == AF_INET && v6 == 1) || - (have_v4 == 0 && v4 == 1) || - (have_v6 == 0 && v6 == 1) || - (have_v4 == 0 && af == AF_INET) || - (have_v6 == 0 && af == AF_INET6 && - (((flags & AI_V4MAPPED) != 0 && have_v4) || - (flags & AI_V4MAPPED) == 0))) { - *error_num = HOST_NOT_FOUND; - return (NULL); - } - - /* - * Literal address? - */ - if (v4 == 1 || v6 == 1) { - char *addr_list[2]; - char *aliases[1]; - union { - const char *const_name; - char *deconst_name; - } u; - - u.const_name = name; - he.h_name = u.deconst_name; - he.h_addr_list = addr_list; - he.h_addr_list[0] = (v4 == 1) ? (char *)&in4 : (char *)&in6; - he.h_addr_list[1] = NULL; - he.h_aliases = aliases; - he.h_aliases[0] = NULL; - he.h_length = (v4 == 1) ? INADDRSZ : IN6ADDRSZ; - he.h_addrtype = (v4 == 1) ? AF_INET : AF_INET6; - return (copyandmerge(&he, NULL, af, error_num)); - } - - n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0); - if (n != 0) { - *error_num = NO_RECOVERY; - goto cleanup; - } - (void) lwres_conf_parse(lwrctx, lwres_resolv_conf); - tmp_err = NO_RECOVERY; - if (have_v6 && af == AF_INET6) { - - n = lwres_getaddrsbyname(lwrctx, name, LWRES_ADDRTYPE_V6, &by); - if (n == 0) { - he1 = hostfromname(by, AF_INET6); - lwres_gabnresponse_free(lwrctx, &by); - if (he1 == NULL) { - *error_num = NO_RECOVERY; - goto cleanup; - } - } else { - tmp_err = HOST_NOT_FOUND; - } - } - - if (have_v4 && - ((af == AF_INET) || - (af == AF_INET6 && (flags & AI_V4MAPPED) != 0 && - (he1 == NULL || (flags & AI_ALL) != 0)))) { - n = lwres_getaddrsbyname(lwrctx, name, LWRES_ADDRTYPE_V4, &by); - if (n == 0) { - he2 = hostfromname(by, AF_INET); - lwres_gabnresponse_free(lwrctx, &by); - if (he2 == NULL) { - *error_num = NO_RECOVERY; - goto cleanup; - } - } else if (he1 == NULL) { - if (n == LWRES_R_NOTFOUND) - *error_num = HOST_NOT_FOUND; - else - *error_num = NO_RECOVERY; - goto cleanup; - } - } else - *error_num = tmp_err; - - he3 = copyandmerge(he1, he2, af, error_num); - - cleanup: - if (he1 != NULL) - lwres_freehostent(he1); - if (he2 != NULL) - lwres_freehostent(he2); - if (lwrctx != NULL) { - lwres_conf_clear(lwrctx); - lwres_context_destroy(&lwrctx); - } - return (he3); -} - -struct hostent * -lwres_getipnodebyaddr(const void *src, size_t len, int af, int *error_num) { - struct hostent *he1, *he2; - lwres_context_t *lwrctx = NULL; - lwres_gnbaresponse_t *by = NULL; - lwres_result_t n; - union { - const void *konst; - struct in6_addr *in6; - } u; - - /* - * Sanity checks. - */ - if (src == NULL) { - *error_num = NO_RECOVERY; - return (NULL); - } - - switch (af) { - case AF_INET: - if (len != INADDRSZ) { - *error_num = NO_RECOVERY; - return (NULL); - } - break; - case AF_INET6: - if (len != IN6ADDRSZ) { - *error_num = NO_RECOVERY; - return (NULL); - } - break; - default: - *error_num = NO_RECOVERY; - return (NULL); - } - - /* - * The de-"const"-ing game is done because at least one - * vendor's system (RedHat 6.0) defines the IN6_IS_ADDR_* - * macros in such a way that they discard the const with - * internal casting, and gcc ends up complaining. Rather - * than replacing their own (possibly optimized) definitions - * with our own, cleanly discarding the const is the easiest - * thing to do. - */ - u.konst = src; - - /* - * Look up IPv4 and IPv4 mapped/compatible addresses. - */ - if ((af == AF_INET6 && IN6_IS_ADDR_V4COMPAT(u.in6)) || - (af == AF_INET6 && IN6_IS_ADDR_V4MAPPED(u.in6)) || - (af == AF_INET)) { - const unsigned char *cp = src; - - if (af == AF_INET6) - cp += 12; - n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0); - if (n == LWRES_R_SUCCESS) - (void) lwres_conf_parse(lwrctx, lwres_resolv_conf); - if (n == LWRES_R_SUCCESS) - n = lwres_getnamebyaddr(lwrctx, LWRES_ADDRTYPE_V4, - INADDRSZ, cp, &by); - if (n != LWRES_R_SUCCESS) { - lwres_conf_clear(lwrctx); - lwres_context_destroy(&lwrctx); - if (n == LWRES_R_NOTFOUND) - *error_num = HOST_NOT_FOUND; - else - *error_num = NO_RECOVERY; - return (NULL); - } - he1 = hostfromaddr(by, AF_INET, cp); - lwres_gnbaresponse_free(lwrctx, &by); - lwres_conf_clear(lwrctx); - lwres_context_destroy(&lwrctx); - if (af != AF_INET6) - return (he1); - - /* - * Convert from AF_INET to AF_INET6. - */ - he2 = copyandmerge(he1, NULL, af, error_num); - lwres_freehostent(he1); - if (he2 == NULL) - return (NULL); - /* - * Restore original address. - */ - memcpy(he2->h_addr, src, len); - return (he2); - } - - /* - * Lookup IPv6 address. - */ - if (memcmp(src, &in6addr_any, IN6ADDRSZ) == 0) { - *error_num = HOST_NOT_FOUND; - return (NULL); - } - - n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0); - if (n == LWRES_R_SUCCESS) - (void) lwres_conf_parse(lwrctx, lwres_resolv_conf); - if (n == LWRES_R_SUCCESS) - n = lwres_getnamebyaddr(lwrctx, LWRES_ADDRTYPE_V6, IN6ADDRSZ, - src, &by); - if (n != 0) { - *error_num = HOST_NOT_FOUND; - return (NULL); - } - he1 = hostfromaddr(by, AF_INET6, src); - lwres_gnbaresponse_free(lwrctx, &by); - if (he1 == NULL) - *error_num = NO_RECOVERY; - lwres_context_destroy(&lwrctx); - return (he1); -} - -void -lwres_freehostent(struct hostent *he) { - char **cpp; - int names = 1; - int addresses = 1; - - free(he->h_name); - - cpp = he->h_addr_list; - while (*cpp != NULL) { - free(*cpp); - *cpp = NULL; - cpp++; - addresses++; - } - - cpp = he->h_aliases; - while (*cpp != NULL) { - free(*cpp); - cpp++; - names++; - } - - free(he->h_aliases); - free(he->h_addr_list); - free(he); -} - -/* - * 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 -scan_interfaces(int *have_v4, int *have_v6) { -#if 1 - *have_v4 = *have_v6 = 1; - return (0); -#else - struct ifconf ifc; - struct ifreq ifreq; - struct in_addr in4; - struct in6_addr in6; - char *buf = NULL, *cp, *cplim; - static int bufsiz = 4095; - int s, cpsize, n; - - /* - * Set to zero. Used as loop terminators below. - */ - *have_v4 = *have_v6 = 0; - - /* - * Get interface list from system. - */ - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) - goto err_ret; - - /* - * Grow buffer until large enough to contain all interface - * descriptions. - */ - for (;;) { - buf = malloc(bufsiz); - if (buf == NULL) - goto err_ret; - ifc.ifc_len = bufsiz; - ifc.ifc_buf = buf; -#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 - if ((n = ioctl(s, SIOCGIFCONF, (char *)&ifc)) != -1) { - /* - * 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. - */ - if (ifc.ifc_len + 2 * sizeof(ifreq) < bufsiz) - break; - } -#endif - if ((n == -1) && errno != EINVAL) - goto err_ret; - - if (bufsiz > 1000000) - goto err_ret; - - free(buf); - bufsiz += 4096; - } - - /* - * Parse system's interface list. - */ - cplim = buf + ifc.ifc_len; /* skip over if's with big ifr_addr's */ - for (cp = buf; - (*have_v4 == 0 || *have_v6 == 0) && cp < cplim; - cp += cpsize) { - memcpy(&ifreq, cp, sizeof ifreq); -#ifdef LWRES_PLATFORM_HAVESALEN -#ifdef FIX_ZERO_SA_LEN - if (ifreq.ifr_addr.sa_len == 0) - ifreq.ifr_addr.sa_len = IN6ADDRSZ; -#endif -#ifdef HAVE_MINIMUM_IFREQ - cpsize = sizeof ifreq; - if (ifreq.ifr_addr.sa_len > sizeof (struct sockaddr)) - cpsize += (int)ifreq.ifr_addr.sa_len - - (int)(sizeof(struct sockaddr)); -#else - cpsize = sizeof ifreq.ifr_name + ifreq.ifr_addr.sa_len; -#endif /* HAVE_MINIMUM_IFREQ */ -#elif defined SIOCGIFCONF_ADDR - cpsize = sizeof ifreq; -#else - cpsize = sizeof ifreq.ifr_name; - /* XXX maybe this should be a hard error? */ - if (ioctl(s, SIOCGIFADDR, (char *)&ifreq) < 0) - continue; -#endif /* LWRES_PLATFORM_HAVESALEN */ - switch (ifreq.ifr_addr.sa_family) { - case AF_INET: - if (*have_v4 == 0) { - memcpy(&in4, - &((struct sockaddr_in *) - &ifreq.ifr_addr)->sin_addr, - sizeof(in4)); - if (in4.s_addr == INADDR_ANY) - break; - n = ioctl(s, SIOCGIFFLAGS, (char *)&ifreq); - if (n < 0) - break; - if ((ifreq.ifr_flags & IFF_UP) == 0) - break; - *have_v4 = 1; - } - break; - case AF_INET6: - if (*have_v6 == 0) { - memcpy(&in6, - &((struct sockaddr_in6 *) - &ifreq.ifr_addr)->sin6_addr, - sizeof(in6)); - if (memcmp(&in6, &in6addr_any, - sizeof(in6)) == 0) - break; - n = ioctl(s, SIOCGIFFLAGS, (char *)&ifreq); - if (n < 0) - break; - if ((ifreq.ifr_flags & IFF_UP) == 0) - break; - *have_v6 = 1; - } - break; - } - } - if (buf != NULL) - free(buf); - close(s); - return (0); - err_ret: - if (buf != NULL) - free(buf); - if (s != -1) - close(s); - return (-1); -#endif -} - -static struct hostent * -copyandmerge(struct hostent *he1, struct hostent *he2, int af, int *error_num) -{ - struct hostent *he = NULL; - int addresses = 1; /* NULL terminator */ - int names = 1; /* NULL terminator */ - int len = 0; - char **cpp, **npp; - - /* - * Work out array sizes. - */ - if (he1 != NULL) { - cpp = he1->h_addr_list; - while (*cpp != NULL) { - addresses++; - cpp++; - } - cpp = he1->h_aliases; - while (*cpp != NULL) { - names++; - cpp++; - } - } - - if (he2 != NULL) { - cpp = he2->h_addr_list; - while (*cpp != NULL) { - addresses++; - cpp++; - } - if (he1 == NULL) { - cpp = he2->h_aliases; - while (*cpp != NULL) { - names++; - cpp++; - } - } - } - - if (addresses == 1) { - *error_num = NO_ADDRESS; - return (NULL); - } - - he = malloc(sizeof *he); - if (he == NULL) - goto no_recovery; - - he->h_addr_list = malloc(sizeof(char *) * (addresses)); - if (he->h_addr_list == NULL) - goto cleanup0; - memset(he->h_addr_list, 0, sizeof(char *) * (addresses)); - - /* - * Copy addresses. - */ - npp = he->h_addr_list; - if (he1 != NULL) { - cpp = he1->h_addr_list; - while (*cpp != NULL) { - *npp = malloc((af == AF_INET) ? INADDRSZ : IN6ADDRSZ); - if (*npp == NULL) - goto cleanup1; - /* - * Convert to mapped if required. - */ - if (af == AF_INET6 && he1->h_addrtype == AF_INET) { - memcpy(*npp, in6addr_mapped, - sizeof in6addr_mapped); - memcpy(*npp + sizeof in6addr_mapped, *cpp, - INADDRSZ); - } else { - memcpy(*npp, *cpp, - (af == AF_INET) ? INADDRSZ : IN6ADDRSZ); - } - cpp++; - npp++; - } - } - - if (he2 != NULL) { - cpp = he2->h_addr_list; - while (*cpp != NULL) { - *npp = malloc((af == AF_INET) ? INADDRSZ : IN6ADDRSZ); - if (*npp == NULL) - goto cleanup1; - /* - * Convert to mapped if required. - */ - if (af == AF_INET6 && he2->h_addrtype == AF_INET) { - memcpy(*npp, in6addr_mapped, - sizeof in6addr_mapped); - memcpy(*npp + sizeof in6addr_mapped, *cpp, - INADDRSZ); - } else { - memcpy(*npp, *cpp, - (af == AF_INET) ? INADDRSZ : IN6ADDRSZ); - } - cpp++; - npp++; - } - } - - he->h_aliases = malloc(sizeof(char *) * (names)); - if (he->h_aliases == NULL) - goto cleanup1; - memset(he->h_aliases, 0, sizeof(char *) * (names)); - - /* - * Copy aliases. - */ - npp = he->h_aliases; - cpp = (he1 != NULL) ? he1->h_aliases : he2->h_aliases; - while (*cpp != NULL) { - len = strlen (*cpp) + 1; - *npp = malloc(len); - if (*npp == NULL) - goto cleanup2; - strcpy(*npp, *cpp); - npp++; - cpp++; - } - - /* - * Copy hostname. - */ - he->h_name = malloc(strlen((he1 != NULL) ? - he1->h_name : he2->h_name) + 1); - if (he->h_name == NULL) - goto cleanup2; - strcpy(he->h_name, (he1 != NULL) ? he1->h_name : he2->h_name); - - /* - * Set address type and length. - */ - he->h_addrtype = af; - he->h_length = (af == AF_INET) ? INADDRSZ : IN6ADDRSZ; - return (he); - - cleanup2: - cpp = he->h_aliases; - while (*cpp != NULL) { - free(*cpp); - cpp++; - } - free(he->h_aliases); - - cleanup1: - cpp = he->h_addr_list; - while (*cpp != NULL) { - free(*cpp); - *cpp = NULL; - cpp++; - } - free(he->h_addr_list); - - cleanup0: - free(he); - - no_recovery: - *error_num = NO_RECOVERY; - return (NULL); -} - -static struct hostent * -hostfromaddr(lwres_gnbaresponse_t *addr, int af, const void *src) { - struct hostent *he; - int i; - - he = malloc(sizeof *he); - if (he == NULL) - goto cleanup; - memset(he, 0, sizeof(*he)); - - /* - * Set family and length. - */ - he->h_addrtype = af; - switch (af) { - case AF_INET: - he->h_length = INADDRSZ; - break; - case AF_INET6: - he->h_length = IN6ADDRSZ; - break; - default: - INSIST(0); - } - - /* - * Copy name. - */ - he->h_name = strdup(addr->realname); - if (he->h_name == NULL) - goto cleanup; - - /* - * Copy aliases. - */ - he->h_aliases = malloc(sizeof(char *) * (addr->naliases + 1)); - if (he->h_aliases == NULL) - goto cleanup; - for (i = 0 ; i < addr->naliases; i++) { - he->h_aliases[i] = strdup(addr->aliases[i]); - if (he->h_aliases[i] == NULL) - goto cleanup; - } - he->h_aliases[i] = NULL; - - /* - * Copy address. - */ - he->h_addr_list = malloc(sizeof(char *) * 2); - if (he->h_addr_list == NULL) - goto cleanup; - he->h_addr_list[0] = malloc(he->h_length); - if (he->h_addr_list[0] == NULL) - goto cleanup; - memcpy(he->h_addr_list[0], src, he->h_length); - he->h_addr_list[1] = NULL; - return (he); - - cleanup: - if (he != NULL && he->h_addr_list != NULL) { - for (i = 0; he->h_addr_list[i] != NULL; i++) - free(he->h_addr_list[i]); - free(he->h_addr_list); - } - if (he != NULL && he->h_aliases != NULL) { - for (i = 0; he->h_aliases[i] != NULL; i++) - free(he->h_aliases[i]); - free(he->h_aliases); - } - if (he != NULL && he->h_name != NULL) - free(he->h_name); - if (he != NULL) - free(he); - return (NULL); -} - -static struct hostent * -hostfromname(lwres_gabnresponse_t *name, int af) { - struct hostent *he; - int i; - lwres_addr_t *addr; - - he = malloc(sizeof *he); - if (he == NULL) - goto cleanup; - memset(he, 0, sizeof(*he)); - - /* - * Set family and length. - */ - he->h_addrtype = af; - switch (af) { - case AF_INET: - he->h_length = INADDRSZ; - break; - case AF_INET6: - he->h_length = IN6ADDRSZ; - break; - default: - INSIST(0); - } - - /* - * Copy name. - */ - he->h_name = strdup(name->realname); - if (he->h_name == NULL) - goto cleanup; - - /* - * Copy aliases. - */ - he->h_aliases = malloc(sizeof(char *) * (name->naliases + 1)); - for (i = 0 ; i < name->naliases; i++) { - he->h_aliases[i] = strdup(name->aliases[i]); - if (he->h_aliases[i] == NULL) - goto cleanup; - } - he->h_aliases[i] = NULL; - - /* - * Copy addresses. - */ - he->h_addr_list = malloc(sizeof(char *) * (name->naddrs + 1)); - addr = LWRES_LIST_HEAD(name->addrs); - i = 0; - while (addr != NULL) { - he->h_addr_list[i] = malloc(he->h_length); - if (he->h_addr_list[i] == NULL) - goto cleanup; - memcpy(he->h_addr_list[i], addr->address, he->h_length); - addr = LWRES_LIST_NEXT(addr, link); - i++; - } - he->h_addr_list[i] = NULL; - return (he); - - cleanup: - if (he != NULL && he->h_addr_list != NULL) { - for (i = 0; he->h_addr_list[i] != NULL; i++) - free(he->h_addr_list[i]); - free(he->h_addr_list); - } - if (he != NULL && he->h_aliases != NULL) { - for (i = 0; he->h_aliases[i] != NULL; i++) - free(he->h_aliases[i]); - free(he->h_aliases); - } - if (he != NULL && he->h_name != NULL) - free(he->h_name); - if (he != NULL) - free(he); - return (NULL); -} |