getipnode.c revision 37d266d288410d1ead241c02a8a1dbcb0160be46
1ccbfca64ae86ace521053773001cb995352f96fBob Halley/*
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley * Copyright (C) 1999, 2000 Internet Software Consortium.
1ccbfca64ae86ace521053773001cb995352f96fBob Halley *
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 *
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
1ccbfca64ae86ace521053773001cb995352f96fBob Halley * SOFTWARE.
1ccbfca64ae86ace521053773001cb995352f96fBob Halley */
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley#include <sys/types.h>
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley#include <sys/socket.h>
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley#include <netinet/in.h>
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
1ccbfca64ae86ace521053773001cb995352f96fBob Halley#include <stdio.h>
1ccbfca64ae86ace521053773001cb995352f96fBob Halley#include <stdlib.h>
1ccbfca64ae86ace521053773001cb995352f96fBob Halley#include <string.h>
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
1ccbfca64ae86ace521053773001cb995352f96fBob Halley#include <lwres/lwres.h>
d549c3734869b48e740c64e80890bcb6f3ce672cJames Brister#include <lwres/netdb.h> /* XXX #include <netdb.h> */
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
1ccbfca64ae86ace521053773001cb995352f96fBob Halley#include "assert_p.h"
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley#ifndef INADDRSZ
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley#define INADDRSZ 4
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley#endif
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley#ifndef IN6ADDRSZ
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley#define IN6ADDRSZ 16
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley#endif
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley#ifndef IN6_IS_ADDR_V4COMPAT
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 ((x)->s6_addr[12] != 0 || \
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley (x)->s6_addr[13] != 0 || \
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley (x)->s6_addr[14] != 0 || \
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley ((x)->s6_addr[15] != 0 && \
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley (x)->s6_addr[15] != 1)))
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley#endif
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley#ifndef IN6_IS_ADDR_V4MAPPED
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley#define IN6_IS_ADDR_V4MAPPED(x) (!memcmp((x)->s6_addr, in6addr_mapped, 12))
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley#endif
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halleystatic const unsigned char in6addr_mapped[12] = {
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
1ccbfca64ae86ace521053773001cb995352f96fBob Halley/***
1ccbfca64ae86ace521053773001cb995352f96fBob Halley *** Forward declarations.
0e3ad060581e366d3e682caf2dd5d9ea2e0f4893Bob Halley ***/
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
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
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley/***
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley *** Public functions.
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley ***/
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley/*
0e3ad060581e366d3e682caf2dd5d9ea2e0f4893Bob Halley * AI_V4MAPPED + AF_INET6
1ccbfca64ae86ace521053773001cb995352f96fBob Halley * If no IPv6 address then a query for IPv4 and map returned values.
1ccbfca64ae86ace521053773001cb995352f96fBob Halley *
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley * AI_ALL + AI_V4MAPPED + AF_INET6
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley * Return IPv6 and IPv4 mapped.
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley *
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley * AI_ADDRCONFIG
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley * Only return IPv6 / IPv4 address if there is an interface of that
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley * type active.
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley */
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
1ccbfca64ae86ace521053773001cb995352f96fBob Halleystruct hostent *
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halleygetipnodebyname(const char *name, int af, int flags, int *error_num) {
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley int have_v4 = 1, have_v6 = 1;
0e3ad060581e366d3e682caf2dd5d9ea2e0f4893Bob Halley struct in_addr in4;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley struct in6_addr in6;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley struct hostent he, *he1 = NULL, *he2 = NULL, *he3 = NULL;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley int v4 = 0, v6 = 0;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley int tmp_err;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley lwres_context_t *lwrctx = NULL;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley lwres_gabnresponse_t *by = NULL;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley int n;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley /* If we care about active interfaces then check. */
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley if ((flags & AI_ADDRCONFIG) != 0)
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley if (scan_interfaces(&have_v4, &have_v6) == -1) {
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley *error_num = NO_RECOVERY;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley return (NULL);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley }
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
1ccbfca64ae86ace521053773001cb995352f96fBob Halley /* Check for literal address. */
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley if ((v4 = inet_pton(AF_INET, name, &in4)) != 1)
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley v6 = inet_pton(AF_INET6, name, &in6);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
1ccbfca64ae86ace521053773001cb995352f96fBob Halley /* Impossible combination? */
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
1ccbfca64ae86ace521053773001cb995352f96fBob Halley if ((af == AF_INET6 && (flags & AI_V4MAPPED) == 0 && v4 == 1) ||
1ccbfca64ae86ace521053773001cb995352f96fBob Halley (af == AF_INET && v6 == 1) ||
1ccbfca64ae86ace521053773001cb995352f96fBob Halley (have_v4 == 0 && v4 == 1) ||
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley (have_v6 == 0 && v6 == 1) ||
1ccbfca64ae86ace521053773001cb995352f96fBob Halley (have_v4 == 0 && af == AF_INET) ||
1ccbfca64ae86ace521053773001cb995352f96fBob Halley (have_v6 == 0 && af == AF_INET6 &&
1ccbfca64ae86ace521053773001cb995352f96fBob Halley (((flags & AI_V4MAPPED) != 0 && have_v4) ||
1ccbfca64ae86ace521053773001cb995352f96fBob Halley (flags & AI_V4MAPPED) == 0))) {
1ccbfca64ae86ace521053773001cb995352f96fBob Halley *error_num = HOST_NOT_FOUND;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley return (NULL);
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley }
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
1ccbfca64ae86ace521053773001cb995352f96fBob Halley /* Literal address? */
1ccbfca64ae86ace521053773001cb995352f96fBob Halley if (v4 == 1 || v6 == 1) {
d549c3734869b48e740c64e80890bcb6f3ce672cJames Brister char *addr_list[2];
d549c3734869b48e740c64e80890bcb6f3ce672cJames Brister char *aliases[1];
d549c3734869b48e740c64e80890bcb6f3ce672cJames Brister
d549c3734869b48e740c64e80890bcb6f3ce672cJames Brister he.h_name = (char *)name;
d549c3734869b48e740c64e80890bcb6f3ce672cJames Brister he.h_addr_list = addr_list;
d549c3734869b48e740c64e80890bcb6f3ce672cJames Brister he.h_addr_list[0] = (v4 == 1) ? (char *)&in4 : (char *)&in6;
d549c3734869b48e740c64e80890bcb6f3ce672cJames Brister he.h_addr_list[1] = NULL;
d549c3734869b48e740c64e80890bcb6f3ce672cJames Brister he.h_aliases = aliases;
d549c3734869b48e740c64e80890bcb6f3ce672cJames Brister he.h_aliases[0] = NULL;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley he.h_length = (v4 == 1) ? INADDRSZ : IN6ADDRSZ;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley he.h_addrtype = (v4 == 1) ? AF_INET : AF_INET6;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley return (copyandmerge(&he, NULL, af, error_num));
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley }
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley n = lwres_context_create(&lwrctx, NULL, NULL, NULL);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley if (n != 0) {
1ccbfca64ae86ace521053773001cb995352f96fBob Halley *error_num = NO_RECOVERY;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley goto cleanup;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley }
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley tmp_err = NO_RECOVERY;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley if (have_v6 && af == AF_INET6) {
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
1ccbfca64ae86ace521053773001cb995352f96fBob Halley n = lwres_getaddrsbyname(lwrctx, name, LWRES_ADDRTYPE_V6, &by);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley if (n == 0) {
1ccbfca64ae86ace521053773001cb995352f96fBob Halley he1 = hostfromname(by, AF_INET6);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley lwres_gabnresponse_free(lwrctx, &by);
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley if (he1 == NULL) {
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley *error_num = NO_RECOVERY;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley goto cleanup;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley }
1ccbfca64ae86ace521053773001cb995352f96fBob Halley } else {
1ccbfca64ae86ace521053773001cb995352f96fBob Halley tmp_err = HOST_NOT_FOUND;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley }
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley }
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley if (have_v4 &&
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley ((af == AF_INET) ||
1ccbfca64ae86ace521053773001cb995352f96fBob Halley (af == AF_INET6 && (flags & AI_V4MAPPED) != 0 &&
1ccbfca64ae86ace521053773001cb995352f96fBob Halley (he1 == NULL || (flags & AI_ALL) != 0)))) {
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halley n = lwres_getaddrsbyname(lwrctx, name, LWRES_ADDRTYPE_V4, &by);
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halley if (n == 0) {
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halley he2 = hostfromname(by, AF_INET);
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halley lwres_gabnresponse_free(lwrctx, &by);
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halley if (he2 == NULL) {
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halley *error_num = NO_RECOVERY;
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halley goto cleanup;
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halley }
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halley } else if (he1 == NULL) {
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halley *error_num = HOST_NOT_FOUND;
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halley goto cleanup;
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halley }
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halley } else
a99979c686ae04efd55ba8f0aacf32493b4aa7faBob Halley *error_num = tmp_err;
a99979c686ae04efd55ba8f0aacf32493b4aa7faBob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley he3 = copyandmerge(he1, he2, af, error_num);
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley cleanup:
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley if (he1 != NULL)
a99979c686ae04efd55ba8f0aacf32493b4aa7faBob Halley freehostent(he1);
a99979c686ae04efd55ba8f0aacf32493b4aa7faBob Halley if (he2 != NULL)
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley freehostent(he2);
a99979c686ae04efd55ba8f0aacf32493b4aa7faBob Halley if (lwrctx != NULL)
a99979c686ae04efd55ba8f0aacf32493b4aa7faBob Halley lwres_context_destroy(&lwrctx);
48481c9b6e19501457bcbc2995555412f352b99fBob Halley return (he3);
48481c9b6e19501457bcbc2995555412f352b99fBob Halley}
48481c9b6e19501457bcbc2995555412f352b99fBob Halley
48481c9b6e19501457bcbc2995555412f352b99fBob Halleystruct hostent *
48481c9b6e19501457bcbc2995555412f352b99fBob Halleygetipnodebyaddr(const void *src, size_t len, int af, int *error_num) {
48481c9b6e19501457bcbc2995555412f352b99fBob Halley struct hostent *he1, *he2;
48481c9b6e19501457bcbc2995555412f352b99fBob Halley lwres_context_t *lwrctx = NULL;
48481c9b6e19501457bcbc2995555412f352b99fBob Halley lwres_gnbaresponse_t *by = NULL;
48481c9b6e19501457bcbc2995555412f352b99fBob Halley int n;
48481c9b6e19501457bcbc2995555412f352b99fBob Halley
48481c9b6e19501457bcbc2995555412f352b99fBob Halley
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff /* Sanity Checks. */
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley if (src == NULL) {
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley *error_num = NO_RECOVERY;
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley return (NULL);
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley }
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley switch (af) {
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley case AF_INET:
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley if (len != INADDRSZ) {
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley *error_num = NO_RECOVERY;
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley return (NULL);
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley }
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley break;
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley case AF_INET6:
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff if (len != IN6ADDRSZ) {
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley *error_num = NO_RECOVERY;
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley return (NULL);
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley }
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley break;
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley default:
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley *error_num = NO_RECOVERY;
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley return (NULL);
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley }
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley /*
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley * Lookup IPv4 and IPv4 mapped/compatible addresses
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff */
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)) ||
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley (af == AF_INET)) {
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley const unsigned char *cp = src;
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley if (af == AF_INET6)
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley cp += 12;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley n = lwres_context_create(&lwrctx, NULL, NULL, NULL);
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley if (n == 0)
b03b67a6f1ea2966367e7beb2ef276ed6a1d3f92Bob Halley n = lwres_getnamebyaddr(lwrctx, LWRES_ADDRTYPE_V4,
b03b67a6f1ea2966367e7beb2ef276ed6a1d3f92Bob Halley INADDRSZ, cp, &by);
b03b67a6f1ea2966367e7beb2ef276ed6a1d3f92Bob Halley if (n != 0) {
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley lwres_context_destroy(&lwrctx);
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley *error_num = HOST_NOT_FOUND;
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley return (NULL);
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley }
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley he1 = hostfromaddr(by, AF_INET, cp);
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley lwres_gnbaresponse_free(lwrctx, &by);
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley lwres_context_destroy(&lwrctx);
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley if (af != AF_INET6)
27ffc5a69779c3c7224580a89aa2bf0a3ff8c16dBob Halley return (he1);
27ffc5a69779c3c7224580a89aa2bf0a3ff8c16dBob Halley
27ffc5a69779c3c7224580a89aa2bf0a3ff8c16dBob Halley /* Convert from AF_INET to AF_INET6 */
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley he2 = copyandmerge(he1, NULL, af, error_num);
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley freehostent(he1);
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley if (he2 == NULL)
27ffc5a69779c3c7224580a89aa2bf0a3ff8c16dBob Halley return (NULL);
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley /*
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley * Restore original address.
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley */
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley memcpy(he2->h_addr, src, len);
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley return (he2);
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley }
b03b67a6f1ea2966367e7beb2ef276ed6a1d3f92Bob Halley
b03b67a6f1ea2966367e7beb2ef276ed6a1d3f92Bob Halley /*
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff * Lookup IPv6 address.
bad8294771671374e811afac79a20cc6927e3e2fBob Halley */
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson if (memcmp((struct in6_addr *)src, &in6addr_any, IN6ADDRSZ) == 0) {
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson *error_num = HOST_NOT_FOUND;
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson return (NULL);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson }
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson n = lwres_context_create(&lwrctx, NULL, NULL, NULL);
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley if (n == 0)
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson n = lwres_getnamebyaddr(lwrctx, LWRES_ADDRTYPE_V6, IN6ADDRSZ,
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson src, &by);
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley if (n != 0) {
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley *error_num = HOST_NOT_FOUND;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley return (NULL);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley }
1ccbfca64ae86ace521053773001cb995352f96fBob Halley he1 = hostfromaddr(by, AF_INET6, src);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley lwres_gnbaresponse_free(lwrctx, &by);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley if (he1 == NULL)
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley *error_num = NO_RECOVERY;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley lwres_context_destroy(&lwrctx);
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley return (he1);
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley}
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
0e3ad060581e366d3e682caf2dd5d9ea2e0f4893Bob Halleyvoid
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halleyfreehostent(struct hostent *he) {
1ccbfca64ae86ace521053773001cb995352f96fBob Halley char **cpp;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley int names = 1;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley int addresses = 1;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff free(he->h_name);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
1ccbfca64ae86ace521053773001cb995352f96fBob Halley cpp = he->h_addr_list;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley while (*cpp != NULL) {
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley free(*cpp);
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley *cpp = NULL;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley cpp++;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley addresses++;
0e3ad060581e366d3e682caf2dd5d9ea2e0f4893Bob Halley }
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
1ccbfca64ae86ace521053773001cb995352f96fBob Halley cpp = he->h_aliases;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley while (*cpp != NULL) {
1ccbfca64ae86ace521053773001cb995352f96fBob Halley free(*cpp);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley cpp++;
b8862d5130b88e7b1a257997d7909f769716d51cBob Halley names++;
b8862d5130b88e7b1a257997d7909f769716d51cBob Halley }
b8862d5130b88e7b1a257997d7909f769716d51cBob Halley
b8862d5130b88e7b1a257997d7909f769716d51cBob Halley free(he->h_aliases);
b8862d5130b88e7b1a257997d7909f769716d51cBob Halley free(he->h_addr_list);
b8862d5130b88e7b1a257997d7909f769716d51cBob Halley free(he);
b8862d5130b88e7b1a257997d7909f769716d51cBob Halley}
b8862d5130b88e7b1a257997d7909f769716d51cBob Halley
b8862d5130b88e7b1a257997d7909f769716d51cBob Halley/*
b8862d5130b88e7b1a257997d7909f769716d51cBob Halley * Private
b8862d5130b88e7b1a257997d7909f769716d51cBob Halley */
b8862d5130b88e7b1a257997d7909f769716d51cBob Halley
b8862d5130b88e7b1a257997d7909f769716d51cBob Halley/*
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 *
b8862d5130b88e7b1a257997d7909f769716d51cBob Halley * Returns:
b8862d5130b88e7b1a257997d7909f769716d51cBob Halley * 0 on success
1ccbfca64ae86ace521053773001cb995352f96fBob Halley * -1 on failure.
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley */
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halleystatic int
1ccbfca64ae86ace521053773001cb995352f96fBob Halleyscan_interfaces(int *have_v4, int *have_v6) {
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley#if 1
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley *have_v4 = *have_v6 = 1;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley return (0);
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley#else
1ccbfca64ae86ace521053773001cb995352f96fBob Halley struct ifconf ifc;
0e3ad060581e366d3e682caf2dd5d9ea2e0f4893Bob Halley struct ifreq ifreq;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley struct in_addr in4;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley struct in6_addr in6;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley char *buf = NULL, *cp, *cplim;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley static int bufsiz = 4095;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley int s, cpsize, n;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
1ccbfca64ae86ace521053773001cb995352f96fBob Halley /* Set to zero. Used as loop terminators below. */
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley *have_v4 = *have_v6 = 0;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley /* Get interface list from system. */
1ccbfca64ae86ace521053773001cb995352f96fBob Halley if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff goto err_ret;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
1ccbfca64ae86ace521053773001cb995352f96fBob Halley /*
1ccbfca64ae86ace521053773001cb995352f96fBob Halley * Grow buffer until large enough to contain all interface
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley * descriptions.
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley */
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley for (;;) {
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley buf = malloc(bufsiz);
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley if (buf == NULL)
1ccbfca64ae86ace521053773001cb995352f96fBob Halley goto err_ret;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley ifc.ifc_len = bufsiz;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley ifc.ifc_buf = buf;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley#ifdef IRIX_EMUL_IOCTL_SIOCGIFCONF
1ccbfca64ae86ace521053773001cb995352f96fBob Halley /*
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.
ced5499494f8afba75c056eb2f3933de24a5f360Bob Halley */
63e6086ef99eca768a4cd69871038181251905bbBob Halley if (emul_ioctl(&ifc) >= 0)
ced5499494f8afba75c056eb2f3933de24a5f360Bob Halley break;
732e0731dec1922747bb3b3147cf2c3d16b22eaaBob Halley#else
d2615909402705135d0560ad9d11f4302053c17cBob Halley if ((n = ioctl(s, SIOCGIFCONF, (char *)&ifc)) != -1) {
ced5499494f8afba75c056eb2f3933de24a5f360Bob Halley /*
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
e7e2e948e37a0eeb93b0d4f2390f38ed2d9dcd82Bob Halley * retry.
e7e2e948e37a0eeb93b0d4f2390f38ed2d9dcd82Bob Halley */
e7e2e948e37a0eeb93b0d4f2390f38ed2d9dcd82Bob Halley if (ifc.ifc_len + 2 * sizeof(ifreq) < bufsiz)
739ccd81b011ec3f7b8029000704b1a925df7e65Bob Halley break;
e7e2e948e37a0eeb93b0d4f2390f38ed2d9dcd82Bob Halley }
e7e2e948e37a0eeb93b0d4f2390f38ed2d9dcd82Bob Halley#endif
732e0731dec1922747bb3b3147cf2c3d16b22eaaBob Halley if ((n == -1) && errno != EINVAL)
732e0731dec1922747bb3b3147cf2c3d16b22eaaBob Halley goto err_ret;
732e0731dec1922747bb3b3147cf2c3d16b22eaaBob Halley
e7e2e948e37a0eeb93b0d4f2390f38ed2d9dcd82Bob Halley if (bufsiz > 1000000)
63e6086ef99eca768a4cd69871038181251905bbBob Halley goto err_ret;
732e0731dec1922747bb3b3147cf2c3d16b22eaaBob Halley
ced5499494f8afba75c056eb2f3933de24a5f360Bob Halley free(buf);
ced5499494f8afba75c056eb2f3933de24a5f360Bob Halley bufsiz += 4096;
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff }
9acbfdb6a2f70d84107ccd99b24a2e523a48259bBob Halley
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 for (cp = buf;
9acbfdb6a2f70d84107ccd99b24a2e523a48259bBob Halley (*have_v4 == 0 || *have_v6 == 0) && cp < cplim;
9acbfdb6a2f70d84107ccd99b24a2e523a48259bBob Halley cp += cpsize) {
9acbfdb6a2f70d84107ccd99b24a2e523a48259bBob Halley memcpy(&ifreq, cp, sizeof ifreq);
9acbfdb6a2f70d84107ccd99b24a2e523a48259bBob Halley#ifdef HAVE_SA_LEN
9acbfdb6a2f70d84107ccd99b24a2e523a48259bBob Halley#ifdef FIX_ZERO_SA_LEN
9acbfdb6a2f70d84107ccd99b24a2e523a48259bBob Halley if (ifreq.ifr_addr.sa_len == 0)
9acbfdb6a2f70d84107ccd99b24a2e523a48259bBob Halley ifreq.ifr_addr.sa_len = IN6ADDRSZ;
9acbfdb6a2f70d84107ccd99b24a2e523a48259bBob Halley#endif
9acbfdb6a2f70d84107ccd99b24a2e523a48259bBob Halley#ifdef HAVE_MINIMUM_IFREQ
9acbfdb6a2f70d84107ccd99b24a2e523a48259bBob Halley cpsize = sizeof ifreq;
9acbfdb6a2f70d84107ccd99b24a2e523a48259bBob Halley if (ifreq.ifr_addr.sa_len > sizeof (struct sockaddr))
9acbfdb6a2f70d84107ccd99b24a2e523a48259bBob Halley cpsize += (int)ifreq.ifr_addr.sa_len -
9acbfdb6a2f70d84107ccd99b24a2e523a48259bBob Halley (int)(sizeof (struct sockaddr));
9acbfdb6a2f70d84107ccd99b24a2e523a48259bBob Halley#else
9acbfdb6a2f70d84107ccd99b24a2e523a48259bBob Halley cpsize = sizeof ifreq.ifr_name + ifreq.ifr_addr.sa_len;
9acbfdb6a2f70d84107ccd99b24a2e523a48259bBob Halley#endif /* HAVE_MINIMUM_IFREQ */
9acbfdb6a2f70d84107ccd99b24a2e523a48259bBob Halley#elif defined SIOCGIFCONF_ADDR
1ccbfca64ae86ace521053773001cb995352f96fBob Halley cpsize = sizeof ifreq;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley#else
1ccbfca64ae86ace521053773001cb995352f96fBob Halley cpsize = sizeof ifreq.ifr_name;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley /* XXX maybe this should be a hard error? */
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley if (ioctl(s, SIOCGIFADDR, (char *)&ifreq) < 0)
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley continue;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley#endif
1ccbfca64ae86ace521053773001cb995352f96fBob Halley switch (ifreq.ifr_addr.sa_family) {
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley case AF_INET:
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley if (*have_v4 == 0) {
1ccbfca64ae86ace521053773001cb995352f96fBob Halley memcpy(&in4,
1ccbfca64ae86ace521053773001cb995352f96fBob Halley &((struct sockaddr_in *)
1ccbfca64ae86ace521053773001cb995352f96fBob Halley &ifreq.ifr_addr)->sin_addr, sizeof in4);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley if (in4.s_addr == INADDR_ANY)
1ccbfca64ae86ace521053773001cb995352f96fBob Halley break;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley n = ioctl(s, SIOCGIFFLAGS, (char *)&ifreq);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley if (n < 0)
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley break;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley if ((ifreq.ifr_flags & IFF_UP) == 0)
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley break;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley *have_v4 = 1;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley }
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley break;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley case AF_INET6:
1ccbfca64ae86ace521053773001cb995352f96fBob Halley if (*have_v6 == 0) {
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley memcpy(&in6,
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley &((struct sockaddr_in6 *)
1ccbfca64ae86ace521053773001cb995352f96fBob Halley &ifreq.ifr_addr)->sin6_addr, sizeof in6);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley if (memcmp(&in6, &in6addr_any, sizeof in6) == 0)
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff break;
6e8ec359a45b7e991d7bcc97ed8547eac725a506Bob Halley n = ioctl(s, SIOCGIFFLAGS, (char *)&ifreq);
6e8ec359a45b7e991d7bcc97ed8547eac725a506Bob Halley if (n < 0)
6e8ec359a45b7e991d7bcc97ed8547eac725a506Bob Halley break;
6e8ec359a45b7e991d7bcc97ed8547eac725a506Bob Halley if ((ifreq.ifr_flags & IFF_UP) == 0)
6e8ec359a45b7e991d7bcc97ed8547eac725a506Bob Halley break;
6e8ec359a45b7e991d7bcc97ed8547eac725a506Bob Halley *have_v6 = 1;
6e8ec359a45b7e991d7bcc97ed8547eac725a506Bob Halley }
6e8ec359a45b7e991d7bcc97ed8547eac725a506Bob Halley break;
6e8ec359a45b7e991d7bcc97ed8547eac725a506Bob Halley }
6e8ec359a45b7e991d7bcc97ed8547eac725a506Bob Halley }
6e8ec359a45b7e991d7bcc97ed8547eac725a506Bob Halley if (buf != NULL)
6e8ec359a45b7e991d7bcc97ed8547eac725a506Bob Halley free(buf);
6e8ec359a45b7e991d7bcc97ed8547eac725a506Bob Halley close(s);
097c31fdea44383b7ce95345a66489040ad5e333Bob Halley return (0);
097c31fdea44383b7ce95345a66489040ad5e333Bob Halley err_ret:
097c31fdea44383b7ce95345a66489040ad5e333Bob Halley if (buf != NULL)
097c31fdea44383b7ce95345a66489040ad5e333Bob Halley free(buf);
097c31fdea44383b7ce95345a66489040ad5e333Bob Halley if (s != -1)
097c31fdea44383b7ce95345a66489040ad5e333Bob Halley close(s);
097c31fdea44383b7ce95345a66489040ad5e333Bob Halley return (-1);
097c31fdea44383b7ce95345a66489040ad5e333Bob Halley#endif
097c31fdea44383b7ce95345a66489040ad5e333Bob Halley}
097c31fdea44383b7ce95345a66489040ad5e333Bob Halley
097c31fdea44383b7ce95345a66489040ad5e333Bob Halleystatic struct hostent *
097c31fdea44383b7ce95345a66489040ad5e333Bob Halleycopyandmerge(struct hostent *he1, struct hostent *he2, int af, int *error_num) {
097c31fdea44383b7ce95345a66489040ad5e333Bob Halley struct hostent *he = NULL;
8c65ae482a50bed3184026301c6f99f32a683dbfBob Halley int addresses = 1; /* NULL terminator */
8c65ae482a50bed3184026301c6f99f32a683dbfBob Halley int names = 1; /* NULL terminator */
8c65ae482a50bed3184026301c6f99f32a683dbfBob Halley int len = 0;
8c65ae482a50bed3184026301c6f99f32a683dbfBob Halley char **cpp, **npp;
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff
6bb7b678f50a61dccad0bb3db4c26f73b59d8c16Bob Halley /*
8c65ae482a50bed3184026301c6f99f32a683dbfBob Halley * Work out array sizes;
8c65ae482a50bed3184026301c6f99f32a683dbfBob Halley */
8c65ae482a50bed3184026301c6f99f32a683dbfBob Halley if (he1 != NULL) {
8c65ae482a50bed3184026301c6f99f32a683dbfBob Halley cpp = he1->h_addr_list;
8c65ae482a50bed3184026301c6f99f32a683dbfBob Halley while (*cpp != NULL) {
8c65ae482a50bed3184026301c6f99f32a683dbfBob Halley addresses++;
8c65ae482a50bed3184026301c6f99f32a683dbfBob Halley cpp++;
8c65ae482a50bed3184026301c6f99f32a683dbfBob Halley }
8c65ae482a50bed3184026301c6f99f32a683dbfBob Halley cpp = he1->h_aliases;
6bb7b678f50a61dccad0bb3db4c26f73b59d8c16Bob Halley while (*cpp != NULL) {
8c65ae482a50bed3184026301c6f99f32a683dbfBob Halley names++;
8c65ae482a50bed3184026301c6f99f32a683dbfBob Halley cpp++;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley }
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley }
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley if (he2 != NULL) {
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff cpp = he2->h_addr_list;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley while (*cpp != NULL) {
732e0731dec1922747bb3b3147cf2c3d16b22eaaBob Halley addresses++;
0b157747b398ab59f42f584adc70a6c97d771abeBob Halley cpp++;
0b157747b398ab59f42f584adc70a6c97d771abeBob Halley }
1ccbfca64ae86ace521053773001cb995352f96fBob Halley if (he1 == NULL) {
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley cpp = he2->h_aliases;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley while (*cpp != NULL) {
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley names++;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley cpp++;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley }
1ccbfca64ae86ace521053773001cb995352f96fBob Halley }
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley }
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley if (addresses == 1) {
732e0731dec1922747bb3b3147cf2c3d16b22eaaBob Halley *error_num = NO_ADDRESS;
732e0731dec1922747bb3b3147cf2c3d16b22eaaBob Halley return (NULL);
0b157747b398ab59f42f584adc70a6c97d771abeBob Halley }
0b157747b398ab59f42f584adc70a6c97d771abeBob Halley
0b157747b398ab59f42f584adc70a6c97d771abeBob Halley he = malloc(sizeof *he);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley if (he == NULL)
732e0731dec1922747bb3b3147cf2c3d16b22eaaBob Halley goto no_recovery;
0b157747b398ab59f42f584adc70a6c97d771abeBob Halley
1ccbfca64ae86ace521053773001cb995352f96fBob Halley he->h_addr_list = malloc(sizeof(char *) * (addresses));
1ccbfca64ae86ace521053773001cb995352f96fBob Halley if (he->h_addr_list == NULL)
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff goto cleanup0;
efe6d8f0665b466052910e8efd4b031dc048f196Bob Halley memset(he->h_addr_list, 0, sizeof(char *) * (addresses));
63e6086ef99eca768a4cd69871038181251905bbBob Halley
efe6d8f0665b466052910e8efd4b031dc048f196Bob Halley /* copy addresses */
efe6d8f0665b466052910e8efd4b031dc048f196Bob Halley npp = he->h_addr_list;
efe6d8f0665b466052910e8efd4b031dc048f196Bob Halley if (he1 != NULL) {
efe6d8f0665b466052910e8efd4b031dc048f196Bob Halley cpp = he1->h_addr_list;
efe6d8f0665b466052910e8efd4b031dc048f196Bob Halley while (*cpp != NULL) {
efe6d8f0665b466052910e8efd4b031dc048f196Bob Halley *npp = malloc((af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
efe6d8f0665b466052910e8efd4b031dc048f196Bob Halley if (*npp == NULL)
efe6d8f0665b466052910e8efd4b031dc048f196Bob Halley goto cleanup1;
efe6d8f0665b466052910e8efd4b031dc048f196Bob Halley /* convert to mapped if required */
63e6086ef99eca768a4cd69871038181251905bbBob Halley if (af == AF_INET6 && he1->h_addrtype == AF_INET) {
63e6086ef99eca768a4cd69871038181251905bbBob Halley memcpy(*npp, in6addr_mapped,
efe6d8f0665b466052910e8efd4b031dc048f196Bob Halley sizeof in6addr_mapped);
efe6d8f0665b466052910e8efd4b031dc048f196Bob Halley memcpy(*npp + sizeof in6addr_mapped, *cpp,
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff INADDRSZ);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley } else {
7f705ac9a20e82264113e561a515d54dde5bcea3Bob Halley memcpy(*npp, *cpp,
64e829fffb8d95e7507079767ef68327b4a7b4caBob Halley (af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley }
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley cpp++;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley npp++;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley }
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley }
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley if (he2 != NULL) {
5c6d49484bf5600e3c2bcb3165e168bd058d167bBob Halley cpp = he2->h_addr_list;
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley while (*cpp != NULL) {
64e829fffb8d95e7507079767ef68327b4a7b4caBob Halley *npp = malloc((af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley if (*npp == NULL)
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley goto cleanup1;
302d9bebb54ad8c5a3e2108698215a0e98e06a32Bob Halley /* convert to mapped if required */
7f705ac9a20e82264113e561a515d54dde5bcea3Bob Halley if (af == AF_INET6 && he2->h_addrtype == AF_INET) {
7f705ac9a20e82264113e561a515d54dde5bcea3Bob Halley memcpy(*npp, in6addr_mapped,
7f705ac9a20e82264113e561a515d54dde5bcea3Bob Halley sizeof in6addr_mapped);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley memcpy(*npp + sizeof in6addr_mapped, *cpp,
7f705ac9a20e82264113e561a515d54dde5bcea3Bob Halley INADDRSZ);
64e829fffb8d95e7507079767ef68327b4a7b4caBob Halley } else {
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley memcpy(*npp, *cpp,
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley (af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff }
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley cpp++;
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley npp++;
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley }
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley }
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley he->h_aliases = malloc(sizeof(char *) * (names));
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley if (he->h_aliases == NULL)
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley goto cleanup1;
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley memset(he->h_aliases, 0, sizeof(char *) * (names));
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley /* copy aliases */
b687c057fbd8b88738300a5038538e589677fe18Bob Halley npp = he->h_aliases;
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley cpp = (he1 != NULL) ? he1->h_aliases : he2->h_aliases;
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley while (*cpp != NULL) {
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley len = strlen (*cpp) + 1;
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley *npp = malloc(len);
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley if (*npp == NULL)
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley goto cleanup2;
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley strcpy(*npp, *cpp);
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley npp++;
a7e185ff3f7db73e282bf53b9f84a95ff8f8cb27Bob Halley cpp++;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley }
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff /* copy hostname */
1ccbfca64ae86ace521053773001cb995352f96fBob Halley he->h_name = malloc(strlen((he1 != NULL) ?
6cac2e0f7a1ab207a64127bef11bb93404523c15Brian Wellington he1->h_name : he2->h_name) + 1);
6cac2e0f7a1ab207a64127bef11bb93404523c15Brian Wellington if (he->h_name == NULL)
1ccbfca64ae86ace521053773001cb995352f96fBob Halley goto cleanup2;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley strcpy(he->h_name, (he1 != NULL) ? he1->h_name : he2->h_name);
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley /* set address type and length */
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley he->h_addrtype = af;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley he->h_length = (af == AF_INET) ? INADDRSZ : IN6ADDRSZ;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley return(he);
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
a3e2ec2dfec1a8171eaf584bb957b80c04de1e0bBob Halley cleanup2:
a3e2ec2dfec1a8171eaf584bb957b80c04de1e0bBob Halley cpp = he->h_aliases;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley while (*cpp != NULL) {
6cac2e0f7a1ab207a64127bef11bb93404523c15Brian Wellington free(*cpp);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley 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));
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);
free(he);
return (NULL);
}
static struct hostent *
hostfromname(lwres_gabnresponse_t *name, int af) {
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(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));
for (i = 0 ; i < name->naddrs; i++) {
he->h_addr_list[i] = malloc(he->h_length);
if (he->h_addr_list[i] == NULL)
goto cleanup;
memcpy(he->h_addr_list[i], name->addrs[i].address, he->h_length);
}
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);
free(he);
return (NULL);
}