2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2001, 2002 Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: getaddresses.c,v 1.13.126.5 2004/05/15 03:46:12 jinmei Exp $ */
24 #include <isc/netaddr.h>
25 #include <isc/netdb.h>
26 #include <isc/netscope.h>
27 #include <isc/result.h>
28 #include <isc/sockaddr.h>
31 #include <bind9/getaddresses.h>
34 #ifdef HAVE_GETADDRINFO
35 #ifdef HAVE_GAISTRERROR
36 #define USE_GETADDRINFO
41 #ifndef USE_GETADDRINFO
42 #ifndef ISC_PLATFORM_NONSTDHERRNO
48 bind9_getaddresses(const char *hostname, in_port_t port,
49 isc_sockaddr_t *addrs, int addrsize, int *addrcount)
53 isc_boolean_t have_ipv4, have_ipv6;
56 #ifdef USE_GETADDRINFO
57 struct addrinfo *ai = NULL, *tmpai, hints;
63 REQUIRE(hostname != NULL);
64 REQUIRE(addrs != NULL);
65 REQUIRE(addrcount != NULL);
66 REQUIRE(addrsize > 0);
68 have_ipv4 = (isc_net_probeipv4() == ISC_R_SUCCESS);
69 have_ipv6 = (isc_net_probeipv6() == ISC_R_SUCCESS);
72 * Try IPv4, then IPv6. In order to handle the extended format
73 * for IPv6 scoped addresses (address%scope_ID), we'll use a local
74 * working buffer of 128 bytes. The length is an ad-hoc value, but
75 * should be enough for this purpose; the buffer can contain a string
76 * of at least 80 bytes for scope_ID in addition to any IPv6 numeric
77 * addresses (up to 46 bytes), the delimiter character and the
78 * terminating NULL character.
80 if (inet_pton(AF_INET, hostname, &in4) == 1) {
82 isc_sockaddr_fromin(&addrs[0], &in4, port);
84 isc_sockaddr_v6fromin(&addrs[0], &in4, port);
86 return (ISC_R_SUCCESS);
87 } else if (strlen(hostname) <= 127) {
89 isc_uint32_t zone = 0;
91 strcpy(tmpbuf, hostname);
92 d = strchr(tmpbuf, '%');
96 if (inet_pton(AF_INET6, tmpbuf, &in6) == 1) {
100 return (ISC_R_FAMILYNOSUPPORT);
103 #ifdef ISC_PLATFORM_HAVESCOPEID
106 result = isc_netscope_pton(AF_INET6, d + 1,
109 if (result != ISC_R_SUCCESS)
113 * The extended format is specified while the
114 * system does not provide the ability to use
115 * it. Throw an explicit error instead of
116 * ignoring the specified value.
118 return (ISC_R_BADADDRESSFORM);
122 isc_netaddr_fromin6(&na, &in6);
123 isc_netaddr_setzone(&na, zone);
124 isc_sockaddr_fromnetaddr(&addrs[0],
125 (const isc_netaddr_t *)&na,
129 return (ISC_R_SUCCESS);
133 #ifdef USE_GETADDRINFO
134 memset(&hints, 0, sizeof(hints));
136 hints.ai_family = PF_INET;
138 hints.ai_family = PF_INET6;
140 hints.ai_family = PF_UNSPEC;
142 hints.ai_flags = AI_ADDRCONFIG;
145 hints.ai_socktype = SOCK_STREAM;
149 result = getaddrinfo(hostname, NULL, &hints, &ai);
154 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
157 return (ISC_R_NOTFOUND);
160 if ((hints.ai_flags & AI_ADDRCONFIG) != 0) {
161 hints.ai_flags &= ~AI_ADDRCONFIG;
166 return (ISC_R_FAILURE);
168 for (tmpai = ai, i = 0;
169 tmpai != NULL && i < addrsize;
170 tmpai = tmpai->ai_next)
172 if (tmpai->ai_family != AF_INET &&
173 tmpai->ai_family != AF_INET6)
175 if (tmpai->ai_family == AF_INET) {
176 struct sockaddr_in *sin;
177 sin = (struct sockaddr_in *)tmpai->ai_addr;
178 isc_sockaddr_fromin(&addrs[i], &sin->sin_addr, port);
180 struct sockaddr_in6 *sin6;
181 sin6 = (struct sockaddr_in6 *)tmpai->ai_addr;
182 isc_sockaddr_fromin6(&addrs[i], &sin6->sin6_addr,
191 he = gethostbyname(hostname);
198 #if defined(NO_ADDRESS) && (!defined(NO_DATA) || (NO_DATA != NO_ADDRESS))
201 return (ISC_R_NOTFOUND);
203 return (ISC_R_FAILURE);
206 if (he->h_addrtype != AF_INET && he->h_addrtype != AF_INET6)
207 return (ISC_R_NOTFOUND);
208 for (i = 0; i < addrsize; i++) {
209 if (he->h_addrtype == AF_INET) {
211 inp = (struct in_addr *)(he->h_addr_list[i]);
214 isc_sockaddr_fromin(&addrs[i], inp, port);
216 struct in6_addr *in6p;
217 in6p = (struct in6_addr *)(he->h_addr_list[i]);
220 isc_sockaddr_fromin6(&addrs[i], in6p, port);
226 return (ISC_R_NOTFOUND);
228 return (ISC_R_SUCCESS);