1 /*
2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * SPDX-License-Identifier: MPL-2.0
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9  *
10  * See the COPYRIGHT file distributed with this work for additional
11  * information regarding copyright ownership.
12  */
13 
14 /*! \file */
15 
16 #include <inttypes.h>
17 #include <stdbool.h>
18 #include <stdio.h>
19 
20 #include <isc/buffer.h>
21 #include <isc/net.h>
22 #include <isc/netaddr.h>
23 #include <isc/print.h>
24 #include <isc/sockaddr.h>
25 #include <isc/string.h>
26 #include <isc/util.h>
27 
28 bool
isc_netaddr_equal(const isc_netaddr_t * a,const isc_netaddr_t * b)29 isc_netaddr_equal(const isc_netaddr_t *a, const isc_netaddr_t *b) {
30 	REQUIRE(a != NULL && b != NULL);
31 
32 	if (a->family != b->family) {
33 		return (false);
34 	}
35 
36 	if (a->zone != b->zone) {
37 		return (false);
38 	}
39 
40 	switch (a->family) {
41 	case AF_INET:
42 		if (a->type.in.s_addr != b->type.in.s_addr) {
43 			return (false);
44 		}
45 		break;
46 	case AF_INET6:
47 		if (memcmp(&a->type.in6, &b->type.in6, sizeof(a->type.in6)) !=
48 			    0 ||
49 		    a->zone != b->zone)
50 		{
51 			return (false);
52 		}
53 		break;
54 #ifdef ISC_PLATFORM_HAVESYSUNH
55 	case AF_UNIX:
56 		if (strcmp(a->type.un, b->type.un) != 0) {
57 			return (false);
58 		}
59 		break;
60 #endif /* ifdef ISC_PLATFORM_HAVESYSUNH */
61 	default:
62 		return (false);
63 	}
64 	return (true);
65 }
66 
67 bool
isc_netaddr_eqprefix(const isc_netaddr_t * a,const isc_netaddr_t * b,unsigned int prefixlen)68 isc_netaddr_eqprefix(const isc_netaddr_t *a, const isc_netaddr_t *b,
69 		     unsigned int prefixlen) {
70 	const unsigned char *pa = NULL, *pb = NULL;
71 	unsigned int ipabytes = 0; /* Length of whole IP address in bytes */
72 	unsigned int nbytes;	   /* Number of significant whole bytes */
73 	unsigned int nbits;	   /* Number of significant leftover bits */
74 
75 	REQUIRE(a != NULL && b != NULL);
76 
77 	if (a->family != b->family) {
78 		return (false);
79 	}
80 
81 	if (a->zone != b->zone && b->zone != 0) {
82 		return (false);
83 	}
84 
85 	switch (a->family) {
86 	case AF_INET:
87 		pa = (const unsigned char *)&a->type.in;
88 		pb = (const unsigned char *)&b->type.in;
89 		ipabytes = 4;
90 		break;
91 	case AF_INET6:
92 		pa = (const unsigned char *)&a->type.in6;
93 		pb = (const unsigned char *)&b->type.in6;
94 		ipabytes = 16;
95 		break;
96 	default:
97 		return (false);
98 	}
99 
100 	/*
101 	 * Don't crash if we get a pattern like 10.0.0.1/9999999.
102 	 */
103 	if (prefixlen > ipabytes * 8) {
104 		prefixlen = ipabytes * 8;
105 	}
106 
107 	nbytes = prefixlen / 8;
108 	nbits = prefixlen % 8;
109 
110 	if (nbytes > 0) {
111 		if (memcmp(pa, pb, nbytes) != 0) {
112 			return (false);
113 		}
114 	}
115 	if (nbits > 0) {
116 		unsigned int bytea, byteb, mask;
117 		INSIST(nbytes < ipabytes);
118 		INSIST(nbits < 8);
119 		bytea = pa[nbytes];
120 		byteb = pb[nbytes];
121 		mask = (0xFF << (8 - nbits)) & 0xFF;
122 		if ((bytea & mask) != (byteb & mask)) {
123 			return (false);
124 		}
125 	}
126 	return (true);
127 }
128 
129 isc_result_t
isc_netaddr_totext(const isc_netaddr_t * netaddr,isc_buffer_t * target)130 isc_netaddr_totext(const isc_netaddr_t *netaddr, isc_buffer_t *target) {
131 	char abuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
132 	char zbuf[sizeof("%4294967295")];
133 	unsigned int alen;
134 	int zlen;
135 	const char *r;
136 	const void *type;
137 
138 	REQUIRE(netaddr != NULL);
139 
140 	switch (netaddr->family) {
141 	case AF_INET:
142 		type = &netaddr->type.in;
143 		break;
144 	case AF_INET6:
145 		type = &netaddr->type.in6;
146 		break;
147 #ifdef ISC_PLATFORM_HAVESYSUNH
148 	case AF_UNIX:
149 		alen = strlen(netaddr->type.un);
150 		if (alen > isc_buffer_availablelength(target)) {
151 			return (ISC_R_NOSPACE);
152 		}
153 		isc_buffer_putmem(target,
154 				  (const unsigned char *)(netaddr->type.un),
155 				  alen);
156 		return (ISC_R_SUCCESS);
157 #endif /* ifdef ISC_PLATFORM_HAVESYSUNH */
158 	default:
159 		return (ISC_R_FAILURE);
160 	}
161 	r = inet_ntop(netaddr->family, type, abuf, sizeof(abuf));
162 	if (r == NULL) {
163 		return (ISC_R_FAILURE);
164 	}
165 
166 	alen = strlen(abuf);
167 	INSIST(alen < sizeof(abuf));
168 
169 	zlen = 0;
170 	if (netaddr->family == AF_INET6 && netaddr->zone != 0) {
171 		zlen = snprintf(zbuf, sizeof(zbuf), "%%%u", netaddr->zone);
172 		if (zlen < 0) {
173 			return (ISC_R_FAILURE);
174 		}
175 		INSIST((unsigned int)zlen < sizeof(zbuf));
176 	}
177 
178 	if (alen + zlen > isc_buffer_availablelength(target)) {
179 		return (ISC_R_NOSPACE);
180 	}
181 
182 	isc_buffer_putmem(target, (unsigned char *)abuf, alen);
183 	isc_buffer_putmem(target, (unsigned char *)zbuf, (unsigned int)zlen);
184 
185 	return (ISC_R_SUCCESS);
186 }
187 
188 void
isc_netaddr_format(const isc_netaddr_t * na,char * array,unsigned int size)189 isc_netaddr_format(const isc_netaddr_t *na, char *array, unsigned int size) {
190 	isc_result_t result;
191 	isc_buffer_t buf;
192 
193 	isc_buffer_init(&buf, array, size);
194 	result = isc_netaddr_totext(na, &buf);
195 
196 	if (size == 0) {
197 		return;
198 	}
199 
200 	/*
201 	 * Null terminate.
202 	 */
203 	if (result == ISC_R_SUCCESS) {
204 		if (isc_buffer_availablelength(&buf) >= 1) {
205 			isc_buffer_putuint8(&buf, 0);
206 		} else {
207 			result = ISC_R_NOSPACE;
208 		}
209 	}
210 
211 	if (result != ISC_R_SUCCESS) {
212 		snprintf(array, size, "<unknown address, family %u>",
213 			 na->family);
214 		array[size - 1] = '\0';
215 	}
216 }
217 
218 isc_result_t
isc_netaddr_prefixok(const isc_netaddr_t * na,unsigned int prefixlen)219 isc_netaddr_prefixok(const isc_netaddr_t *na, unsigned int prefixlen) {
220 	static const unsigned char zeros[16];
221 	unsigned int nbits, nbytes, ipbytes = 0;
222 	const unsigned char *p;
223 
224 	switch (na->family) {
225 	case AF_INET:
226 		p = (const unsigned char *)&na->type.in;
227 		ipbytes = 4;
228 		if (prefixlen > 32) {
229 			return (ISC_R_RANGE);
230 		}
231 		break;
232 	case AF_INET6:
233 		p = (const unsigned char *)&na->type.in6;
234 		ipbytes = 16;
235 		if (prefixlen > 128) {
236 			return (ISC_R_RANGE);
237 		}
238 		break;
239 	default:
240 		return (ISC_R_NOTIMPLEMENTED);
241 	}
242 	nbytes = prefixlen / 8;
243 	nbits = prefixlen % 8;
244 	if (nbits != 0) {
245 		INSIST(nbytes < ipbytes);
246 		if ((p[nbytes] & (0xff >> nbits)) != 0U) {
247 			return (ISC_R_FAILURE);
248 		}
249 		nbytes++;
250 	}
251 	if (nbytes < ipbytes &&
252 	    memcmp(p + nbytes, zeros, ipbytes - nbytes) != 0) {
253 		return (ISC_R_FAILURE);
254 	}
255 	return (ISC_R_SUCCESS);
256 }
257 
258 isc_result_t
isc_netaddr_masktoprefixlen(const isc_netaddr_t * s,unsigned int * lenp)259 isc_netaddr_masktoprefixlen(const isc_netaddr_t *s, unsigned int *lenp) {
260 	unsigned int nbits = 0, nbytes = 0, ipbytes = 0, i;
261 	const unsigned char *p;
262 
263 	switch (s->family) {
264 	case AF_INET:
265 		p = (const unsigned char *)&s->type.in;
266 		ipbytes = 4;
267 		break;
268 	case AF_INET6:
269 		p = (const unsigned char *)&s->type.in6;
270 		ipbytes = 16;
271 		break;
272 	default:
273 		return (ISC_R_NOTIMPLEMENTED);
274 	}
275 	for (i = 0; i < ipbytes; i++) {
276 		if (p[i] != 0xFF) {
277 			break;
278 		}
279 	}
280 	nbytes = i;
281 	if (i < ipbytes) {
282 		unsigned int c = p[nbytes];
283 		while ((c & 0x80) != 0 && nbits < 8) {
284 			c <<= 1;
285 			nbits++;
286 		}
287 		if ((c & 0xFF) != 0) {
288 			return (ISC_R_MASKNONCONTIG);
289 		}
290 		i++;
291 	}
292 	for (; i < ipbytes; i++) {
293 		if (p[i] != 0) {
294 			return (ISC_R_MASKNONCONTIG);
295 		}
296 	}
297 	*lenp = nbytes * 8 + nbits;
298 	return (ISC_R_SUCCESS);
299 }
300 
301 void
isc_netaddr_fromin(isc_netaddr_t * netaddr,const struct in_addr * ina)302 isc_netaddr_fromin(isc_netaddr_t *netaddr, const struct in_addr *ina) {
303 	memset(netaddr, 0, sizeof(*netaddr));
304 	netaddr->family = AF_INET;
305 	netaddr->type.in = *ina;
306 }
307 
308 void
isc_netaddr_fromin6(isc_netaddr_t * netaddr,const struct in6_addr * ina6)309 isc_netaddr_fromin6(isc_netaddr_t *netaddr, const struct in6_addr *ina6) {
310 	memset(netaddr, 0, sizeof(*netaddr));
311 	netaddr->family = AF_INET6;
312 	netaddr->type.in6 = *ina6;
313 }
314 
315 isc_result_t
isc_netaddr_frompath(isc_netaddr_t * netaddr,const char * path)316 isc_netaddr_frompath(isc_netaddr_t *netaddr, const char *path) {
317 #ifdef ISC_PLATFORM_HAVESYSUNH
318 	if (strlen(path) > sizeof(netaddr->type.un) - 1) {
319 		return (ISC_R_NOSPACE);
320 	}
321 
322 	memset(netaddr, 0, sizeof(*netaddr));
323 	netaddr->family = AF_UNIX;
324 	strlcpy(netaddr->type.un, path, sizeof(netaddr->type.un));
325 	netaddr->zone = 0;
326 	return (ISC_R_SUCCESS);
327 #else  /* ifdef ISC_PLATFORM_HAVESYSUNH */
328 	UNUSED(netaddr);
329 	UNUSED(path);
330 	return (ISC_R_NOTIMPLEMENTED);
331 #endif /* ifdef ISC_PLATFORM_HAVESYSUNH */
332 }
333 
334 void
isc_netaddr_setzone(isc_netaddr_t * netaddr,uint32_t zone)335 isc_netaddr_setzone(isc_netaddr_t *netaddr, uint32_t zone) {
336 	/* we currently only support AF_INET6. */
337 	REQUIRE(netaddr->family == AF_INET6);
338 
339 	netaddr->zone = zone;
340 }
341 
342 uint32_t
isc_netaddr_getzone(const isc_netaddr_t * netaddr)343 isc_netaddr_getzone(const isc_netaddr_t *netaddr) {
344 	return (netaddr->zone);
345 }
346 
347 void
isc_netaddr_fromsockaddr(isc_netaddr_t * t,const isc_sockaddr_t * s)348 isc_netaddr_fromsockaddr(isc_netaddr_t *t, const isc_sockaddr_t *s) {
349 	int family = s->type.sa.sa_family;
350 	t->family = family;
351 	switch (family) {
352 	case AF_INET:
353 		t->type.in = s->type.sin.sin_addr;
354 		t->zone = 0;
355 		break;
356 	case AF_INET6:
357 		memmove(&t->type.in6, &s->type.sin6.sin6_addr, 16);
358 		t->zone = s->type.sin6.sin6_scope_id;
359 		break;
360 #ifdef ISC_PLATFORM_HAVESYSUNH
361 	case AF_UNIX:
362 		memmove(t->type.un, s->type.sunix.sun_path, sizeof(t->type.un));
363 		t->zone = 0;
364 		break;
365 #endif /* ifdef ISC_PLATFORM_HAVESYSUNH */
366 	default:
367 		INSIST(0);
368 		ISC_UNREACHABLE();
369 	}
370 }
371 
372 void
isc_netaddr_any(isc_netaddr_t * netaddr)373 isc_netaddr_any(isc_netaddr_t *netaddr) {
374 	memset(netaddr, 0, sizeof(*netaddr));
375 	netaddr->family = AF_INET;
376 	netaddr->type.in.s_addr = INADDR_ANY;
377 }
378 
379 void
isc_netaddr_any6(isc_netaddr_t * netaddr)380 isc_netaddr_any6(isc_netaddr_t *netaddr) {
381 	memset(netaddr, 0, sizeof(*netaddr));
382 	netaddr->family = AF_INET6;
383 	netaddr->type.in6 = in6addr_any;
384 }
385 
386 void
isc_netaddr_unspec(isc_netaddr_t * netaddr)387 isc_netaddr_unspec(isc_netaddr_t *netaddr) {
388 	memset(netaddr, 0, sizeof(*netaddr));
389 	netaddr->family = AF_UNSPEC;
390 }
391 
392 bool
isc_netaddr_ismulticast(const isc_netaddr_t * na)393 isc_netaddr_ismulticast(const isc_netaddr_t *na) {
394 	switch (na->family) {
395 	case AF_INET:
396 		return (ISC_IPADDR_ISMULTICAST(na->type.in.s_addr));
397 	case AF_INET6:
398 		return (IN6_IS_ADDR_MULTICAST(&na->type.in6));
399 	default:
400 		return (false); /* XXXMLG ? */
401 	}
402 }
403 
404 bool
isc_netaddr_isexperimental(const isc_netaddr_t * na)405 isc_netaddr_isexperimental(const isc_netaddr_t *na) {
406 	switch (na->family) {
407 	case AF_INET:
408 		return (ISC_IPADDR_ISEXPERIMENTAL(na->type.in.s_addr));
409 	default:
410 		return (false); /* XXXMLG ? */
411 	}
412 }
413 
414 bool
isc_netaddr_islinklocal(const isc_netaddr_t * na)415 isc_netaddr_islinklocal(const isc_netaddr_t *na) {
416 	switch (na->family) {
417 	case AF_INET:
418 		return (false);
419 	case AF_INET6:
420 		return (IN6_IS_ADDR_LINKLOCAL(&na->type.in6));
421 	default:
422 		return (false);
423 	}
424 }
425 
426 bool
isc_netaddr_issitelocal(const isc_netaddr_t * na)427 isc_netaddr_issitelocal(const isc_netaddr_t *na) {
428 	switch (na->family) {
429 	case AF_INET:
430 		return (false);
431 	case AF_INET6:
432 		return (IN6_IS_ADDR_SITELOCAL(&na->type.in6));
433 	default:
434 		return (false);
435 	}
436 }
437 
438 #define ISC_IPADDR_ISNETZERO(i) \
439 	(((uint32_t)(i)&ISC__IPADDR(0xff000000)) == ISC__IPADDR(0x00000000))
440 
441 bool
isc_netaddr_isnetzero(const isc_netaddr_t * na)442 isc_netaddr_isnetzero(const isc_netaddr_t *na) {
443 	switch (na->family) {
444 	case AF_INET:
445 		return (ISC_IPADDR_ISNETZERO(na->type.in.s_addr));
446 	case AF_INET6:
447 		return (false);
448 	default:
449 		return (false);
450 	}
451 }
452 
453 void
isc_netaddr_fromv4mapped(isc_netaddr_t * t,const isc_netaddr_t * s)454 isc_netaddr_fromv4mapped(isc_netaddr_t *t, const isc_netaddr_t *s) {
455 	isc_netaddr_t *src;
456 
457 	DE_CONST(s, src); /* Must come before IN6_IS_ADDR_V4MAPPED. */
458 
459 	REQUIRE(s->family == AF_INET6);
460 	REQUIRE(IN6_IS_ADDR_V4MAPPED(&src->type.in6));
461 
462 	memset(t, 0, sizeof(*t));
463 	t->family = AF_INET;
464 	memmove(&t->type.in, (char *)&src->type.in6 + 12, 4);
465 	return;
466 }
467 
468 bool
isc_netaddr_isloopback(const isc_netaddr_t * na)469 isc_netaddr_isloopback(const isc_netaddr_t *na) {
470 	switch (na->family) {
471 	case AF_INET:
472 		return (((ntohl(na->type.in.s_addr) & 0xff000000U) ==
473 			 0x7f000000U));
474 	case AF_INET6:
475 		return (IN6_IS_ADDR_LOOPBACK(&na->type.in6));
476 	default:
477 		return (false);
478 	}
479 }
480