1135446Strhodes/*
2262706Serwin * Copyright (C) 2004, 2005, 2007, 2010-2012, 2014  Internet Systems Consortium, Inc. ("ISC")
3135446Strhodes * Copyright (C) 1999-2002  Internet Software Consortium.
4135446Strhodes *
5193149Sdougb * Permission to use, copy, modify, and/or distribute this software for any
6135446Strhodes * purpose with or without fee is hereby granted, provided that the above
7135446Strhodes * copyright notice and this permission notice appear in all copies.
8135446Strhodes *
9135446Strhodes * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10135446Strhodes * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11135446Strhodes * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12135446Strhodes * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13135446Strhodes * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14135446Strhodes * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15135446Strhodes * PERFORMANCE OF THIS SOFTWARE.
16135446Strhodes */
17135446Strhodes
18234010Sdougb/* $Id$ */
19135446Strhodes
20170222Sdougb/*! \file */
21170222Sdougb
22135446Strhodes#include <config.h>
23135446Strhodes
24135446Strhodes#include <stdio.h>
25135446Strhodes
26135446Strhodes#include <isc/buffer.h>
27135446Strhodes#include <isc/msgs.h>
28135446Strhodes#include <isc/net.h>
29135446Strhodes#include <isc/netaddr.h>
30135446Strhodes#include <isc/print.h>
31135446Strhodes#include <isc/sockaddr.h>
32135446Strhodes#include <isc/string.h>
33135446Strhodes#include <isc/util.h>
34135446Strhodes
35135446Strhodesisc_boolean_t
36135446Strhodesisc_netaddr_equal(const isc_netaddr_t *a, const isc_netaddr_t *b) {
37135446Strhodes	REQUIRE(a != NULL && b != NULL);
38135446Strhodes
39135446Strhodes	if (a->family != b->family)
40135446Strhodes		return (ISC_FALSE);
41135446Strhodes
42135446Strhodes	if (a->zone != b->zone)
43135446Strhodes		return (ISC_FALSE);
44135446Strhodes
45135446Strhodes	switch (a->family) {
46135446Strhodes	case AF_INET:
47135446Strhodes		if (a->type.in.s_addr != b->type.in.s_addr)
48135446Strhodes			return (ISC_FALSE);
49135446Strhodes		break;
50135446Strhodes	case AF_INET6:
51135446Strhodes		if (memcmp(&a->type.in6, &b->type.in6,
52135446Strhodes			   sizeof(a->type.in6)) != 0 ||
53135446Strhodes		    a->zone != b->zone)
54135446Strhodes			return (ISC_FALSE);
55135446Strhodes		break;
56170222Sdougb#ifdef ISC_PLATFORM_HAVESYSUNH
57170222Sdougb	case AF_UNIX:
58170222Sdougb		if (strcmp(a->type.un, b->type.un) != 0)
59170222Sdougb			return (ISC_FALSE);
60170222Sdougb		break;
61170222Sdougb#endif
62135446Strhodes	default:
63135446Strhodes		return (ISC_FALSE);
64135446Strhodes	}
65135446Strhodes	return (ISC_TRUE);
66135446Strhodes}
67135446Strhodes
68135446Strhodesisc_boolean_t
69135446Strhodesisc_netaddr_eqprefix(const isc_netaddr_t *a, const isc_netaddr_t *b,
70135446Strhodes		     unsigned int prefixlen)
71135446Strhodes{
72225361Sdougb	const unsigned char *pa = NULL, *pb = NULL;
73225361Sdougb	unsigned int ipabytes = 0; /* Length of whole IP address in bytes */
74225361Sdougb	unsigned int nbytes;       /* Number of significant whole bytes */
75225361Sdougb	unsigned int nbits;        /* Number of significant leftover bits */
76135446Strhodes
77135446Strhodes	REQUIRE(a != NULL && b != NULL);
78135446Strhodes
79135446Strhodes	if (a->family != b->family)
80135446Strhodes		return (ISC_FALSE);
81135446Strhodes
82193149Sdougb	if (a->zone != b->zone && b->zone != 0)
83135446Strhodes		return (ISC_FALSE);
84135446Strhodes
85135446Strhodes	switch (a->family) {
86135446Strhodes	case AF_INET:
87135446Strhodes		pa = (const unsigned char *) &a->type.in;
88135446Strhodes		pb = (const unsigned char *) &b->type.in;
89135446Strhodes		ipabytes = 4;
90135446Strhodes		break;
91135446Strhodes	case AF_INET6:
92135446Strhodes		pa = (const unsigned char *) &a->type.in6;
93135446Strhodes		pb = (const unsigned char *) &b->type.in6;
94135446Strhodes		ipabytes = 16;
95135446Strhodes		break;
96135446Strhodes	default:
97135446Strhodes		return (ISC_FALSE);
98135446Strhodes	}
99135446Strhodes
100135446Strhodes	/*
101135446Strhodes	 * Don't crash if we get a pattern like 10.0.0.1/9999999.
102135446Strhodes	 */
103135446Strhodes	if (prefixlen > ipabytes * 8)
104135446Strhodes		prefixlen = ipabytes * 8;
105135446Strhodes
106135446Strhodes	nbytes = prefixlen / 8;
107135446Strhodes	nbits = prefixlen % 8;
108135446Strhodes
109135446Strhodes	if (nbytes > 0) {
110135446Strhodes		if (memcmp(pa, pb, nbytes) != 0)
111135446Strhodes			return (ISC_FALSE);
112135446Strhodes	}
113135446Strhodes	if (nbits > 0) {
114135446Strhodes		unsigned int bytea, byteb, mask;
115135446Strhodes		INSIST(nbytes < ipabytes);
116135446Strhodes		INSIST(nbits < 8);
117135446Strhodes		bytea = pa[nbytes];
118135446Strhodes		byteb = pb[nbytes];
119135446Strhodes		mask = (0xFF << (8-nbits)) & 0xFF;
120135446Strhodes		if ((bytea & mask) != (byteb & mask))
121135446Strhodes			return (ISC_FALSE);
122135446Strhodes	}
123135446Strhodes	return (ISC_TRUE);
124135446Strhodes}
125135446Strhodes
126135446Strhodesisc_result_t
127135446Strhodesisc_netaddr_totext(const isc_netaddr_t *netaddr, isc_buffer_t *target) {
128135446Strhodes	char abuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
129135446Strhodes	char zbuf[sizeof("%4294967295")];
130135446Strhodes	unsigned int alen;
131135446Strhodes	int zlen;
132135446Strhodes	const char *r;
133135446Strhodes	const void *type;
134135446Strhodes
135135446Strhodes	REQUIRE(netaddr != NULL);
136135446Strhodes
137135446Strhodes	switch (netaddr->family) {
138135446Strhodes	case AF_INET:
139135446Strhodes		type = &netaddr->type.in;
140135446Strhodes		break;
141135446Strhodes	case AF_INET6:
142135446Strhodes		type = &netaddr->type.in6;
143135446Strhodes		break;
144170222Sdougb#ifdef ISC_PLATFORM_HAVESYSUNH
145170222Sdougb	case AF_UNIX:
146170222Sdougb		alen = strlen(netaddr->type.un);
147170222Sdougb		if (alen > isc_buffer_availablelength(target))
148170222Sdougb			return (ISC_R_NOSPACE);
149170222Sdougb		isc_buffer_putmem(target,
150170222Sdougb				  (const unsigned char *)(netaddr->type.un),
151170222Sdougb				  alen);
152170222Sdougb		return (ISC_R_SUCCESS);
153170222Sdougb#endif
154135446Strhodes	default:
155135446Strhodes		return (ISC_R_FAILURE);
156135446Strhodes	}
157135446Strhodes	r = inet_ntop(netaddr->family, type, abuf, sizeof(abuf));
158135446Strhodes	if (r == NULL)
159135446Strhodes		return (ISC_R_FAILURE);
160135446Strhodes
161135446Strhodes	alen = strlen(abuf);
162135446Strhodes	INSIST(alen < sizeof(abuf));
163135446Strhodes
164135446Strhodes	zlen = 0;
165135446Strhodes	if (netaddr->family == AF_INET6 && netaddr->zone != 0) {
166135446Strhodes		zlen = snprintf(zbuf, sizeof(zbuf), "%%%u", netaddr->zone);
167135446Strhodes		if (zlen < 0)
168135446Strhodes			return (ISC_R_FAILURE);
169135446Strhodes		INSIST((unsigned int)zlen < sizeof(zbuf));
170135446Strhodes	}
171135446Strhodes
172135446Strhodes	if (alen + zlen > isc_buffer_availablelength(target))
173135446Strhodes		return (ISC_R_NOSPACE);
174135446Strhodes
175135446Strhodes	isc_buffer_putmem(target, (unsigned char *)abuf, alen);
176135446Strhodes	isc_buffer_putmem(target, (unsigned char *)zbuf, zlen);
177135446Strhodes
178135446Strhodes	return (ISC_R_SUCCESS);
179135446Strhodes}
180135446Strhodes
181135446Strhodesvoid
182135446Strhodesisc_netaddr_format(const isc_netaddr_t *na, char *array, unsigned int size) {
183135446Strhodes	isc_result_t result;
184135446Strhodes	isc_buffer_t buf;
185135446Strhodes
186135446Strhodes	isc_buffer_init(&buf, array, size);
187135446Strhodes	result = isc_netaddr_totext(na, &buf);
188135446Strhodes
189225361Sdougb	if (size == 0)
190225361Sdougb		return;
191225361Sdougb
192135446Strhodes	/*
193135446Strhodes	 * Null terminate.
194135446Strhodes	 */
195135446Strhodes	if (result == ISC_R_SUCCESS) {
196135446Strhodes		if (isc_buffer_availablelength(&buf) >= 1)
197135446Strhodes			isc_buffer_putuint8(&buf, 0);
198135446Strhodes		else
199135446Strhodes			result = ISC_R_NOSPACE;
200135446Strhodes	}
201135446Strhodes
202135446Strhodes	if (result != ISC_R_SUCCESS) {
203135446Strhodes		snprintf(array, size,
204135446Strhodes			 isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR,
205135446Strhodes					ISC_MSG_UNKNOWNADDR,
206135446Strhodes					"<unknown address, family %u>"),
207135446Strhodes			 na->family);
208135446Strhodes		array[size - 1] = '\0';
209135446Strhodes	}
210135446Strhodes}
211135446Strhodes
212170222Sdougb
213135446Strhodesisc_result_t
214170222Sdougbisc_netaddr_prefixok(const isc_netaddr_t *na, unsigned int prefixlen) {
215170222Sdougb	static const unsigned char zeros[16];
216225361Sdougb	unsigned int nbits, nbytes, ipbytes = 0;
217170222Sdougb	const unsigned char *p;
218170222Sdougb
219170222Sdougb	switch (na->family) {
220170222Sdougb	case AF_INET:
221170222Sdougb		p = (const unsigned char *) &na->type.in;
222170222Sdougb		ipbytes = 4;
223170222Sdougb		if (prefixlen > 32)
224170222Sdougb			return (ISC_R_RANGE);
225170222Sdougb		break;
226170222Sdougb	case AF_INET6:
227170222Sdougb		p = (const unsigned char *) &na->type.in6;
228170222Sdougb		ipbytes = 16;
229170222Sdougb		if (prefixlen > 128)
230170222Sdougb			return (ISC_R_RANGE);
231170222Sdougb		break;
232170222Sdougb	default:
233170222Sdougb		return (ISC_R_NOTIMPLEMENTED);
234170222Sdougb	}
235170222Sdougb	nbytes = prefixlen / 8;
236170222Sdougb	nbits = prefixlen % 8;
237170222Sdougb	if (nbits != 0) {
238170222Sdougb		if ((p[nbytes] & (0xff>>nbits)) != 0U)
239170222Sdougb			return (ISC_R_FAILURE);
240170222Sdougb		nbytes++;
241170222Sdougb	}
242170222Sdougb	if (memcmp(p + nbytes, zeros, ipbytes - nbytes) != 0)
243170222Sdougb		return (ISC_R_FAILURE);
244170222Sdougb	return (ISC_R_SUCCESS);
245170222Sdougb}
246170222Sdougb
247170222Sdougbisc_result_t
248135446Strhodesisc_netaddr_masktoprefixlen(const isc_netaddr_t *s, unsigned int *lenp) {
249225361Sdougb	unsigned int nbits = 0, nbytes = 0, ipbytes = 0, i;
250135446Strhodes	const unsigned char *p;
251135446Strhodes
252135446Strhodes	switch (s->family) {
253135446Strhodes	case AF_INET:
254135446Strhodes		p = (const unsigned char *) &s->type.in;
255135446Strhodes		ipbytes = 4;
256135446Strhodes		break;
257135446Strhodes	case AF_INET6:
258135446Strhodes		p = (const unsigned char *) &s->type.in6;
259135446Strhodes		ipbytes = 16;
260135446Strhodes		break;
261135446Strhodes	default:
262135446Strhodes		return (ISC_R_NOTIMPLEMENTED);
263135446Strhodes	}
264135446Strhodes	for (i = 0; i < ipbytes; i++) {
265135446Strhodes		if (p[i] != 0xFF)
266135446Strhodes			break;
267135446Strhodes	}
268135446Strhodes	nbytes = i;
269135446Strhodes	if (i < ipbytes) {
270135446Strhodes		unsigned int c = p[nbytes];
271135446Strhodes		while ((c & 0x80) != 0 && nbits < 8) {
272135446Strhodes			c <<= 1; nbits++;
273135446Strhodes		}
274135446Strhodes		if ((c & 0xFF) != 0)
275135446Strhodes			return (ISC_R_MASKNONCONTIG);
276135446Strhodes		i++;
277135446Strhodes	}
278135446Strhodes	for (; i < ipbytes; i++) {
279135446Strhodes		if (p[i] != 0)
280135446Strhodes			return (ISC_R_MASKNONCONTIG);
281135446Strhodes		i++;
282135446Strhodes	}
283135446Strhodes	*lenp = nbytes * 8 + nbits;
284135446Strhodes	return (ISC_R_SUCCESS);
285135446Strhodes}
286135446Strhodes
287135446Strhodesvoid
288135446Strhodesisc_netaddr_fromin(isc_netaddr_t *netaddr, const struct in_addr *ina) {
289135446Strhodes	memset(netaddr, 0, sizeof(*netaddr));
290135446Strhodes	netaddr->family = AF_INET;
291135446Strhodes	netaddr->type.in = *ina;
292135446Strhodes}
293135446Strhodes
294135446Strhodesvoid
295135446Strhodesisc_netaddr_fromin6(isc_netaddr_t *netaddr, const struct in6_addr *ina6) {
296135446Strhodes	memset(netaddr, 0, sizeof(*netaddr));
297135446Strhodes	netaddr->family = AF_INET6;
298135446Strhodes	netaddr->type.in6 = *ina6;
299135446Strhodes}
300135446Strhodes
301170222Sdougbisc_result_t
302170222Sdougbisc_netaddr_frompath(isc_netaddr_t *netaddr, const char *path) {
303170222Sdougb#ifdef ISC_PLATFORM_HAVESYSUNH
304224092Sdougb	if (strlen(path) > sizeof(netaddr->type.un) - 1)
305224092Sdougb		return (ISC_R_NOSPACE);
306170222Sdougb
307224092Sdougb	memset(netaddr, 0, sizeof(*netaddr));
308224092Sdougb	netaddr->family = AF_UNIX;
309224092Sdougb	strcpy(netaddr->type.un, path);
310224092Sdougb	netaddr->zone = 0;
311224092Sdougb	return (ISC_R_SUCCESS);
312224092Sdougb#else
313170222Sdougb	UNUSED(netaddr);
314170222Sdougb	UNUSED(path);
315224092Sdougb	return (ISC_R_NOTIMPLEMENTED);
316170222Sdougb#endif
317170222Sdougb}
318170222Sdougb
319170222Sdougb
320135446Strhodesvoid
321135446Strhodesisc_netaddr_setzone(isc_netaddr_t *netaddr, isc_uint32_t zone) {
322135446Strhodes	/* we currently only support AF_INET6. */
323135446Strhodes	REQUIRE(netaddr->family == AF_INET6);
324135446Strhodes
325135446Strhodes	netaddr->zone = zone;
326135446Strhodes}
327135446Strhodes
328135446Strhodesisc_uint32_t
329135446Strhodesisc_netaddr_getzone(const isc_netaddr_t *netaddr) {
330135446Strhodes	return (netaddr->zone);
331135446Strhodes}
332135446Strhodes
333135446Strhodesvoid
334135446Strhodesisc_netaddr_fromsockaddr(isc_netaddr_t *t, const isc_sockaddr_t *s) {
335135446Strhodes	int family = s->type.sa.sa_family;
336135446Strhodes	t->family = family;
337135446Strhodes	switch (family) {
338135446Strhodes	case AF_INET:
339135446Strhodes		t->type.in = s->type.sin.sin_addr;
340135446Strhodes		t->zone = 0;
341135446Strhodes		break;
342135446Strhodes	case AF_INET6:
343262706Serwin		memmove(&t->type.in6, &s->type.sin6.sin6_addr, 16);
344135446Strhodes#ifdef ISC_PLATFORM_HAVESCOPEID
345135446Strhodes		t->zone = s->type.sin6.sin6_scope_id;
346135446Strhodes#else
347135446Strhodes		t->zone = 0;
348135446Strhodes#endif
349135446Strhodes		break;
350170222Sdougb#ifdef ISC_PLATFORM_HAVESYSUNH
351170222Sdougb	case AF_UNIX:
352262706Serwin		memmove(t->type.un, s->type.sunix.sun_path, sizeof(t->type.un));
353170222Sdougb		t->zone = 0;
354170222Sdougb		break;
355170222Sdougb#endif
356135446Strhodes	default:
357135446Strhodes		INSIST(0);
358135446Strhodes	}
359135446Strhodes}
360135446Strhodes
361135446Strhodesvoid
362135446Strhodesisc_netaddr_any(isc_netaddr_t *netaddr) {
363135446Strhodes	memset(netaddr, 0, sizeof(*netaddr));
364135446Strhodes	netaddr->family = AF_INET;
365135446Strhodes	netaddr->type.in.s_addr = INADDR_ANY;
366135446Strhodes}
367135446Strhodes
368135446Strhodesvoid
369135446Strhodesisc_netaddr_any6(isc_netaddr_t *netaddr) {
370135446Strhodes	memset(netaddr, 0, sizeof(*netaddr));
371135446Strhodes	netaddr->family = AF_INET6;
372135446Strhodes	netaddr->type.in6 = in6addr_any;
373135446Strhodes}
374135446Strhodes
375135446Strhodesisc_boolean_t
376135446Strhodesisc_netaddr_ismulticast(isc_netaddr_t *na) {
377135446Strhodes	switch (na->family) {
378135446Strhodes	case AF_INET:
379135446Strhodes		return (ISC_TF(ISC_IPADDR_ISMULTICAST(na->type.in.s_addr)));
380135446Strhodes	case AF_INET6:
381135446Strhodes		return (ISC_TF(IN6_IS_ADDR_MULTICAST(&na->type.in6)));
382135446Strhodes	default:
383135446Strhodes		return (ISC_FALSE);  /* XXXMLG ? */
384135446Strhodes	}
385135446Strhodes}
386135446Strhodes
387135446Strhodesisc_boolean_t
388135446Strhodesisc_netaddr_isexperimental(isc_netaddr_t *na) {
389135446Strhodes	switch (na->family) {
390135446Strhodes	case AF_INET:
391135446Strhodes		return (ISC_TF(ISC_IPADDR_ISEXPERIMENTAL(na->type.in.s_addr)));
392135446Strhodes	default:
393135446Strhodes		return (ISC_FALSE);  /* XXXMLG ? */
394135446Strhodes	}
395135446Strhodes}
396135446Strhodes
397135446Strhodesisc_boolean_t
398135446Strhodesisc_netaddr_islinklocal(isc_netaddr_t *na) {
399135446Strhodes	switch (na->family) {
400135446Strhodes	case AF_INET:
401135446Strhodes		return (ISC_FALSE);
402135446Strhodes	case AF_INET6:
403135446Strhodes		return (ISC_TF(IN6_IS_ADDR_LINKLOCAL(&na->type.in6)));
404135446Strhodes	default:
405135446Strhodes		return (ISC_FALSE);
406135446Strhodes	}
407135446Strhodes}
408135446Strhodes
409135446Strhodesisc_boolean_t
410135446Strhodesisc_netaddr_issitelocal(isc_netaddr_t *na) {
411135446Strhodes	switch (na->family) {
412135446Strhodes	case AF_INET:
413135446Strhodes		return (ISC_FALSE);
414135446Strhodes	case AF_INET6:
415135446Strhodes		return (ISC_TF(IN6_IS_ADDR_SITELOCAL(&na->type.in6)));
416135446Strhodes	default:
417135446Strhodes		return (ISC_FALSE);
418135446Strhodes	}
419135446Strhodes}
420135446Strhodes
421135446Strhodesvoid
422135446Strhodesisc_netaddr_fromv4mapped(isc_netaddr_t *t, const isc_netaddr_t *s) {
423135446Strhodes	isc_netaddr_t *src;
424135446Strhodes
425135446Strhodes	DE_CONST(s, src);	/* Must come before IN6_IS_ADDR_V4MAPPED. */
426135446Strhodes
427135446Strhodes	REQUIRE(s->family == AF_INET6);
428135446Strhodes	REQUIRE(IN6_IS_ADDR_V4MAPPED(&src->type.in6));
429135446Strhodes
430135446Strhodes	memset(t, 0, sizeof(*t));
431135446Strhodes	t->family = AF_INET;
432262706Serwin	memmove(&t->type.in, (char *)&src->type.in6 + 12, 4);
433135446Strhodes	return;
434135446Strhodes}
435