1*a466cc55SCy Schubert /*
2*a466cc55SCy Schubert * Copyright (C) 2004-2007, 2010-2012 Internet Systems Consortium, Inc. ("ISC")
3*a466cc55SCy Schubert * Copyright (C) 1999-2003 Internet Software Consortium.
4*a466cc55SCy Schubert *
5*a466cc55SCy Schubert * Permission to use, copy, modify, and/or distribute this software for any
6*a466cc55SCy Schubert * purpose with or without fee is hereby granted, provided that the above
7*a466cc55SCy Schubert * copyright notice and this permission notice appear in all copies.
8*a466cc55SCy Schubert *
9*a466cc55SCy Schubert * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10*a466cc55SCy Schubert * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11*a466cc55SCy Schubert * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12*a466cc55SCy Schubert * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13*a466cc55SCy Schubert * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14*a466cc55SCy Schubert * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15*a466cc55SCy Schubert * PERFORMANCE OF THIS SOFTWARE.
16*a466cc55SCy Schubert */
17*a466cc55SCy Schubert
18*a466cc55SCy Schubert /* $Id$ */
19*a466cc55SCy Schubert
20*a466cc55SCy Schubert /*! \file */
21*a466cc55SCy Schubert
22*a466cc55SCy Schubert #include <config.h>
23*a466cc55SCy Schubert
24*a466cc55SCy Schubert #include <stdio.h>
25*a466cc55SCy Schubert
26*a466cc55SCy Schubert #include <isc/buffer.h>
27*a466cc55SCy Schubert #include <isc/hash.h>
28*a466cc55SCy Schubert #include <isc/msgs.h>
29*a466cc55SCy Schubert #include <isc/netaddr.h>
30*a466cc55SCy Schubert #include <isc/print.h>
31*a466cc55SCy Schubert #include <isc/region.h>
32*a466cc55SCy Schubert #include <isc/sockaddr.h>
33*a466cc55SCy Schubert #include <isc/string.h>
34*a466cc55SCy Schubert #include <isc/util.h>
35*a466cc55SCy Schubert
36*a466cc55SCy Schubert isc_boolean_t
isc_sockaddr_equal(const isc_sockaddr_t * a,const isc_sockaddr_t * b)37*a466cc55SCy Schubert isc_sockaddr_equal(const isc_sockaddr_t *a, const isc_sockaddr_t *b) {
38*a466cc55SCy Schubert return (isc_sockaddr_compare(a, b, ISC_SOCKADDR_CMPADDR|
39*a466cc55SCy Schubert ISC_SOCKADDR_CMPPORT|
40*a466cc55SCy Schubert ISC_SOCKADDR_CMPSCOPE));
41*a466cc55SCy Schubert }
42*a466cc55SCy Schubert
43*a466cc55SCy Schubert isc_boolean_t
isc_sockaddr_eqaddr(const isc_sockaddr_t * a,const isc_sockaddr_t * b)44*a466cc55SCy Schubert isc_sockaddr_eqaddr(const isc_sockaddr_t *a, const isc_sockaddr_t *b) {
45*a466cc55SCy Schubert return (isc_sockaddr_compare(a, b, ISC_SOCKADDR_CMPADDR|
46*a466cc55SCy Schubert ISC_SOCKADDR_CMPSCOPE));
47*a466cc55SCy Schubert }
48*a466cc55SCy Schubert
49*a466cc55SCy Schubert isc_boolean_t
isc_sockaddr_compare(const isc_sockaddr_t * a,const isc_sockaddr_t * b,unsigned int flags)50*a466cc55SCy Schubert isc_sockaddr_compare(const isc_sockaddr_t *a, const isc_sockaddr_t *b,
51*a466cc55SCy Schubert unsigned int flags)
52*a466cc55SCy Schubert {
53*a466cc55SCy Schubert REQUIRE(a != NULL && b != NULL);
54*a466cc55SCy Schubert
55*a466cc55SCy Schubert if (a->length != b->length)
56*a466cc55SCy Schubert return (ISC_FALSE);
57*a466cc55SCy Schubert
58*a466cc55SCy Schubert /*
59*a466cc55SCy Schubert * We don't just memcmp because the sin_zero field isn't always
60*a466cc55SCy Schubert * zero.
61*a466cc55SCy Schubert */
62*a466cc55SCy Schubert
63*a466cc55SCy Schubert if (a->type.sa.sa_family != b->type.sa.sa_family)
64*a466cc55SCy Schubert return (ISC_FALSE);
65*a466cc55SCy Schubert switch (a->type.sa.sa_family) {
66*a466cc55SCy Schubert case AF_INET:
67*a466cc55SCy Schubert if ((flags & ISC_SOCKADDR_CMPADDR) != 0 &&
68*a466cc55SCy Schubert memcmp(&a->type.sin.sin_addr, &b->type.sin.sin_addr,
69*a466cc55SCy Schubert sizeof(a->type.sin.sin_addr)) != 0)
70*a466cc55SCy Schubert return (ISC_FALSE);
71*a466cc55SCy Schubert if ((flags & ISC_SOCKADDR_CMPPORT) != 0 &&
72*a466cc55SCy Schubert a->type.sin.sin_port != b->type.sin.sin_port)
73*a466cc55SCy Schubert return (ISC_FALSE);
74*a466cc55SCy Schubert break;
75*a466cc55SCy Schubert case AF_INET6:
76*a466cc55SCy Schubert if ((flags & ISC_SOCKADDR_CMPADDR) != 0 &&
77*a466cc55SCy Schubert memcmp(&a->type.sin6.sin6_addr, &b->type.sin6.sin6_addr,
78*a466cc55SCy Schubert sizeof(a->type.sin6.sin6_addr)) != 0)
79*a466cc55SCy Schubert return (ISC_FALSE);
80*a466cc55SCy Schubert #ifdef ISC_PLATFORM_HAVESCOPEID
81*a466cc55SCy Schubert /*
82*a466cc55SCy Schubert * If ISC_SOCKADDR_CMPSCOPEZERO is set then don't return
83*a466cc55SCy Schubert * ISC_FALSE if one of the scopes in zero.
84*a466cc55SCy Schubert */
85*a466cc55SCy Schubert if ((flags & ISC_SOCKADDR_CMPSCOPE) != 0 &&
86*a466cc55SCy Schubert a->type.sin6.sin6_scope_id != b->type.sin6.sin6_scope_id &&
87*a466cc55SCy Schubert ((flags & ISC_SOCKADDR_CMPSCOPEZERO) == 0 ||
88*a466cc55SCy Schubert (a->type.sin6.sin6_scope_id != 0 &&
89*a466cc55SCy Schubert b->type.sin6.sin6_scope_id != 0)))
90*a466cc55SCy Schubert return (ISC_FALSE);
91*a466cc55SCy Schubert #endif
92*a466cc55SCy Schubert if ((flags & ISC_SOCKADDR_CMPPORT) != 0 &&
93*a466cc55SCy Schubert a->type.sin6.sin6_port != b->type.sin6.sin6_port)
94*a466cc55SCy Schubert return (ISC_FALSE);
95*a466cc55SCy Schubert break;
96*a466cc55SCy Schubert default:
97*a466cc55SCy Schubert if (memcmp(&a->type, &b->type, a->length) != 0)
98*a466cc55SCy Schubert return (ISC_FALSE);
99*a466cc55SCy Schubert }
100*a466cc55SCy Schubert return (ISC_TRUE);
101*a466cc55SCy Schubert }
102*a466cc55SCy Schubert
103*a466cc55SCy Schubert isc_boolean_t
isc_sockaddr_eqaddrprefix(const isc_sockaddr_t * a,const isc_sockaddr_t * b,unsigned int prefixlen)104*a466cc55SCy Schubert isc_sockaddr_eqaddrprefix(const isc_sockaddr_t *a, const isc_sockaddr_t *b,
105*a466cc55SCy Schubert unsigned int prefixlen)
106*a466cc55SCy Schubert {
107*a466cc55SCy Schubert isc_netaddr_t na, nb;
108*a466cc55SCy Schubert isc_netaddr_fromsockaddr(&na, a);
109*a466cc55SCy Schubert isc_netaddr_fromsockaddr(&nb, b);
110*a466cc55SCy Schubert return (isc_netaddr_eqprefix(&na, &nb, prefixlen));
111*a466cc55SCy Schubert }
112*a466cc55SCy Schubert
113*a466cc55SCy Schubert isc_result_t
isc_sockaddr_totext(const isc_sockaddr_t * sockaddr,isc_buffer_t * target)114*a466cc55SCy Schubert isc_sockaddr_totext(const isc_sockaddr_t *sockaddr, isc_buffer_t *target) {
115*a466cc55SCy Schubert isc_result_t result;
116*a466cc55SCy Schubert isc_netaddr_t netaddr;
117*a466cc55SCy Schubert char pbuf[sizeof("65000")];
118*a466cc55SCy Schubert unsigned int plen;
119*a466cc55SCy Schubert isc_region_t avail;
120*a466cc55SCy Schubert
121*a466cc55SCy Schubert REQUIRE(sockaddr != NULL);
122*a466cc55SCy Schubert
123*a466cc55SCy Schubert /*
124*a466cc55SCy Schubert * Do the port first, giving us the opportunity to check for
125*a466cc55SCy Schubert * unsupported address families before calling
126*a466cc55SCy Schubert * isc_netaddr_fromsockaddr().
127*a466cc55SCy Schubert */
128*a466cc55SCy Schubert switch (sockaddr->type.sa.sa_family) {
129*a466cc55SCy Schubert case AF_INET:
130*a466cc55SCy Schubert snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin.sin_port));
131*a466cc55SCy Schubert break;
132*a466cc55SCy Schubert case AF_INET6:
133*a466cc55SCy Schubert snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin6.sin6_port));
134*a466cc55SCy Schubert break;
135*a466cc55SCy Schubert #ifdef ISC_PLAFORM_HAVESYSUNH
136*a466cc55SCy Schubert case AF_UNIX:
137*a466cc55SCy Schubert plen = (unsigned int)strlen(sockaddr->type.sunix.sun_path);
138*a466cc55SCy Schubert if (plen >= isc_buffer_availablelength(target))
139*a466cc55SCy Schubert return (ISC_R_NOSPACE);
140*a466cc55SCy Schubert
141*a466cc55SCy Schubert isc_buffer_putmem(target, sockaddr->type.sunix.sun_path, plen);
142*a466cc55SCy Schubert
143*a466cc55SCy Schubert /*
144*a466cc55SCy Schubert * Null terminate after used region.
145*a466cc55SCy Schubert */
146*a466cc55SCy Schubert isc_buffer_availableregion(target, &avail);
147*a466cc55SCy Schubert INSIST(avail.length >= 1);
148*a466cc55SCy Schubert avail.base[0] = '\0';
149*a466cc55SCy Schubert
150*a466cc55SCy Schubert return (ISC_R_SUCCESS);
151*a466cc55SCy Schubert #endif
152*a466cc55SCy Schubert default:
153*a466cc55SCy Schubert return (ISC_R_FAILURE);
154*a466cc55SCy Schubert }
155*a466cc55SCy Schubert
156*a466cc55SCy Schubert plen = (unsigned int)strlen(pbuf);
157*a466cc55SCy Schubert INSIST(plen < sizeof(pbuf));
158*a466cc55SCy Schubert
159*a466cc55SCy Schubert isc_netaddr_fromsockaddr(&netaddr, sockaddr);
160*a466cc55SCy Schubert result = isc_netaddr_totext(&netaddr, target);
161*a466cc55SCy Schubert if (result != ISC_R_SUCCESS)
162*a466cc55SCy Schubert return (result);
163*a466cc55SCy Schubert
164*a466cc55SCy Schubert if (1 + plen + 1 > isc_buffer_availablelength(target))
165*a466cc55SCy Schubert return (ISC_R_NOSPACE);
166*a466cc55SCy Schubert
167*a466cc55SCy Schubert isc_buffer_putmem(target, (const unsigned char *)"#", 1);
168*a466cc55SCy Schubert isc_buffer_putmem(target, (const unsigned char *)pbuf, plen);
169*a466cc55SCy Schubert
170*a466cc55SCy Schubert /*
171*a466cc55SCy Schubert * Null terminate after used region.
172*a466cc55SCy Schubert */
173*a466cc55SCy Schubert isc_buffer_availableregion(target, &avail);
174*a466cc55SCy Schubert INSIST(avail.length >= 1);
175*a466cc55SCy Schubert avail.base[0] = '\0';
176*a466cc55SCy Schubert
177*a466cc55SCy Schubert return (ISC_R_SUCCESS);
178*a466cc55SCy Schubert }
179*a466cc55SCy Schubert
180*a466cc55SCy Schubert void
isc_sockaddr_format(const isc_sockaddr_t * sa,char * array,unsigned int size)181*a466cc55SCy Schubert isc_sockaddr_format(const isc_sockaddr_t *sa, char *array, unsigned int size) {
182*a466cc55SCy Schubert isc_result_t result;
183*a466cc55SCy Schubert isc_buffer_t buf;
184*a466cc55SCy Schubert
185*a466cc55SCy Schubert if (size == 0U)
186*a466cc55SCy Schubert return;
187*a466cc55SCy Schubert
188*a466cc55SCy Schubert isc_buffer_init(&buf, array, size);
189*a466cc55SCy Schubert result = isc_sockaddr_totext(sa, &buf);
190*a466cc55SCy Schubert if (result != ISC_R_SUCCESS) {
191*a466cc55SCy Schubert /*
192*a466cc55SCy Schubert * The message is the same as in netaddr.c.
193*a466cc55SCy Schubert */
194*a466cc55SCy Schubert snprintf(array, size,
195*a466cc55SCy Schubert "<%s %u>",
196*a466cc55SCy Schubert isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR,
197*a466cc55SCy Schubert ISC_MSG_UNKNOWNADDR,
198*a466cc55SCy Schubert "unknown address, family"),
199*a466cc55SCy Schubert sa->type.sa.sa_family);
200*a466cc55SCy Schubert array[size - 1] = '\0';
201*a466cc55SCy Schubert }
202*a466cc55SCy Schubert }
203*a466cc55SCy Schubert
204*a466cc55SCy Schubert unsigned int
isc_sockaddr_hash(const isc_sockaddr_t * sockaddr,isc_boolean_t address_only)205*a466cc55SCy Schubert isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, isc_boolean_t address_only) {
206*a466cc55SCy Schubert unsigned int length = 0;
207*a466cc55SCy Schubert const unsigned char *s = NULL;
208*a466cc55SCy Schubert unsigned int h = 0;
209*a466cc55SCy Schubert unsigned int g;
210*a466cc55SCy Schubert unsigned int p = 0;
211*a466cc55SCy Schubert const struct in6_addr *in6;
212*a466cc55SCy Schubert
213*a466cc55SCy Schubert REQUIRE(sockaddr != NULL);
214*a466cc55SCy Schubert
215*a466cc55SCy Schubert switch (sockaddr->type.sa.sa_family) {
216*a466cc55SCy Schubert case AF_INET:
217*a466cc55SCy Schubert s = (const unsigned char *)&sockaddr->type.sin.sin_addr;
218*a466cc55SCy Schubert p = ntohs(sockaddr->type.sin.sin_port);
219*a466cc55SCy Schubert length = sizeof(sockaddr->type.sin.sin_addr.s_addr);
220*a466cc55SCy Schubert break;
221*a466cc55SCy Schubert case AF_INET6:
222*a466cc55SCy Schubert in6 = &sockaddr->type.sin6.sin6_addr;
223*a466cc55SCy Schubert if (IN6_IS_ADDR_V4MAPPED(in6)) {
224*a466cc55SCy Schubert s = (const unsigned char *)&in6 + 12;
225*a466cc55SCy Schubert length = sizeof(sockaddr->type.sin.sin_addr.s_addr);
226*a466cc55SCy Schubert } else {
227*a466cc55SCy Schubert s = (const unsigned char *)in6;
228*a466cc55SCy Schubert length = sizeof(sockaddr->type.sin6.sin6_addr);
229*a466cc55SCy Schubert }
230*a466cc55SCy Schubert p = ntohs(sockaddr->type.sin6.sin6_port);
231*a466cc55SCy Schubert break;
232*a466cc55SCy Schubert default:
233*a466cc55SCy Schubert UNEXPECTED_ERROR(__FILE__, __LINE__,
234*a466cc55SCy Schubert "%s: %d",
235*a466cc55SCy Schubert isc_msgcat_get(isc_msgcat,
236*a466cc55SCy Schubert ISC_MSGSET_SOCKADDR,
237*a466cc55SCy Schubert ISC_MSG_UNKNOWNFAMILY,
238*a466cc55SCy Schubert "unknown address family"),
239*a466cc55SCy Schubert (int)sockaddr->type.sa.sa_family);
240*a466cc55SCy Schubert s = (const unsigned char *)&sockaddr->type;
241*a466cc55SCy Schubert length = sockaddr->length;
242*a466cc55SCy Schubert p = 0;
243*a466cc55SCy Schubert }
244*a466cc55SCy Schubert
245*a466cc55SCy Schubert h = isc_hash_calc(s, length, ISC_TRUE);
246*a466cc55SCy Schubert if (!address_only) {
247*a466cc55SCy Schubert g = isc_hash_calc((const unsigned char *)&p, sizeof(p),
248*a466cc55SCy Schubert ISC_TRUE);
249*a466cc55SCy Schubert h = h ^ g; /* XXX: we should concatenate h and p first */
250*a466cc55SCy Schubert }
251*a466cc55SCy Schubert
252*a466cc55SCy Schubert return (h);
253*a466cc55SCy Schubert }
254*a466cc55SCy Schubert
255*a466cc55SCy Schubert void
isc_sockaddr_any(isc_sockaddr_t * sockaddr)256*a466cc55SCy Schubert isc_sockaddr_any(isc_sockaddr_t *sockaddr)
257*a466cc55SCy Schubert {
258*a466cc55SCy Schubert memset(sockaddr, 0, sizeof(*sockaddr));
259*a466cc55SCy Schubert sockaddr->type.sin.sin_family = AF_INET;
260*a466cc55SCy Schubert #ifdef ISC_PLATFORM_HAVESALEN
261*a466cc55SCy Schubert sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
262*a466cc55SCy Schubert #endif
263*a466cc55SCy Schubert sockaddr->type.sin.sin_addr.s_addr = INADDR_ANY;
264*a466cc55SCy Schubert sockaddr->type.sin.sin_port = 0;
265*a466cc55SCy Schubert sockaddr->length = sizeof(sockaddr->type.sin);
266*a466cc55SCy Schubert ISC_LINK_INIT(sockaddr, link);
267*a466cc55SCy Schubert }
268*a466cc55SCy Schubert
269*a466cc55SCy Schubert void
isc_sockaddr_any6(isc_sockaddr_t * sockaddr)270*a466cc55SCy Schubert isc_sockaddr_any6(isc_sockaddr_t *sockaddr)
271*a466cc55SCy Schubert {
272*a466cc55SCy Schubert memset(sockaddr, 0, sizeof(*sockaddr));
273*a466cc55SCy Schubert sockaddr->type.sin6.sin6_family = AF_INET6;
274*a466cc55SCy Schubert #ifdef ISC_PLATFORM_HAVESALEN
275*a466cc55SCy Schubert sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
276*a466cc55SCy Schubert #endif
277*a466cc55SCy Schubert sockaddr->type.sin6.sin6_addr = in6addr_any;
278*a466cc55SCy Schubert sockaddr->type.sin6.sin6_port = 0;
279*a466cc55SCy Schubert sockaddr->length = sizeof(sockaddr->type.sin6);
280*a466cc55SCy Schubert ISC_LINK_INIT(sockaddr, link);
281*a466cc55SCy Schubert }
282*a466cc55SCy Schubert
283*a466cc55SCy Schubert void
isc_sockaddr_fromin(isc_sockaddr_t * sockaddr,const struct in_addr * ina,in_port_t port)284*a466cc55SCy Schubert isc_sockaddr_fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina,
285*a466cc55SCy Schubert in_port_t port)
286*a466cc55SCy Schubert {
287*a466cc55SCy Schubert memset(sockaddr, 0, sizeof(*sockaddr));
288*a466cc55SCy Schubert sockaddr->type.sin.sin_family = AF_INET;
289*a466cc55SCy Schubert #ifdef ISC_PLATFORM_HAVESALEN
290*a466cc55SCy Schubert sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
291*a466cc55SCy Schubert #endif
292*a466cc55SCy Schubert sockaddr->type.sin.sin_addr = *ina;
293*a466cc55SCy Schubert sockaddr->type.sin.sin_port = htons(port);
294*a466cc55SCy Schubert sockaddr->length = sizeof(sockaddr->type.sin);
295*a466cc55SCy Schubert ISC_LINK_INIT(sockaddr, link);
296*a466cc55SCy Schubert }
297*a466cc55SCy Schubert
298*a466cc55SCy Schubert void
isc_sockaddr_anyofpf(isc_sockaddr_t * sockaddr,int pf)299*a466cc55SCy Schubert isc_sockaddr_anyofpf(isc_sockaddr_t *sockaddr, int pf) {
300*a466cc55SCy Schubert switch (pf) {
301*a466cc55SCy Schubert case AF_INET:
302*a466cc55SCy Schubert isc_sockaddr_any(sockaddr);
303*a466cc55SCy Schubert break;
304*a466cc55SCy Schubert case AF_INET6:
305*a466cc55SCy Schubert isc_sockaddr_any6(sockaddr);
306*a466cc55SCy Schubert break;
307*a466cc55SCy Schubert default:
308*a466cc55SCy Schubert INSIST(0);
309*a466cc55SCy Schubert }
310*a466cc55SCy Schubert }
311*a466cc55SCy Schubert
312*a466cc55SCy Schubert void
isc_sockaddr_fromin6(isc_sockaddr_t * sockaddr,const struct in6_addr * ina6,in_port_t port)313*a466cc55SCy Schubert isc_sockaddr_fromin6(isc_sockaddr_t *sockaddr, const struct in6_addr *ina6,
314*a466cc55SCy Schubert in_port_t port)
315*a466cc55SCy Schubert {
316*a466cc55SCy Schubert memset(sockaddr, 0, sizeof(*sockaddr));
317*a466cc55SCy Schubert sockaddr->type.sin6.sin6_family = AF_INET6;
318*a466cc55SCy Schubert #ifdef ISC_PLATFORM_HAVESALEN
319*a466cc55SCy Schubert sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
320*a466cc55SCy Schubert #endif
321*a466cc55SCy Schubert sockaddr->type.sin6.sin6_addr = *ina6;
322*a466cc55SCy Schubert sockaddr->type.sin6.sin6_port = htons(port);
323*a466cc55SCy Schubert sockaddr->length = sizeof(sockaddr->type.sin6);
324*a466cc55SCy Schubert ISC_LINK_INIT(sockaddr, link);
325*a466cc55SCy Schubert }
326*a466cc55SCy Schubert
327*a466cc55SCy Schubert void
isc_sockaddr_v6fromin(isc_sockaddr_t * sockaddr,const struct in_addr * ina,in_port_t port)328*a466cc55SCy Schubert isc_sockaddr_v6fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina,
329*a466cc55SCy Schubert in_port_t port)
330*a466cc55SCy Schubert {
331*a466cc55SCy Schubert memset(sockaddr, 0, sizeof(*sockaddr));
332*a466cc55SCy Schubert sockaddr->type.sin6.sin6_family = AF_INET6;
333*a466cc55SCy Schubert #ifdef ISC_PLATFORM_HAVESALEN
334*a466cc55SCy Schubert sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
335*a466cc55SCy Schubert #endif
336*a466cc55SCy Schubert sockaddr->type.sin6.sin6_addr.s6_addr[10] = 0xff;
337*a466cc55SCy Schubert sockaddr->type.sin6.sin6_addr.s6_addr[11] = 0xff;
338*a466cc55SCy Schubert memcpy(&sockaddr->type.sin6.sin6_addr.s6_addr[12], ina, 4);
339*a466cc55SCy Schubert sockaddr->type.sin6.sin6_port = htons(port);
340*a466cc55SCy Schubert sockaddr->length = sizeof(sockaddr->type.sin6);
341*a466cc55SCy Schubert ISC_LINK_INIT(sockaddr, link);
342*a466cc55SCy Schubert }
343*a466cc55SCy Schubert
344*a466cc55SCy Schubert int
isc_sockaddr_pf(const isc_sockaddr_t * sockaddr)345*a466cc55SCy Schubert isc_sockaddr_pf(const isc_sockaddr_t *sockaddr) {
346*a466cc55SCy Schubert
347*a466cc55SCy Schubert /*
348*a466cc55SCy Schubert * Get the protocol family of 'sockaddr'.
349*a466cc55SCy Schubert */
350*a466cc55SCy Schubert
351*a466cc55SCy Schubert #if (AF_INET == PF_INET && AF_INET6 == PF_INET6)
352*a466cc55SCy Schubert /*
353*a466cc55SCy Schubert * Assume that PF_xxx == AF_xxx for all AF and PF.
354*a466cc55SCy Schubert */
355*a466cc55SCy Schubert return (sockaddr->type.sa.sa_family);
356*a466cc55SCy Schubert #else
357*a466cc55SCy Schubert switch (sockaddr->type.sa.sa_family) {
358*a466cc55SCy Schubert case AF_INET:
359*a466cc55SCy Schubert return (PF_INET);
360*a466cc55SCy Schubert case AF_INET6:
361*a466cc55SCy Schubert return (PF_INET6);
362*a466cc55SCy Schubert default:
363*a466cc55SCy Schubert FATAL_ERROR(__FILE__, __LINE__,
364*a466cc55SCy Schubert isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
365*a466cc55SCy Schubert ISC_MSG_UNKNOWNFAMILY,
366*a466cc55SCy Schubert "unknown address family: %d"),
367*a466cc55SCy Schubert (int)sockaddr->type.sa.sa_family);
368*a466cc55SCy Schubert }
369*a466cc55SCy Schubert #endif
370*a466cc55SCy Schubert }
371*a466cc55SCy Schubert
372*a466cc55SCy Schubert void
isc_sockaddr_fromnetaddr(isc_sockaddr_t * sockaddr,const isc_netaddr_t * na,in_port_t port)373*a466cc55SCy Schubert isc_sockaddr_fromnetaddr(isc_sockaddr_t *sockaddr, const isc_netaddr_t *na,
374*a466cc55SCy Schubert in_port_t port)
375*a466cc55SCy Schubert {
376*a466cc55SCy Schubert memset(sockaddr, 0, sizeof(*sockaddr));
377*a466cc55SCy Schubert sockaddr->type.sin.sin_family = (short)na->family;
378*a466cc55SCy Schubert switch (na->family) {
379*a466cc55SCy Schubert case AF_INET:
380*a466cc55SCy Schubert sockaddr->length = sizeof(sockaddr->type.sin);
381*a466cc55SCy Schubert #ifdef ISC_PLATFORM_HAVESALEN
382*a466cc55SCy Schubert sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
383*a466cc55SCy Schubert #endif
384*a466cc55SCy Schubert sockaddr->type.sin.sin_addr = na->type.in;
385*a466cc55SCy Schubert sockaddr->type.sin.sin_port = htons(port);
386*a466cc55SCy Schubert break;
387*a466cc55SCy Schubert case AF_INET6:
388*a466cc55SCy Schubert sockaddr->length = sizeof(sockaddr->type.sin6);
389*a466cc55SCy Schubert #ifdef ISC_PLATFORM_HAVESALEN
390*a466cc55SCy Schubert sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
391*a466cc55SCy Schubert #endif
392*a466cc55SCy Schubert memcpy(&sockaddr->type.sin6.sin6_addr, &na->type.in6, 16);
393*a466cc55SCy Schubert #ifdef ISC_PLATFORM_HAVESCOPEID
394*a466cc55SCy Schubert sockaddr->type.sin6.sin6_scope_id = isc_netaddr_getzone(na);
395*a466cc55SCy Schubert #endif
396*a466cc55SCy Schubert sockaddr->type.sin6.sin6_port = htons(port);
397*a466cc55SCy Schubert break;
398*a466cc55SCy Schubert default:
399*a466cc55SCy Schubert INSIST(0);
400*a466cc55SCy Schubert }
401*a466cc55SCy Schubert ISC_LINK_INIT(sockaddr, link);
402*a466cc55SCy Schubert }
403*a466cc55SCy Schubert
404*a466cc55SCy Schubert void
isc_sockaddr_setport(isc_sockaddr_t * sockaddr,in_port_t port)405*a466cc55SCy Schubert isc_sockaddr_setport(isc_sockaddr_t *sockaddr, in_port_t port) {
406*a466cc55SCy Schubert switch (sockaddr->type.sa.sa_family) {
407*a466cc55SCy Schubert case AF_INET:
408*a466cc55SCy Schubert sockaddr->type.sin.sin_port = htons(port);
409*a466cc55SCy Schubert break;
410*a466cc55SCy Schubert case AF_INET6:
411*a466cc55SCy Schubert sockaddr->type.sin6.sin6_port = htons(port);
412*a466cc55SCy Schubert break;
413*a466cc55SCy Schubert default:
414*a466cc55SCy Schubert FATAL_ERROR(__FILE__, __LINE__,
415*a466cc55SCy Schubert "%s: %d",
416*a466cc55SCy Schubert isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
417*a466cc55SCy Schubert ISC_MSG_UNKNOWNFAMILY,
418*a466cc55SCy Schubert "unknown address family"),
419*a466cc55SCy Schubert (int)sockaddr->type.sa.sa_family);
420*a466cc55SCy Schubert }
421*a466cc55SCy Schubert }
422*a466cc55SCy Schubert
423*a466cc55SCy Schubert in_port_t
isc_sockaddr_getport(const isc_sockaddr_t * sockaddr)424*a466cc55SCy Schubert isc_sockaddr_getport(const isc_sockaddr_t *sockaddr) {
425*a466cc55SCy Schubert in_port_t port = 0;
426*a466cc55SCy Schubert
427*a466cc55SCy Schubert switch (sockaddr->type.sa.sa_family) {
428*a466cc55SCy Schubert case AF_INET:
429*a466cc55SCy Schubert port = ntohs(sockaddr->type.sin.sin_port);
430*a466cc55SCy Schubert break;
431*a466cc55SCy Schubert case AF_INET6:
432*a466cc55SCy Schubert port = ntohs(sockaddr->type.sin6.sin6_port);
433*a466cc55SCy Schubert break;
434*a466cc55SCy Schubert default:
435*a466cc55SCy Schubert FATAL_ERROR(__FILE__, __LINE__,
436*a466cc55SCy Schubert "%s: %d",
437*a466cc55SCy Schubert isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
438*a466cc55SCy Schubert ISC_MSG_UNKNOWNFAMILY,
439*a466cc55SCy Schubert "unknown address family"),
440*a466cc55SCy Schubert (int)sockaddr->type.sa.sa_family);
441*a466cc55SCy Schubert }
442*a466cc55SCy Schubert
443*a466cc55SCy Schubert return (port);
444*a466cc55SCy Schubert }
445*a466cc55SCy Schubert
446*a466cc55SCy Schubert isc_boolean_t
isc_sockaddr_ismulticast(const isc_sockaddr_t * sockaddr)447*a466cc55SCy Schubert isc_sockaddr_ismulticast(const isc_sockaddr_t *sockaddr) {
448*a466cc55SCy Schubert isc_netaddr_t netaddr;
449*a466cc55SCy Schubert
450*a466cc55SCy Schubert if (sockaddr->type.sa.sa_family == AF_INET ||
451*a466cc55SCy Schubert sockaddr->type.sa.sa_family == AF_INET6) {
452*a466cc55SCy Schubert isc_netaddr_fromsockaddr(&netaddr, sockaddr);
453*a466cc55SCy Schubert return (isc_netaddr_ismulticast(&netaddr));
454*a466cc55SCy Schubert }
455*a466cc55SCy Schubert return (ISC_FALSE);
456*a466cc55SCy Schubert }
457*a466cc55SCy Schubert
458*a466cc55SCy Schubert isc_boolean_t
isc_sockaddr_isexperimental(const isc_sockaddr_t * sockaddr)459*a466cc55SCy Schubert isc_sockaddr_isexperimental(const isc_sockaddr_t *sockaddr) {
460*a466cc55SCy Schubert isc_netaddr_t netaddr;
461*a466cc55SCy Schubert
462*a466cc55SCy Schubert if (sockaddr->type.sa.sa_family == AF_INET) {
463*a466cc55SCy Schubert isc_netaddr_fromsockaddr(&netaddr, sockaddr);
464*a466cc55SCy Schubert return (isc_netaddr_isexperimental(&netaddr));
465*a466cc55SCy Schubert }
466*a466cc55SCy Schubert return (ISC_FALSE);
467*a466cc55SCy Schubert }
468*a466cc55SCy Schubert
469*a466cc55SCy Schubert isc_boolean_t
isc_sockaddr_issitelocal(const isc_sockaddr_t * sockaddr)470*a466cc55SCy Schubert isc_sockaddr_issitelocal(const isc_sockaddr_t *sockaddr) {
471*a466cc55SCy Schubert isc_netaddr_t netaddr;
472*a466cc55SCy Schubert
473*a466cc55SCy Schubert if (sockaddr->type.sa.sa_family == AF_INET6) {
474*a466cc55SCy Schubert isc_netaddr_fromsockaddr(&netaddr, sockaddr);
475*a466cc55SCy Schubert return (isc_netaddr_issitelocal(&netaddr));
476*a466cc55SCy Schubert }
477*a466cc55SCy Schubert return (ISC_FALSE);
478*a466cc55SCy Schubert }
479*a466cc55SCy Schubert
480*a466cc55SCy Schubert isc_boolean_t
isc_sockaddr_islinklocal(const isc_sockaddr_t * sockaddr)481*a466cc55SCy Schubert isc_sockaddr_islinklocal(const isc_sockaddr_t *sockaddr) {
482*a466cc55SCy Schubert isc_netaddr_t netaddr;
483*a466cc55SCy Schubert
484*a466cc55SCy Schubert if (sockaddr->type.sa.sa_family == AF_INET6) {
485*a466cc55SCy Schubert isc_netaddr_fromsockaddr(&netaddr, sockaddr);
486*a466cc55SCy Schubert return (isc_netaddr_islinklocal(&netaddr));
487*a466cc55SCy Schubert }
488*a466cc55SCy Schubert return (ISC_FALSE);
489*a466cc55SCy Schubert }
490*a466cc55SCy Schubert
491*a466cc55SCy Schubert isc_result_t
isc_sockaddr_frompath(isc_sockaddr_t * sockaddr,const char * path)492*a466cc55SCy Schubert isc_sockaddr_frompath(isc_sockaddr_t *sockaddr, const char *path) {
493*a466cc55SCy Schubert #ifdef ISC_PLATFORM_HAVESYSUNH
494*a466cc55SCy Schubert if (strlen(path) >= sizeof(sockaddr->type.sunix.sun_path))
495*a466cc55SCy Schubert return (ISC_R_NOSPACE);
496*a466cc55SCy Schubert memset(sockaddr, 0, sizeof(*sockaddr));
497*a466cc55SCy Schubert sockaddr->length = sizeof(sockaddr->type.sunix);
498*a466cc55SCy Schubert sockaddr->type.sunix.sun_family = AF_UNIX;
499*a466cc55SCy Schubert #ifdef ISC_PLATFORM_HAVESALEN
500*a466cc55SCy Schubert sockaddr->type.sunix.sun_len =
501*a466cc55SCy Schubert (unsigned char)sizeof(sockaddr->type.sunix);
502*a466cc55SCy Schubert #endif
503*a466cc55SCy Schubert strcpy(sockaddr->type.sunix.sun_path, path);
504*a466cc55SCy Schubert return (ISC_R_SUCCESS);
505*a466cc55SCy Schubert #else
506*a466cc55SCy Schubert UNUSED(sockaddr);
507*a466cc55SCy Schubert UNUSED(path);
508*a466cc55SCy Schubert return (ISC_R_NOTIMPLEMENTED);
509*a466cc55SCy Schubert #endif
510*a466cc55SCy Schubert }
511