1234949Sbapt/*
2234949Sbapt * Copyright (C) 2004, 2005, 2007, 2010-2012  Internet Systems Consortium, Inc. ("ISC")
3234949Sbapt * Copyright (C) 1999-2002  Internet Software Consortium.
4234949Sbapt *
5234949Sbapt * Permission to use, copy, modify, and/or distribute this software for any
6234949Sbapt * purpose with or without fee is hereby granted, provided that the above
7234949Sbapt * copyright notice and this permission notice appear in all copies.
8234949Sbapt *
9234949Sbapt * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10234949Sbapt * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11234949Sbapt * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12234949Sbapt * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13234949Sbapt * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14234949Sbapt * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15234949Sbapt * PERFORMANCE OF THIS SOFTWARE.
16234949Sbapt */
17234949Sbapt
18234949Sbapt/* $Id$ */
19234949Sbapt
20234949Sbapt/*! \file */
21234949Sbapt
22234949Sbapt#include <config.h>
23234949Sbapt
24234949Sbapt#include <stdio.h>
25234949Sbapt
26234949Sbapt#include <isc/buffer.h>
27234949Sbapt#include <isc/msgs.h>
28234949Sbapt#include <isc/net.h>
29234949Sbapt#include <isc/netaddr.h>
30234949Sbapt#include <isc/print.h>
31234949Sbapt#include <isc/sockaddr.h>
32234949Sbapt#include <isc/string.h>
33234949Sbapt#include <isc/util.h>
34234949Sbapt#include "ntp_stdlib.h"		/* NTP change for strlcpy, strlcat */
35234949Sbapt
36234949Sbaptisc_boolean_t
37234949Sbaptisc_netaddr_equal(const isc_netaddr_t *a, const isc_netaddr_t *b) {
38234949Sbapt	REQUIRE(a != NULL && b != NULL);
39234949Sbapt
40234949Sbapt	if (a->family != b->family)
41234949Sbapt		return (ISC_FALSE);
42234949Sbapt
43234949Sbapt	if (a->zone != b->zone)
44234949Sbapt		return (ISC_FALSE);
45234949Sbapt
46234949Sbapt	switch (a->family) {
47234949Sbapt	case AF_INET:
48234949Sbapt		if (a->type.in.s_addr != b->type.in.s_addr)
49234949Sbapt			return (ISC_FALSE);
50234949Sbapt		break;
51234949Sbapt	case AF_INET6:
52234949Sbapt		if (memcmp(&a->type.in6, &b->type.in6,
53234949Sbapt			   sizeof(a->type.in6)) != 0 ||
54234949Sbapt		    a->zone != b->zone)
55234949Sbapt			return (ISC_FALSE);
56234949Sbapt		break;
57234949Sbapt#ifdef ISC_PLATFORM_HAVESYSUNH
58234949Sbapt	case AF_UNIX:
59234949Sbapt		if (strcmp(a->type.un, b->type.un) != 0)
60234949Sbapt			return (ISC_FALSE);
61234949Sbapt		break;
62234949Sbapt#endif
63234949Sbapt	default:
64234949Sbapt		return (ISC_FALSE);
65234949Sbapt	}
66234949Sbapt	return (ISC_TRUE);
67234949Sbapt}
68234949Sbapt
69234949Sbaptisc_boolean_t
70234949Sbaptisc_netaddr_eqprefix(const isc_netaddr_t *a, const isc_netaddr_t *b,
71234949Sbapt		     unsigned int prefixlen)
72234949Sbapt{
73234949Sbapt	const unsigned char *pa = NULL, *pb = NULL;
74234949Sbapt	unsigned int ipabytes = 0; /* Length of whole IP address in bytes */
75234949Sbapt	unsigned int nbytes;       /* Number of significant whole bytes */
76234949Sbapt	unsigned int nbits;        /* Number of significant leftover bits */
77234949Sbapt
78234949Sbapt	REQUIRE(a != NULL && b != NULL);
79234949Sbapt
80234949Sbapt	if (a->family != b->family)
81234949Sbapt		return (ISC_FALSE);
82234949Sbapt
83234949Sbapt	if (a->zone != b->zone && b->zone != 0)
84234949Sbapt		return (ISC_FALSE);
85234949Sbapt
86234949Sbapt	switch (a->family) {
87234949Sbapt	case AF_INET:
88234949Sbapt		pa = (const unsigned char *) &a->type.in;
89234949Sbapt		pb = (const unsigned char *) &b->type.in;
90234949Sbapt		ipabytes = 4;
91234949Sbapt		break;
92234949Sbapt	case AF_INET6:
93234949Sbapt		pa = (const unsigned char *) &a->type.in6;
94234949Sbapt		pb = (const unsigned char *) &b->type.in6;
95234949Sbapt		ipabytes = 16;
96234949Sbapt		break;
97234949Sbapt	default:
98234949Sbapt		return (ISC_FALSE);
99234949Sbapt	}
100234949Sbapt
101234949Sbapt	/*
102234949Sbapt	 * Don't crash if we get a pattern like 10.0.0.1/9999999.
103234949Sbapt	 */
104234949Sbapt	if (prefixlen > ipabytes * 8)
105234949Sbapt		prefixlen = ipabytes * 8;
106234949Sbapt
107234949Sbapt	nbytes = prefixlen / 8;
108234949Sbapt	nbits = prefixlen % 8;
109234949Sbapt
110234949Sbapt	if (nbytes > 0) {
111234949Sbapt		if (memcmp(pa, pb, nbytes) != 0)
112234949Sbapt			return (ISC_FALSE);
113234949Sbapt	}
114234949Sbapt	if (nbits > 0) {
115234949Sbapt		unsigned int bytea, byteb, mask;
116234949Sbapt		INSIST(nbytes < ipabytes);
117234949Sbapt		INSIST(nbits < 8);
118234949Sbapt		bytea = pa[nbytes];
119234949Sbapt		byteb = pb[nbytes];
120234949Sbapt		mask = (0xFF << (8-nbits)) & 0xFF;
121234949Sbapt		if ((bytea & mask) != (byteb & mask))
122234949Sbapt			return (ISC_FALSE);
123234949Sbapt	}
124234949Sbapt	return (ISC_TRUE);
125234949Sbapt}
126234949Sbapt
127234949Sbaptisc_result_t
128234949Sbaptisc_netaddr_totext(const isc_netaddr_t *netaddr, isc_buffer_t *target) {
129234949Sbapt	char abuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
130234949Sbapt	char zbuf[sizeof("%4294967295")];
131234949Sbapt	unsigned int alen;
132234949Sbapt	int zlen;
133234949Sbapt	const char *r;
134234949Sbapt	const void *type;
135234949Sbapt
136234949Sbapt	REQUIRE(netaddr != NULL);
137234949Sbapt
138234949Sbapt	switch (netaddr->family) {
139234949Sbapt	case AF_INET:
140234949Sbapt		type = &netaddr->type.in;
141234949Sbapt		break;
142234949Sbapt	case AF_INET6:
143234949Sbapt		type = &netaddr->type.in6;
144234949Sbapt		break;
145234949Sbapt#ifdef ISC_PLATFORM_HAVESYSUNH
146234949Sbapt	case AF_UNIX:
147234949Sbapt		alen = strlen(netaddr->type.un);
148234949Sbapt		if (alen > isc_buffer_availablelength(target))
149234949Sbapt			return (ISC_R_NOSPACE);
150234949Sbapt		isc_buffer_putmem(target,
151234949Sbapt				  (const unsigned char *)(netaddr->type.un),
152234949Sbapt				  alen);
153234949Sbapt		return (ISC_R_SUCCESS);
154234949Sbapt#endif
155234949Sbapt	default:
156234949Sbapt		return (ISC_R_FAILURE);
157234949Sbapt	}
158234949Sbapt	r = inet_ntop(netaddr->family, type, abuf, sizeof(abuf));
159234949Sbapt	if (r == NULL)
160234949Sbapt		return (ISC_R_FAILURE);
161234949Sbapt
162234949Sbapt	alen = (unsigned int)strlen(abuf); /* no overflow possible */
163234949Sbapt	INSIST(alen < sizeof(abuf));
164234949Sbapt
165234949Sbapt	zlen = 0;
166234949Sbapt	if (netaddr->family == AF_INET6 && netaddr->zone != 0) {
167234949Sbapt		zlen = snprintf(zbuf, sizeof(zbuf), "%%%u", netaddr->zone);
168234949Sbapt		if (zlen < 0)
169234949Sbapt			return (ISC_R_FAILURE);
170234949Sbapt		INSIST((unsigned int)zlen < sizeof(zbuf));
171234949Sbapt	}
172234949Sbapt
173234949Sbapt	if (alen + zlen > isc_buffer_availablelength(target))
174234949Sbapt		return (ISC_R_NOSPACE);
175234949Sbapt
176234949Sbapt	isc_buffer_putmem(target, (unsigned char *)abuf, alen);
177234949Sbapt	isc_buffer_putmem(target, (unsigned char *)zbuf, zlen);
178234949Sbapt
179234949Sbapt	return (ISC_R_SUCCESS);
180234949Sbapt}
181234949Sbapt
182234949Sbaptvoid
183234949Sbaptisc_netaddr_format(const isc_netaddr_t *na, char *array, unsigned int size) {
184234949Sbapt	isc_result_t result;
185234949Sbapt	isc_buffer_t buf;
186234949Sbapt
187234949Sbapt	isc_buffer_init(&buf, array, size);
188234949Sbapt	result = isc_netaddr_totext(na, &buf);
189234949Sbapt
190234949Sbapt	if (size == 0)
191234949Sbapt		return;
192234949Sbapt
193234949Sbapt	/*
194234949Sbapt	 * Null terminate.
195234949Sbapt	 */
196234949Sbapt	if (result == ISC_R_SUCCESS) {
197234949Sbapt		if (isc_buffer_availablelength(&buf) >= 1)
198234949Sbapt			isc_buffer_putuint8(&buf, 0);
199234949Sbapt		else
200234949Sbapt			result = ISC_R_NOSPACE;
201234949Sbapt	}
202234949Sbapt
203234949Sbapt	if (result != ISC_R_SUCCESS) {
204234949Sbapt		snprintf(array, size,
205234949Sbapt			 "<%s %u>",
206234949Sbapt			 isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR,
207234949Sbapt					ISC_MSG_UNKNOWNADDR,
208234949Sbapt					"unknown address, family"),
209234949Sbapt			 na->family);
210234949Sbapt		array[size - 1] = '\0';
211	}
212}
213
214
215isc_result_t
216isc_netaddr_prefixok(const isc_netaddr_t *na, unsigned int prefixlen) {
217	static const unsigned char zeros[16] = { 0 };
218	unsigned int nbits, nbytes, ipbytes = 0;
219	const unsigned char *p;
220
221	switch (na->family) {
222	case AF_INET:
223		p = (const unsigned char *) &na->type.in;
224		ipbytes = 4;
225		if (prefixlen > 32)
226			return (ISC_R_RANGE);
227		break;
228	case AF_INET6:
229		p = (const unsigned char *) &na->type.in6;
230		ipbytes = 16;
231		if (prefixlen > 128)
232			return (ISC_R_RANGE);
233		break;
234	default:
235		return (ISC_R_NOTIMPLEMENTED);
236	}
237	nbytes = prefixlen / 8;
238	nbits = prefixlen % 8;
239	if (nbits != 0) {
240		if ((p[nbytes] & (0xff>>nbits)) != 0U)
241			return (ISC_R_FAILURE);
242		nbytes++;
243	}
244	if (memcmp(p + nbytes, zeros, ipbytes - nbytes) != 0)
245		return (ISC_R_FAILURE);
246	return (ISC_R_SUCCESS);
247}
248
249isc_result_t
250isc_netaddr_masktoprefixlen(const isc_netaddr_t *s, unsigned int *lenp) {
251	unsigned int nbits = 0, nbytes = 0, ipbytes = 0, i;
252	const unsigned char *p;
253
254	switch (s->family) {
255	case AF_INET:
256		p = (const unsigned char *) &s->type.in;
257		ipbytes = 4;
258		break;
259	case AF_INET6:
260		p = (const unsigned char *) &s->type.in6;
261		ipbytes = 16;
262		break;
263	default:
264		return (ISC_R_NOTIMPLEMENTED);
265	}
266	for (i = 0; i < ipbytes; i++) {
267		if (p[i] != 0xFF)
268			break;
269	}
270	nbytes = i;
271	if (i < ipbytes) {
272		unsigned int c = p[nbytes];
273		while ((c & 0x80) != 0 && nbits < 8) {
274			c <<= 1; nbits++;
275		}
276		if ((c & 0xFF) != 0)
277			return (ISC_R_MASKNONCONTIG);
278		i++;
279	}
280	for (; i < ipbytes; i++) {
281		if (p[i] != 0)
282			return (ISC_R_MASKNONCONTIG);
283	}
284	*lenp = nbytes * 8 + nbits;
285	return (ISC_R_SUCCESS);
286}
287
288void
289isc_netaddr_fromin(isc_netaddr_t *netaddr, const struct in_addr *ina) {
290	memset(netaddr, 0, sizeof(*netaddr));
291	netaddr->family = AF_INET;
292	netaddr->type.in = *ina;
293}
294
295void
296isc_netaddr_fromin6(isc_netaddr_t *netaddr, const struct in6_addr *ina6) {
297	memset(netaddr, 0, sizeof(*netaddr));
298	netaddr->family = AF_INET6;
299	netaddr->type.in6 = *ina6;
300}
301
302isc_result_t
303isc_netaddr_frompath(isc_netaddr_t *netaddr, const char *path) {
304#ifdef ISC_PLATFORM_HAVESYSUNH
305	if (strlen(path) > sizeof(netaddr->type.un) - 1)
306		return (ISC_R_NOSPACE);
307
308        memset(netaddr, 0, sizeof(*netaddr));
309        netaddr->family = AF_UNIX;
310	strlcpy(netaddr->type.un, path, sizeof(netaddr->type.un));
311        netaddr->zone = 0;
312        return (ISC_R_SUCCESS);
313#else
314	UNUSED(netaddr);
315	UNUSED(path);
316	return (ISC_R_NOTIMPLEMENTED);
317#endif
318}
319
320
321void
322isc_netaddr_setzone(isc_netaddr_t *netaddr, isc_uint32_t zone) {
323	/* we currently only support AF_INET6. */
324	REQUIRE(netaddr->family == AF_INET6);
325
326	netaddr->zone = zone;
327}
328
329isc_uint32_t
330isc_netaddr_getzone(const isc_netaddr_t *netaddr) {
331	return (netaddr->zone);
332}
333
334void
335isc_netaddr_fromsockaddr(isc_netaddr_t *t, const isc_sockaddr_t *s) {
336	int family = s->type.sa.sa_family;
337	t->family = family;
338	switch (family) {
339	case AF_INET:
340		t->type.in = s->type.sin.sin_addr;
341		t->zone = 0;
342		break;
343	case AF_INET6:
344		memcpy(&t->type.in6, &s->type.sin6.sin6_addr, 16);
345#ifdef ISC_PLATFORM_HAVESCOPEID
346		t->zone = s->type.sin6.sin6_scope_id;
347#else
348		t->zone = 0;
349#endif
350		break;
351#ifdef ISC_PLATFORM_HAVESYSUNH
352	case AF_UNIX:
353		memcpy(t->type.un, s->type.sunix.sun_path, sizeof(t->type.un));
354		t->zone = 0;
355		break;
356#endif
357	default:
358		INSIST(0);
359	}
360}
361
362void
363isc_netaddr_any(isc_netaddr_t *netaddr) {
364	memset(netaddr, 0, sizeof(*netaddr));
365	netaddr->family = AF_INET;
366	netaddr->type.in.s_addr = INADDR_ANY;
367}
368
369void
370isc_netaddr_any6(isc_netaddr_t *netaddr) {
371	memset(netaddr, 0, sizeof(*netaddr));
372	netaddr->family = AF_INET6;
373	netaddr->type.in6 = in6addr_any;
374}
375
376isc_boolean_t
377isc_netaddr_ismulticast(isc_netaddr_t *na) {
378	switch (na->family) {
379	case AF_INET:
380		return (ISC_TF(ISC_IPADDR_ISMULTICAST(na->type.in.s_addr)));
381	case AF_INET6:
382		return (ISC_TF(IN6_IS_ADDR_MULTICAST(&na->type.in6)));
383	default:
384		return (ISC_FALSE);  /* XXXMLG ? */
385	}
386}
387
388isc_boolean_t
389isc_netaddr_isexperimental(isc_netaddr_t *na) {
390	switch (na->family) {
391	case AF_INET:
392		return (ISC_TF(ISC_IPADDR_ISEXPERIMENTAL(na->type.in.s_addr)));
393	default:
394		return (ISC_FALSE);  /* XXXMLG ? */
395	}
396}
397
398isc_boolean_t
399isc_netaddr_islinklocal(isc_netaddr_t *na) {
400	switch (na->family) {
401	case AF_INET:
402		return (ISC_FALSE);
403	case AF_INET6:
404		return (ISC_TF(IN6_IS_ADDR_LINKLOCAL(&na->type.in6)));
405	default:
406		return (ISC_FALSE);
407	}
408}
409
410isc_boolean_t
411isc_netaddr_issitelocal(isc_netaddr_t *na) {
412	switch (na->family) {
413	case AF_INET:
414		return (ISC_FALSE);
415	case AF_INET6:
416		return (ISC_TF(IN6_IS_ADDR_SITELOCAL(&na->type.in6)));
417	default:
418		return (ISC_FALSE);
419	}
420}
421
422void
423isc_netaddr_fromv4mapped(isc_netaddr_t *t, const isc_netaddr_t *s) {
424	isc_netaddr_t *src;
425
426	DE_CONST(s, src);	/* Must come before IN6_IS_ADDR_V4MAPPED. */
427
428	REQUIRE(s->family == AF_INET6);
429	REQUIRE(IN6_IS_ADDR_V4MAPPED(&src->type.in6));
430
431	memset(t, 0, sizeof(*t));
432	t->family = AF_INET;
433	memcpy(&t->type.in, (char *)&src->type.in6 + 12, 4);
434	return;
435}
436