xref: /minix/external/bsd/bind/dist/lib/isc/netaddr.c (revision 00b67f09)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: netaddr.c,v 1.6 2014/12/10 04:37:59 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2004, 2005, 2007, 2010-2012, 2014  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  * Copyright (C) 1999-2002  Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek  *
7*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek  *
11*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek  */
19*00b67f09SDavid van Moolenbroek 
20*00b67f09SDavid van Moolenbroek /* Id */
21*00b67f09SDavid van Moolenbroek 
22*00b67f09SDavid van Moolenbroek /*! \file */
23*00b67f09SDavid van Moolenbroek 
24*00b67f09SDavid van Moolenbroek #include <config.h>
25*00b67f09SDavid van Moolenbroek 
26*00b67f09SDavid van Moolenbroek #include <stdio.h>
27*00b67f09SDavid van Moolenbroek 
28*00b67f09SDavid van Moolenbroek #include <isc/buffer.h>
29*00b67f09SDavid van Moolenbroek #include <isc/msgs.h>
30*00b67f09SDavid van Moolenbroek #include <isc/net.h>
31*00b67f09SDavid van Moolenbroek #include <isc/netaddr.h>
32*00b67f09SDavid van Moolenbroek #include <isc/print.h>
33*00b67f09SDavid van Moolenbroek #include <isc/sockaddr.h>
34*00b67f09SDavid van Moolenbroek #include <isc/string.h>
35*00b67f09SDavid van Moolenbroek #include <isc/util.h>
36*00b67f09SDavid van Moolenbroek 
37*00b67f09SDavid van Moolenbroek isc_boolean_t
isc_netaddr_equal(const isc_netaddr_t * a,const isc_netaddr_t * b)38*00b67f09SDavid van Moolenbroek isc_netaddr_equal(const isc_netaddr_t *a, const isc_netaddr_t *b) {
39*00b67f09SDavid van Moolenbroek 	REQUIRE(a != NULL && b != NULL);
40*00b67f09SDavid van Moolenbroek 
41*00b67f09SDavid van Moolenbroek 	if (a->family != b->family)
42*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);
43*00b67f09SDavid van Moolenbroek 
44*00b67f09SDavid van Moolenbroek 	if (a->zone != b->zone)
45*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);
46*00b67f09SDavid van Moolenbroek 
47*00b67f09SDavid van Moolenbroek 	switch (a->family) {
48*00b67f09SDavid van Moolenbroek 	case AF_INET:
49*00b67f09SDavid van Moolenbroek 		if (a->type.in.s_addr != b->type.in.s_addr)
50*00b67f09SDavid van Moolenbroek 			return (ISC_FALSE);
51*00b67f09SDavid van Moolenbroek 		break;
52*00b67f09SDavid van Moolenbroek 	case AF_INET6:
53*00b67f09SDavid van Moolenbroek 		if (memcmp(&a->type.in6, &b->type.in6,
54*00b67f09SDavid van Moolenbroek 			   sizeof(a->type.in6)) != 0 ||
55*00b67f09SDavid van Moolenbroek 		    a->zone != b->zone)
56*00b67f09SDavid van Moolenbroek 			return (ISC_FALSE);
57*00b67f09SDavid van Moolenbroek 		break;
58*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_HAVESYSUNH
59*00b67f09SDavid van Moolenbroek 	case AF_UNIX:
60*00b67f09SDavid van Moolenbroek 		if (strcmp(a->type.un, b->type.un) != 0)
61*00b67f09SDavid van Moolenbroek 			return (ISC_FALSE);
62*00b67f09SDavid van Moolenbroek 		break;
63*00b67f09SDavid van Moolenbroek #endif
64*00b67f09SDavid van Moolenbroek 	default:
65*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);
66*00b67f09SDavid van Moolenbroek 	}
67*00b67f09SDavid van Moolenbroek 	return (ISC_TRUE);
68*00b67f09SDavid van Moolenbroek }
69*00b67f09SDavid van Moolenbroek 
70*00b67f09SDavid van Moolenbroek isc_boolean_t
isc_netaddr_eqprefix(const isc_netaddr_t * a,const isc_netaddr_t * b,unsigned int prefixlen)71*00b67f09SDavid van Moolenbroek isc_netaddr_eqprefix(const isc_netaddr_t *a, const isc_netaddr_t *b,
72*00b67f09SDavid van Moolenbroek 		     unsigned int prefixlen)
73*00b67f09SDavid van Moolenbroek {
74*00b67f09SDavid van Moolenbroek 	const unsigned char *pa = NULL, *pb = NULL;
75*00b67f09SDavid van Moolenbroek 	unsigned int ipabytes = 0; /* Length of whole IP address in bytes */
76*00b67f09SDavid van Moolenbroek 	unsigned int nbytes;       /* Number of significant whole bytes */
77*00b67f09SDavid van Moolenbroek 	unsigned int nbits;        /* Number of significant leftover bits */
78*00b67f09SDavid van Moolenbroek 
79*00b67f09SDavid van Moolenbroek 	REQUIRE(a != NULL && b != NULL);
80*00b67f09SDavid van Moolenbroek 
81*00b67f09SDavid van Moolenbroek 	if (a->family != b->family)
82*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);
83*00b67f09SDavid van Moolenbroek 
84*00b67f09SDavid van Moolenbroek 	if (a->zone != b->zone && b->zone != 0)
85*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);
86*00b67f09SDavid van Moolenbroek 
87*00b67f09SDavid van Moolenbroek 	switch (a->family) {
88*00b67f09SDavid van Moolenbroek 	case AF_INET:
89*00b67f09SDavid van Moolenbroek 		pa = (const unsigned char *) &a->type.in;
90*00b67f09SDavid van Moolenbroek 		pb = (const unsigned char *) &b->type.in;
91*00b67f09SDavid van Moolenbroek 		ipabytes = 4;
92*00b67f09SDavid van Moolenbroek 		break;
93*00b67f09SDavid van Moolenbroek 	case AF_INET6:
94*00b67f09SDavid van Moolenbroek 		pa = (const unsigned char *) &a->type.in6;
95*00b67f09SDavid van Moolenbroek 		pb = (const unsigned char *) &b->type.in6;
96*00b67f09SDavid van Moolenbroek 		ipabytes = 16;
97*00b67f09SDavid van Moolenbroek 		break;
98*00b67f09SDavid van Moolenbroek 	default:
99*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);
100*00b67f09SDavid van Moolenbroek 	}
101*00b67f09SDavid van Moolenbroek 
102*00b67f09SDavid van Moolenbroek 	/*
103*00b67f09SDavid van Moolenbroek 	 * Don't crash if we get a pattern like 10.0.0.1/9999999.
104*00b67f09SDavid van Moolenbroek 	 */
105*00b67f09SDavid van Moolenbroek 	if (prefixlen > ipabytes * 8)
106*00b67f09SDavid van Moolenbroek 		prefixlen = ipabytes * 8;
107*00b67f09SDavid van Moolenbroek 
108*00b67f09SDavid van Moolenbroek 	nbytes = prefixlen / 8;
109*00b67f09SDavid van Moolenbroek 	nbits = prefixlen % 8;
110*00b67f09SDavid van Moolenbroek 
111*00b67f09SDavid van Moolenbroek 	if (nbytes > 0) {
112*00b67f09SDavid van Moolenbroek 		if (memcmp(pa, pb, nbytes) != 0)
113*00b67f09SDavid van Moolenbroek 			return (ISC_FALSE);
114*00b67f09SDavid van Moolenbroek 	}
115*00b67f09SDavid van Moolenbroek 	if (nbits > 0) {
116*00b67f09SDavid van Moolenbroek 		unsigned int bytea, byteb, mask;
117*00b67f09SDavid van Moolenbroek 		INSIST(nbytes < ipabytes);
118*00b67f09SDavid van Moolenbroek 		INSIST(nbits < 8);
119*00b67f09SDavid van Moolenbroek 		bytea = pa[nbytes];
120*00b67f09SDavid van Moolenbroek 		byteb = pb[nbytes];
121*00b67f09SDavid van Moolenbroek 		mask = (0xFF << (8-nbits)) & 0xFF;
122*00b67f09SDavid van Moolenbroek 		if ((bytea & mask) != (byteb & mask))
123*00b67f09SDavid van Moolenbroek 			return (ISC_FALSE);
124*00b67f09SDavid van Moolenbroek 	}
125*00b67f09SDavid van Moolenbroek 	return (ISC_TRUE);
126*00b67f09SDavid van Moolenbroek }
127*00b67f09SDavid van Moolenbroek 
128*00b67f09SDavid van Moolenbroek isc_result_t
isc_netaddr_totext(const isc_netaddr_t * netaddr,isc_buffer_t * target)129*00b67f09SDavid van Moolenbroek isc_netaddr_totext(const isc_netaddr_t *netaddr, isc_buffer_t *target) {
130*00b67f09SDavid van Moolenbroek 	char abuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
131*00b67f09SDavid van Moolenbroek 	char zbuf[sizeof("%4294967295")];
132*00b67f09SDavid van Moolenbroek 	unsigned int alen;
133*00b67f09SDavid van Moolenbroek 	int zlen;
134*00b67f09SDavid van Moolenbroek 	const char *r;
135*00b67f09SDavid van Moolenbroek 	const void *type;
136*00b67f09SDavid van Moolenbroek 
137*00b67f09SDavid van Moolenbroek 	REQUIRE(netaddr != NULL);
138*00b67f09SDavid van Moolenbroek 
139*00b67f09SDavid van Moolenbroek 	switch (netaddr->family) {
140*00b67f09SDavid van Moolenbroek 	case AF_INET:
141*00b67f09SDavid van Moolenbroek 		type = &netaddr->type.in;
142*00b67f09SDavid van Moolenbroek 		break;
143*00b67f09SDavid van Moolenbroek 	case AF_INET6:
144*00b67f09SDavid van Moolenbroek 		type = &netaddr->type.in6;
145*00b67f09SDavid van Moolenbroek 		break;
146*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_HAVESYSUNH
147*00b67f09SDavid van Moolenbroek 	case AF_UNIX:
148*00b67f09SDavid van Moolenbroek 		alen = strlen(netaddr->type.un);
149*00b67f09SDavid van Moolenbroek 		if (alen > isc_buffer_availablelength(target))
150*00b67f09SDavid van Moolenbroek 			return (ISC_R_NOSPACE);
151*00b67f09SDavid van Moolenbroek 		isc_buffer_putmem(target,
152*00b67f09SDavid van Moolenbroek 				  (const unsigned char *)(netaddr->type.un),
153*00b67f09SDavid van Moolenbroek 				  alen);
154*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
155*00b67f09SDavid van Moolenbroek #endif
156*00b67f09SDavid van Moolenbroek 	default:
157*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
158*00b67f09SDavid van Moolenbroek 	}
159*00b67f09SDavid van Moolenbroek 	r = inet_ntop(netaddr->family, type, abuf, sizeof(abuf));
160*00b67f09SDavid van Moolenbroek 	if (r == NULL)
161*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
162*00b67f09SDavid van Moolenbroek 
163*00b67f09SDavid van Moolenbroek 	alen = strlen(abuf);
164*00b67f09SDavid van Moolenbroek 	INSIST(alen < sizeof(abuf));
165*00b67f09SDavid van Moolenbroek 
166*00b67f09SDavid van Moolenbroek 	zlen = 0;
167*00b67f09SDavid van Moolenbroek 	if (netaddr->family == AF_INET6 && netaddr->zone != 0) {
168*00b67f09SDavid van Moolenbroek 		zlen = snprintf(zbuf, sizeof(zbuf), "%%%u", netaddr->zone);
169*00b67f09SDavid van Moolenbroek 		if (zlen < 0)
170*00b67f09SDavid van Moolenbroek 			return (ISC_R_FAILURE);
171*00b67f09SDavid van Moolenbroek 		INSIST((unsigned int)zlen < sizeof(zbuf));
172*00b67f09SDavid van Moolenbroek 	}
173*00b67f09SDavid van Moolenbroek 
174*00b67f09SDavid van Moolenbroek 	if (alen + zlen > isc_buffer_availablelength(target))
175*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOSPACE);
176*00b67f09SDavid van Moolenbroek 
177*00b67f09SDavid van Moolenbroek 	isc_buffer_putmem(target, (unsigned char *)abuf, alen);
178*00b67f09SDavid van Moolenbroek 	isc_buffer_putmem(target, (unsigned char *)zbuf, zlen);
179*00b67f09SDavid van Moolenbroek 
180*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
181*00b67f09SDavid van Moolenbroek }
182*00b67f09SDavid van Moolenbroek 
183*00b67f09SDavid van Moolenbroek void
isc_netaddr_format(const isc_netaddr_t * na,char * array,unsigned int size)184*00b67f09SDavid van Moolenbroek isc_netaddr_format(const isc_netaddr_t *na, char *array, unsigned int size) {
185*00b67f09SDavid van Moolenbroek 	isc_result_t result;
186*00b67f09SDavid van Moolenbroek 	isc_buffer_t buf;
187*00b67f09SDavid van Moolenbroek 
188*00b67f09SDavid van Moolenbroek 	isc_buffer_init(&buf, array, size);
189*00b67f09SDavid van Moolenbroek 	result = isc_netaddr_totext(na, &buf);
190*00b67f09SDavid van Moolenbroek 
191*00b67f09SDavid van Moolenbroek 	if (size == 0)
192*00b67f09SDavid van Moolenbroek 		return;
193*00b67f09SDavid van Moolenbroek 
194*00b67f09SDavid van Moolenbroek 	/*
195*00b67f09SDavid van Moolenbroek 	 * Null terminate.
196*00b67f09SDavid van Moolenbroek 	 */
197*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS) {
198*00b67f09SDavid van Moolenbroek 		if (isc_buffer_availablelength(&buf) >= 1)
199*00b67f09SDavid van Moolenbroek 			isc_buffer_putuint8(&buf, 0);
200*00b67f09SDavid van Moolenbroek 		else
201*00b67f09SDavid van Moolenbroek 			result = ISC_R_NOSPACE;
202*00b67f09SDavid van Moolenbroek 	}
203*00b67f09SDavid van Moolenbroek 
204*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
205*00b67f09SDavid van Moolenbroek 		snprintf(array, size,
206*00b67f09SDavid van Moolenbroek 			 isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR,
207*00b67f09SDavid van Moolenbroek 					ISC_MSG_UNKNOWNADDR,
208*00b67f09SDavid van Moolenbroek 					"<unknown address, family %u>"),
209*00b67f09SDavid van Moolenbroek 			 na->family);
210*00b67f09SDavid van Moolenbroek 		array[size - 1] = '\0';
211*00b67f09SDavid van Moolenbroek 	}
212*00b67f09SDavid van Moolenbroek }
213*00b67f09SDavid van Moolenbroek 
214*00b67f09SDavid van Moolenbroek 
215*00b67f09SDavid van Moolenbroek isc_result_t
isc_netaddr_prefixok(const isc_netaddr_t * na,unsigned int prefixlen)216*00b67f09SDavid van Moolenbroek isc_netaddr_prefixok(const isc_netaddr_t *na, unsigned int prefixlen) {
217*00b67f09SDavid van Moolenbroek 	static const unsigned char zeros[16];
218*00b67f09SDavid van Moolenbroek 	unsigned int nbits, nbytes, ipbytes = 0;
219*00b67f09SDavid van Moolenbroek 	const unsigned char *p;
220*00b67f09SDavid van Moolenbroek 
221*00b67f09SDavid van Moolenbroek 	switch (na->family) {
222*00b67f09SDavid van Moolenbroek 	case AF_INET:
223*00b67f09SDavid van Moolenbroek 		p = (const unsigned char *) &na->type.in;
224*00b67f09SDavid van Moolenbroek 		ipbytes = 4;
225*00b67f09SDavid van Moolenbroek 		if (prefixlen > 32)
226*00b67f09SDavid van Moolenbroek 			return (ISC_R_RANGE);
227*00b67f09SDavid van Moolenbroek 		break;
228*00b67f09SDavid van Moolenbroek 	case AF_INET6:
229*00b67f09SDavid van Moolenbroek 		p = (const unsigned char *) &na->type.in6;
230*00b67f09SDavid van Moolenbroek 		ipbytes = 16;
231*00b67f09SDavid van Moolenbroek 		if (prefixlen > 128)
232*00b67f09SDavid van Moolenbroek 			return (ISC_R_RANGE);
233*00b67f09SDavid van Moolenbroek 		break;
234*00b67f09SDavid van Moolenbroek 	default:
235*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOTIMPLEMENTED);
236*00b67f09SDavid van Moolenbroek 	}
237*00b67f09SDavid van Moolenbroek 	nbytes = prefixlen / 8;
238*00b67f09SDavid van Moolenbroek 	nbits = prefixlen % 8;
239*00b67f09SDavid van Moolenbroek 	if (nbits != 0) {
240*00b67f09SDavid van Moolenbroek 		INSIST(nbytes < ipbytes);
241*00b67f09SDavid van Moolenbroek 		if ((p[nbytes] & (0xff>>nbits)) != 0U)
242*00b67f09SDavid van Moolenbroek 			return (ISC_R_FAILURE);
243*00b67f09SDavid van Moolenbroek 		nbytes++;
244*00b67f09SDavid van Moolenbroek 	}
245*00b67f09SDavid van Moolenbroek 	if (nbytes < ipbytes && memcmp(p + nbytes, zeros, ipbytes - nbytes) != 0)
246*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
247*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
248*00b67f09SDavid van Moolenbroek }
249*00b67f09SDavid van Moolenbroek 
250*00b67f09SDavid van Moolenbroek isc_result_t
isc_netaddr_masktoprefixlen(const isc_netaddr_t * s,unsigned int * lenp)251*00b67f09SDavid van Moolenbroek isc_netaddr_masktoprefixlen(const isc_netaddr_t *s, unsigned int *lenp) {
252*00b67f09SDavid van Moolenbroek 	unsigned int nbits = 0, nbytes = 0, ipbytes = 0, i;
253*00b67f09SDavid van Moolenbroek 	const unsigned char *p;
254*00b67f09SDavid van Moolenbroek 
255*00b67f09SDavid van Moolenbroek 	switch (s->family) {
256*00b67f09SDavid van Moolenbroek 	case AF_INET:
257*00b67f09SDavid van Moolenbroek 		p = (const unsigned char *) &s->type.in;
258*00b67f09SDavid van Moolenbroek 		ipbytes = 4;
259*00b67f09SDavid van Moolenbroek 		break;
260*00b67f09SDavid van Moolenbroek 	case AF_INET6:
261*00b67f09SDavid van Moolenbroek 		p = (const unsigned char *) &s->type.in6;
262*00b67f09SDavid van Moolenbroek 		ipbytes = 16;
263*00b67f09SDavid van Moolenbroek 		break;
264*00b67f09SDavid van Moolenbroek 	default:
265*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOTIMPLEMENTED);
266*00b67f09SDavid van Moolenbroek 	}
267*00b67f09SDavid van Moolenbroek 	for (i = 0; i < ipbytes; i++) {
268*00b67f09SDavid van Moolenbroek 		if (p[i] != 0xFF)
269*00b67f09SDavid van Moolenbroek 			break;
270*00b67f09SDavid van Moolenbroek 	}
271*00b67f09SDavid van Moolenbroek 	nbytes = i;
272*00b67f09SDavid van Moolenbroek 	if (i < ipbytes) {
273*00b67f09SDavid van Moolenbroek 		unsigned int c = p[nbytes];
274*00b67f09SDavid van Moolenbroek 		while ((c & 0x80) != 0 && nbits < 8) {
275*00b67f09SDavid van Moolenbroek 			c <<= 1; nbits++;
276*00b67f09SDavid van Moolenbroek 		}
277*00b67f09SDavid van Moolenbroek 		if ((c & 0xFF) != 0)
278*00b67f09SDavid van Moolenbroek 			return (ISC_R_MASKNONCONTIG);
279*00b67f09SDavid van Moolenbroek 		i++;
280*00b67f09SDavid van Moolenbroek 	}
281*00b67f09SDavid van Moolenbroek 	for (; i < ipbytes; i++) {
282*00b67f09SDavid van Moolenbroek 		if (p[i] != 0)
283*00b67f09SDavid van Moolenbroek 			return (ISC_R_MASKNONCONTIG);
284*00b67f09SDavid van Moolenbroek 		i++;
285*00b67f09SDavid van Moolenbroek 	}
286*00b67f09SDavid van Moolenbroek 	*lenp = nbytes * 8 + nbits;
287*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
288*00b67f09SDavid van Moolenbroek }
289*00b67f09SDavid van Moolenbroek 
290*00b67f09SDavid van Moolenbroek void
isc_netaddr_fromin(isc_netaddr_t * netaddr,const struct in_addr * ina)291*00b67f09SDavid van Moolenbroek isc_netaddr_fromin(isc_netaddr_t *netaddr, const struct in_addr *ina) {
292*00b67f09SDavid van Moolenbroek 	memset(netaddr, 0, sizeof(*netaddr));
293*00b67f09SDavid van Moolenbroek 	netaddr->family = AF_INET;
294*00b67f09SDavid van Moolenbroek 	netaddr->type.in = *ina;
295*00b67f09SDavid van Moolenbroek }
296*00b67f09SDavid van Moolenbroek 
297*00b67f09SDavid van Moolenbroek void
isc_netaddr_fromin6(isc_netaddr_t * netaddr,const struct in6_addr * ina6)298*00b67f09SDavid van Moolenbroek isc_netaddr_fromin6(isc_netaddr_t *netaddr, const struct in6_addr *ina6) {
299*00b67f09SDavid van Moolenbroek 	memset(netaddr, 0, sizeof(*netaddr));
300*00b67f09SDavid van Moolenbroek 	netaddr->family = AF_INET6;
301*00b67f09SDavid van Moolenbroek 	netaddr->type.in6 = *ina6;
302*00b67f09SDavid van Moolenbroek }
303*00b67f09SDavid van Moolenbroek 
304*00b67f09SDavid van Moolenbroek isc_result_t
isc_netaddr_frompath(isc_netaddr_t * netaddr,const char * path)305*00b67f09SDavid van Moolenbroek isc_netaddr_frompath(isc_netaddr_t *netaddr, const char *path) {
306*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_HAVESYSUNH
307*00b67f09SDavid van Moolenbroek 	if (strlen(path) > sizeof(netaddr->type.un) - 1)
308*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOSPACE);
309*00b67f09SDavid van Moolenbroek 
310*00b67f09SDavid van Moolenbroek 	memset(netaddr, 0, sizeof(*netaddr));
311*00b67f09SDavid van Moolenbroek 	netaddr->family = AF_UNIX;
312*00b67f09SDavid van Moolenbroek 	strcpy(netaddr->type.un, path);
313*00b67f09SDavid van Moolenbroek 	netaddr->zone = 0;
314*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
315*00b67f09SDavid van Moolenbroek #else
316*00b67f09SDavid van Moolenbroek 	UNUSED(netaddr);
317*00b67f09SDavid van Moolenbroek 	UNUSED(path);
318*00b67f09SDavid van Moolenbroek 	return (ISC_R_NOTIMPLEMENTED);
319*00b67f09SDavid van Moolenbroek #endif
320*00b67f09SDavid van Moolenbroek }
321*00b67f09SDavid van Moolenbroek 
322*00b67f09SDavid van Moolenbroek 
323*00b67f09SDavid van Moolenbroek void
isc_netaddr_setzone(isc_netaddr_t * netaddr,isc_uint32_t zone)324*00b67f09SDavid van Moolenbroek isc_netaddr_setzone(isc_netaddr_t *netaddr, isc_uint32_t zone) {
325*00b67f09SDavid van Moolenbroek 	/* we currently only support AF_INET6. */
326*00b67f09SDavid van Moolenbroek 	REQUIRE(netaddr->family == AF_INET6);
327*00b67f09SDavid van Moolenbroek 
328*00b67f09SDavid van Moolenbroek 	netaddr->zone = zone;
329*00b67f09SDavid van Moolenbroek }
330*00b67f09SDavid van Moolenbroek 
331*00b67f09SDavid van Moolenbroek isc_uint32_t
isc_netaddr_getzone(const isc_netaddr_t * netaddr)332*00b67f09SDavid van Moolenbroek isc_netaddr_getzone(const isc_netaddr_t *netaddr) {
333*00b67f09SDavid van Moolenbroek 	return (netaddr->zone);
334*00b67f09SDavid van Moolenbroek }
335*00b67f09SDavid van Moolenbroek 
336*00b67f09SDavid van Moolenbroek void
isc_netaddr_fromsockaddr(isc_netaddr_t * t,const isc_sockaddr_t * s)337*00b67f09SDavid van Moolenbroek isc_netaddr_fromsockaddr(isc_netaddr_t *t, const isc_sockaddr_t *s) {
338*00b67f09SDavid van Moolenbroek 	int family = s->type.sa.sa_family;
339*00b67f09SDavid van Moolenbroek 	t->family = family;
340*00b67f09SDavid van Moolenbroek 	switch (family) {
341*00b67f09SDavid van Moolenbroek 	case AF_INET:
342*00b67f09SDavid van Moolenbroek 		t->type.in = s->type.sin.sin_addr;
343*00b67f09SDavid van Moolenbroek 		t->zone = 0;
344*00b67f09SDavid van Moolenbroek 		break;
345*00b67f09SDavid van Moolenbroek 	case AF_INET6:
346*00b67f09SDavid van Moolenbroek 		memmove(&t->type.in6, &s->type.sin6.sin6_addr, 16);
347*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_HAVESCOPEID
348*00b67f09SDavid van Moolenbroek 		t->zone = s->type.sin6.sin6_scope_id;
349*00b67f09SDavid van Moolenbroek #else
350*00b67f09SDavid van Moolenbroek 		t->zone = 0;
351*00b67f09SDavid van Moolenbroek #endif
352*00b67f09SDavid van Moolenbroek 		break;
353*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_HAVESYSUNH
354*00b67f09SDavid van Moolenbroek 	case AF_UNIX:
355*00b67f09SDavid van Moolenbroek 		memmove(t->type.un, s->type.sunix.sun_path, sizeof(t->type.un));
356*00b67f09SDavid van Moolenbroek 		t->zone = 0;
357*00b67f09SDavid van Moolenbroek 		break;
358*00b67f09SDavid van Moolenbroek #endif
359*00b67f09SDavid van Moolenbroek 	default:
360*00b67f09SDavid van Moolenbroek 		INSIST(0);
361*00b67f09SDavid van Moolenbroek 	}
362*00b67f09SDavid van Moolenbroek }
363*00b67f09SDavid van Moolenbroek 
364*00b67f09SDavid van Moolenbroek void
isc_netaddr_any(isc_netaddr_t * netaddr)365*00b67f09SDavid van Moolenbroek isc_netaddr_any(isc_netaddr_t *netaddr) {
366*00b67f09SDavid van Moolenbroek 	memset(netaddr, 0, sizeof(*netaddr));
367*00b67f09SDavid van Moolenbroek 	netaddr->family = AF_INET;
368*00b67f09SDavid van Moolenbroek 	netaddr->type.in.s_addr = INADDR_ANY;
369*00b67f09SDavid van Moolenbroek }
370*00b67f09SDavid van Moolenbroek 
371*00b67f09SDavid van Moolenbroek void
isc_netaddr_any6(isc_netaddr_t * netaddr)372*00b67f09SDavid van Moolenbroek isc_netaddr_any6(isc_netaddr_t *netaddr) {
373*00b67f09SDavid van Moolenbroek 	memset(netaddr, 0, sizeof(*netaddr));
374*00b67f09SDavid van Moolenbroek 	netaddr->family = AF_INET6;
375*00b67f09SDavid van Moolenbroek 	netaddr->type.in6 = in6addr_any;
376*00b67f09SDavid van Moolenbroek }
377*00b67f09SDavid van Moolenbroek 
378*00b67f09SDavid van Moolenbroek isc_boolean_t
isc_netaddr_ismulticast(isc_netaddr_t * na)379*00b67f09SDavid van Moolenbroek isc_netaddr_ismulticast(isc_netaddr_t *na) {
380*00b67f09SDavid van Moolenbroek 	switch (na->family) {
381*00b67f09SDavid van Moolenbroek 	case AF_INET:
382*00b67f09SDavid van Moolenbroek 		return (ISC_TF(ISC_IPADDR_ISMULTICAST(na->type.in.s_addr)));
383*00b67f09SDavid van Moolenbroek 	case AF_INET6:
384*00b67f09SDavid van Moolenbroek 		return (ISC_TF(IN6_IS_ADDR_MULTICAST(&na->type.in6)));
385*00b67f09SDavid van Moolenbroek 	default:
386*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);  /* XXXMLG ? */
387*00b67f09SDavid van Moolenbroek 	}
388*00b67f09SDavid van Moolenbroek }
389*00b67f09SDavid van Moolenbroek 
390*00b67f09SDavid van Moolenbroek isc_boolean_t
isc_netaddr_isexperimental(isc_netaddr_t * na)391*00b67f09SDavid van Moolenbroek isc_netaddr_isexperimental(isc_netaddr_t *na) {
392*00b67f09SDavid van Moolenbroek 	switch (na->family) {
393*00b67f09SDavid van Moolenbroek 	case AF_INET:
394*00b67f09SDavid van Moolenbroek 		return (ISC_TF(ISC_IPADDR_ISEXPERIMENTAL(na->type.in.s_addr)));
395*00b67f09SDavid van Moolenbroek 	default:
396*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);  /* XXXMLG ? */
397*00b67f09SDavid van Moolenbroek 	}
398*00b67f09SDavid van Moolenbroek }
399*00b67f09SDavid van Moolenbroek 
400*00b67f09SDavid van Moolenbroek isc_boolean_t
isc_netaddr_islinklocal(isc_netaddr_t * na)401*00b67f09SDavid van Moolenbroek isc_netaddr_islinklocal(isc_netaddr_t *na) {
402*00b67f09SDavid van Moolenbroek 	switch (na->family) {
403*00b67f09SDavid van Moolenbroek 	case AF_INET:
404*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);
405*00b67f09SDavid van Moolenbroek 	case AF_INET6:
406*00b67f09SDavid van Moolenbroek 		return (ISC_TF(IN6_IS_ADDR_LINKLOCAL(&na->type.in6)));
407*00b67f09SDavid van Moolenbroek 	default:
408*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);
409*00b67f09SDavid van Moolenbroek 	}
410*00b67f09SDavid van Moolenbroek }
411*00b67f09SDavid van Moolenbroek 
412*00b67f09SDavid van Moolenbroek isc_boolean_t
isc_netaddr_issitelocal(isc_netaddr_t * na)413*00b67f09SDavid van Moolenbroek isc_netaddr_issitelocal(isc_netaddr_t *na) {
414*00b67f09SDavid van Moolenbroek 	switch (na->family) {
415*00b67f09SDavid van Moolenbroek 	case AF_INET:
416*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);
417*00b67f09SDavid van Moolenbroek 	case AF_INET6:
418*00b67f09SDavid van Moolenbroek 		return (ISC_TF(IN6_IS_ADDR_SITELOCAL(&na->type.in6)));
419*00b67f09SDavid van Moolenbroek 	default:
420*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);
421*00b67f09SDavid van Moolenbroek 	}
422*00b67f09SDavid van Moolenbroek }
423*00b67f09SDavid van Moolenbroek 
424*00b67f09SDavid van Moolenbroek void
isc_netaddr_fromv4mapped(isc_netaddr_t * t,const isc_netaddr_t * s)425*00b67f09SDavid van Moolenbroek isc_netaddr_fromv4mapped(isc_netaddr_t *t, const isc_netaddr_t *s) {
426*00b67f09SDavid van Moolenbroek 	isc_netaddr_t *src;
427*00b67f09SDavid van Moolenbroek 
428*00b67f09SDavid van Moolenbroek 	DE_CONST(s, src);	/* Must come before IN6_IS_ADDR_V4MAPPED. */
429*00b67f09SDavid van Moolenbroek 
430*00b67f09SDavid van Moolenbroek 	REQUIRE(s->family == AF_INET6);
431*00b67f09SDavid van Moolenbroek 	REQUIRE(IN6_IS_ADDR_V4MAPPED(&src->type.in6));
432*00b67f09SDavid van Moolenbroek 
433*00b67f09SDavid van Moolenbroek 	memset(t, 0, sizeof(*t));
434*00b67f09SDavid van Moolenbroek 	t->family = AF_INET;
435*00b67f09SDavid van Moolenbroek 	memmove(&t->type.in, (char *)&src->type.in6 + 12, 4);
436*00b67f09SDavid van Moolenbroek 	return;
437*00b67f09SDavid van Moolenbroek }
438