xref: /netbsd/external/mpl/dhcp/dist/common/inet.c (revision 13df4856)
1 /*	$NetBSD: inet.c,v 1.3 2022/04/03 01:10:58 christos Exp $	*/
2 
3 /* inet.c
4 
5    Subroutines to manipulate internet addresses and ports in a safely portable
6    way... */
7 
8 /*
9  * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
10  * Copyright (c) 1995-2003 by Internet Software Consortium
11  *
12  * This Source Code Form is subject to the terms of the Mozilla Public
13  * License, v. 2.0. If a copy of the MPL was not distributed with this
14  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
17  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
19  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
21  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
22  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23  *
24  *   Internet Systems Consortium, Inc.
25  *   PO Box 360
26  *   Newmarket, NH 03857 USA
27  *   <info@isc.org>
28  *   https://www.isc.org/
29  *
30  */
31 
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: inet.c,v 1.3 2022/04/03 01:10:58 christos Exp $");
34 
35 #include "dhcpd.h"
36 
37 /* Return just the network number of an internet address... */
38 
subnet_number(addr,mask)39 struct iaddr subnet_number (addr, mask)
40 	struct iaddr addr;
41 	struct iaddr mask;
42 {
43 	int i;
44 	struct iaddr rv;
45 
46 	if (addr.len > sizeof(addr.iabuf))
47 		log_fatal("subnet_number():%s:%d: Invalid addr length.", MDL);
48 	if (addr.len != mask.len)
49 		log_fatal("subnet_number():%s:%d: Addr/mask length mismatch.",
50 			  MDL);
51 
52 	rv.len = 0;
53 
54 	/* Both addresses must have the same length... */
55 	if (addr.len != mask.len)
56 		return rv;
57 
58 	rv.len = addr.len;
59 	for (i = 0; i < rv.len; i++)
60 		rv.iabuf [i] = addr.iabuf [i] & mask.iabuf [i];
61 	return rv;
62 }
63 
64 /* Combine a network number and a integer to produce an internet address.
65    This won't work for subnets with more than 32 bits of host address, but
66    maybe this isn't a problem. */
67 
ip_addr(subnet,mask,host_address)68 struct iaddr ip_addr (subnet, mask, host_address)
69 	struct iaddr subnet;
70 	struct iaddr mask;
71 	u_int32_t host_address;
72 {
73 	int i, j, k;
74 	u_int32_t swaddr;
75 	struct iaddr rv;
76 	unsigned char habuf [sizeof swaddr];
77 
78 	if (subnet.len > sizeof(subnet.iabuf))
79 		log_fatal("ip_addr():%s:%d: Invalid addr length.", MDL);
80 	if (subnet.len != mask.len)
81 		log_fatal("ip_addr():%s:%d: Addr/mask length mismatch.",
82 			  MDL);
83 
84 	swaddr = htonl (host_address);
85 	memcpy (habuf, &swaddr, sizeof swaddr);
86 
87 	/* Combine the subnet address and the host address.   If
88 	   the host address is bigger than can fit in the subnet,
89 	   return a zero-length iaddr structure. */
90 	rv = subnet;
91 	j = rv.len - sizeof habuf;
92 	for (i = sizeof habuf - 1; i >= 0; i--) {
93 		if (mask.iabuf [i + j]) {
94 			if (habuf [i] > (mask.iabuf [i + j] ^ 0xFF)) {
95 				rv.len = 0;
96 				return rv;
97 			}
98 			for (k = i - 1; k >= 0; k--) {
99 				if (habuf [k]) {
100 					rv.len = 0;
101 					return rv;
102 				}
103 			}
104 			rv.iabuf [i + j] |= habuf [i];
105 			break;
106 		} else
107 			rv.iabuf [i + j] = habuf [i];
108 	}
109 
110 	return rv;
111 }
112 
113 /* Given a subnet number and netmask, return the address on that subnet
114    for which the host portion of the address is all ones (the standard
115    broadcast address). */
116 
broadcast_addr(subnet,mask)117 struct iaddr broadcast_addr (subnet, mask)
118 	struct iaddr subnet;
119 	struct iaddr mask;
120 {
121 	int i;
122 	struct iaddr rv;
123 
124 	if (subnet.len > sizeof(subnet.iabuf))
125 		log_fatal("broadcast_addr():%s:%d: Invalid addr length.", MDL);
126 	if (subnet.len != mask.len)
127 		log_fatal("broadcast_addr():%s:%d: Addr/mask length mismatch.",
128 			  MDL);
129 
130 	if (subnet.len != mask.len) {
131 		rv.len = 0;
132 		return rv;
133 	}
134 
135 	for (i = 0; i < subnet.len; i++) {
136 		rv.iabuf [i] = subnet.iabuf [i] | (~mask.iabuf [i] & 255);
137 	}
138 	rv.len = subnet.len;
139 
140 	return rv;
141 }
142 
host_addr(addr,mask)143 u_int32_t host_addr (addr, mask)
144 	struct iaddr addr;
145 	struct iaddr mask;
146 {
147 	int i;
148 	u_int32_t swaddr;
149 	struct iaddr rv;
150 
151 	if (addr.len > sizeof(addr.iabuf))
152 		log_fatal("host_addr():%s:%d: Invalid addr length.", MDL);
153 	if (addr.len != mask.len)
154 		log_fatal("host_addr():%s:%d: Addr/mask length mismatch.",
155 			  MDL);
156 
157 	rv.len = 0;
158 
159 	/* Mask out the network bits... */
160 	rv.len = addr.len;
161 	for (i = 0; i < rv.len; i++)
162 		rv.iabuf [i] = addr.iabuf [i] & ~mask.iabuf [i];
163 
164 	/* Copy out up to 32 bits... */
165 	memcpy (&swaddr, &rv.iabuf [rv.len - sizeof swaddr], sizeof swaddr);
166 
167 	/* Swap it and return it. */
168 	return ntohl (swaddr);
169 }
170 
addr_eq(addr1,addr2)171 int addr_eq (addr1, addr2)
172 	struct iaddr addr1, addr2;
173 {
174 	if (addr1.len > sizeof(addr1.iabuf))
175 		log_fatal("addr_eq():%s:%d: Invalid addr length.", MDL);
176 
177 	if (addr1.len != addr2.len)
178 		return 0;
179 	return memcmp (addr1.iabuf, addr2.iabuf, addr1.len) == 0;
180 }
181 
182 /* addr_match
183  *
184  * compares an IP address against a network/mask combination
185  * by ANDing the IP with the mask and seeing whether the result
186  * matches the masked network value.
187  */
188 int
addr_match(addr,match)189 addr_match(addr, match)
190 	struct iaddr *addr;
191 	struct iaddrmatch *match;
192 {
193         int i;
194 
195 	if (addr->len != match->addr.len)
196 		return 0;
197 
198 	for (i = 0 ; i < addr->len ; i++) {
199 		if ((addr->iabuf[i] & match->mask.iabuf[i]) !=
200 							match->addr.iabuf[i])
201 			return 0;
202 	}
203 	return 1;
204 }
205 
206 /*
207  * Compares the addresses a1 and a2.
208  *
209  * If a1 < a2, returns -1.
210  * If a1 == a2, returns 0.
211  * If a1 > a2, returns 1.
212  *
213  * WARNING: if a1 and a2 differ in length, returns 0.
214  */
215 int
addr_cmp(const struct iaddr * a1,const struct iaddr * a2)216 addr_cmp(const struct iaddr *a1, const struct iaddr *a2) {
217 	int i;
218 
219 	if (a1->len != a2->len) {
220 		return 0;
221 	}
222 
223 	for (i=0; i<a1->len; i++) {
224 		if (a1->iabuf[i] < a2->iabuf[i]) {
225 			return -1;
226 		}
227 		if (a1->iabuf[i] > a2->iabuf[i]) {
228 			return 1;
229 		}
230 	}
231 
232 	return 0;
233 }
234 
235 /*
236  * Performs a bitwise-OR of two addresses.
237  *
238  * Returns 1 if the result is non-zero, or 0 otherwise.
239  *
240  * WARNING: if a1 and a2 differ in length, returns 0.
241  */
242 int
addr_or(struct iaddr * result,const struct iaddr * a1,const struct iaddr * a2)243 addr_or(struct iaddr *result, const struct iaddr *a1, const struct iaddr *a2) {
244 	int i;
245 	int all_zero;
246 
247 	if (a1->len != a2->len) {
248 		return 0;
249 	}
250 
251 	all_zero = 1;
252 
253 	result->len = a1->len;
254 	for (i=0; i<a1->len; i++) {
255 		result->iabuf[i] = a1->iabuf[i] | a2->iabuf[i];
256 		if (result->iabuf[i] != 0) {
257 			all_zero = 0;
258 		}
259 	}
260 
261 	return !all_zero;
262 }
263 
264 /*
265  * Performs a bitwise-AND of two addresses.
266  *
267  * Returns 1 if the result is non-zero, or 0 otherwise.
268  *
269  * WARNING: if a1 and a2 differ in length, returns 0.
270  */
271 int
addr_and(struct iaddr * result,const struct iaddr * a1,const struct iaddr * a2)272 addr_and(struct iaddr *result, const struct iaddr *a1, const struct iaddr *a2) {
273 	int i;
274 	int all_zero;
275 
276 	if (a1->len != a2->len) {
277 		return 0;
278 	}
279 
280 	all_zero = 1;
281 
282 	result->len = a1->len;
283 	for (i=0; i<a1->len; i++) {
284 		result->iabuf[i] = a1->iabuf[i] & a2->iabuf[i];
285 		if (result->iabuf[i] != 0) {
286 			all_zero = 0;
287 		}
288 	}
289 
290 	return !all_zero;
291 }
292 
293 /*
294  * Check if a bitmask of the given length is valid for the address.
295  * This is not the case if any bits longer than the bitmask are 1.
296  *
297  * So, this is valid:
298  *
299  * 127.0.0.0/8
300  *
301  * But this is not:
302  *
303  * 127.0.0.1/8
304  *
305  * Because the final ".1" would get masked out by the /8.
306  */
307 isc_boolean_t
is_cidr_mask_valid(const struct iaddr * addr,int bits)308 is_cidr_mask_valid(const struct iaddr *addr, int bits) {
309 	int zero_bits;
310 	int zero_bytes;
311 	int i;
312 	char byte;
313 	int shift_bits;
314 
315 	/*
316 	 * Check our bit boundaries.
317 	 */
318 	if (bits < 0) {
319 		return ISC_FALSE;
320 	}
321 	if (bits > (addr->len * 8)) {
322 		return ISC_FALSE;
323 	}
324 
325 	/*
326 	 * Figure out how many low-order bits need to be zero.
327 	 */
328 	zero_bits = (addr->len * 8) - bits;
329 	zero_bytes = zero_bits / 8;
330 
331 	/*
332 	 * Check to make sure the low-order bytes are zero.
333 	 */
334 	for (i=1; i<=zero_bytes; i++) {
335 		if (addr->iabuf[addr->len-i] != 0) {
336 			return ISC_FALSE;
337 		}
338 	}
339 
340 	/*
341 	 * Look to see if any bits not in right-hand bytes are
342 	 * non-zero, by making a byte that has these bits set to zero
343 	 * comparing to the original byte. If these two values are
344 	 * equal, then the right-hand bits are zero, and we are
345 	 * happy.
346 	 */
347 	shift_bits = zero_bits % 8;
348 	if (shift_bits == 0) return ISC_TRUE;
349 	byte = addr->iabuf[addr->len-zero_bytes-1];
350 	return (((byte >> shift_bits) << shift_bits) == byte);
351 }
352 
353 /*
354  * range2cidr
355  *
356  * Converts a range of IP addresses to a set of CIDR networks.
357  *
358  * Examples:
359  *  192.168.0.0 - 192.168.0.255 = 192.168.0.0/24
360  *  10.0.0.0 - 10.0.1.127 = 10.0.0.0/24, 10.0.1.0/25
361  *  255.255.255.32 - 255.255.255.255 = 255.255.255.32/27, 255.255.255.64/26,
362  *  				       255.255.255.128/25
363  */
364 isc_result_t
range2cidr(struct iaddrcidrnetlist ** result,const struct iaddr * lo,const struct iaddr * hi)365 range2cidr(struct iaddrcidrnetlist **result,
366 	   const struct iaddr *lo, const struct iaddr *hi) {
367 	struct iaddr addr;
368 	struct iaddr mask;
369 	int bit;
370 	struct iaddr end_addr;
371 	struct iaddr dummy;
372 	int ofs, val;
373 	struct iaddrcidrnetlist *net;
374 	int tmp;
375 
376 	if (result == NULL) {
377 		return DHCP_R_INVALIDARG;
378 	}
379 	if (*result != NULL) {
380 		return DHCP_R_INVALIDARG;
381 	}
382 	if ((lo == NULL) || (hi == NULL) || (lo->len != hi->len)) {
383 		return DHCP_R_INVALIDARG;
384 	}
385 
386 	/*
387 	 * Put our start and end in the right order, if reversed.
388 	 */
389 	if (addr_cmp(lo, hi) > 0) {
390 		const struct iaddr *tmp;
391 		tmp = lo;
392 		lo = hi;
393 		hi = tmp;
394 	}
395 
396 	/*
397 	 * Theory of operation:
398 	 *
399 	 * -------------------
400 	 * Start at the low end, and keep trying larger networks
401 	 * until we get one that is too big (explained below).
402 	 *
403 	 * We keep a "mask", which is the ones-complement of a
404 	 * normal netmask. So, a /23 has a netmask of 255.255.254.0,
405 	 * and a mask of 0.0.1.255.
406 	 *
407 	 * We know when a network is too big when we bitwise-AND the
408 	 * mask with the starting address and we get a non-zero
409 	 * result, like this:
410 	 *
411 	 *    addr: 192.168.1.0, mask: 0.0.1.255
412 	 *    bitwise-AND: 0.0.1.0
413 	 *
414 	 * A network is also too big if the bitwise-OR of the mask
415 	 * with the starting address is larger than the end address,
416 	 * like this:
417 	 *
418 	 *    start: 192.168.1.0, mask: 0.0.1.255, end: 192.168.0.255
419 	 *    bitwise-OR: 192.168.1.255
420 	 *
421 	 * -------------------
422 	 * Once we have found a network that is too big, we add the
423 	 * appropriate CIDR network to our list of found networks.
424 	 *
425 	 * We then use the next IP address as our low address, and
426 	 * begin the process of searching for a network that is
427 	 * too big again, starting with an empty mask.
428 	 */
429 	addr = *lo;
430 	bit = 0;
431 	memset(&mask, 0, sizeof(mask));
432 	mask.len = addr.len;
433 	while (addr_cmp(&addr, hi) <= 0) {
434 		/*
435 		 * Bitwise-OR mask with (1 << bit)
436 		 */
437 		ofs = addr.len - (bit / 8) - 1;
438 		val = 1 << (bit % 8);
439 		if (ofs >= 0) {
440 			mask.iabuf[ofs] |= val;
441 		}
442 
443 		/*
444 		 * See if we're too big, and save this network if so.
445 		 */
446 		addr_or(&end_addr, &addr, &mask);
447 		if ((ofs < 0) ||
448 		    (addr_cmp(&end_addr, hi) > 0) ||
449 		    addr_and(&dummy, &addr, &mask)) {
450 		    	/*
451 			 * Add a new prefix to our list.
452 			 */
453 			net = dmalloc(sizeof(*net), MDL);
454 			if (net == NULL) {
455 				while (*result != NULL) {
456 					net = (*result)->next;
457 					dfree(*result, MDL);
458 					*result = net;
459 				}
460 				return ISC_R_NOMEMORY;
461 			}
462 			net->cidrnet.lo_addr = addr;
463 			net->cidrnet.bits = (addr.len * 8) - bit;
464 			net->next = *result;
465 			*result = net;
466 
467 		    	/*
468 			 * Figure out our new starting address,
469 			 * by adding (1 << bit) to our previous
470 			 * starting address.
471 			 */
472 			tmp = addr.iabuf[ofs] + val;
473 			while ((ofs >= 0) && (tmp > 255)) {
474 				addr.iabuf[ofs] = tmp - 256;
475 				ofs--;
476 				tmp = addr.iabuf[ofs] + 1;
477 			}
478 			if (ofs < 0) {
479 				/* Gone past last address, we're done. */
480 				break;
481 			}
482 			addr.iabuf[ofs] = tmp;
483 
484 			/*
485 			 * Reset our bit and mask.
486 			 */
487 		    	bit = 0;
488 			memset(mask.iabuf, 0, sizeof(mask.iabuf));
489 			memset(end_addr.iabuf, 0, sizeof(end_addr.iabuf));
490 		} else {
491 			/*
492 			 * If we're not too big, increase our network size.
493 			 */
494 			bit++;
495 		}
496 	}
497 
498 	/*
499 	 * We're done.
500 	 */
501 	return ISC_R_SUCCESS;
502 }
503 
504 /*
505  * Free a list of CIDR networks, such as returned from range2cidr().
506  */
507 isc_result_t
free_iaddrcidrnetlist(struct iaddrcidrnetlist ** result)508 free_iaddrcidrnetlist(struct iaddrcidrnetlist **result) {
509 	struct iaddrcidrnetlist *p;
510 
511 	if (result == NULL) {
512 		return DHCP_R_INVALIDARG;
513 	}
514 	if (*result == NULL) {
515 		return DHCP_R_INVALIDARG;
516 	}
517 
518 	while (*result != NULL) {
519 		p = *result;
520 		*result = p->next;
521 		dfree(p, MDL);
522 	}
523 
524 	return ISC_R_SUCCESS;
525 }
526 
527 /* piaddr() turns an iaddr structure into a printable address. */
528 /* XXX: should use a const pointer rather than passing the structure */
529 const char *
piaddr(const struct iaddr addr)530 piaddr(const struct iaddr addr) {
531 	static char
532 		pbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
533 			 /* "255.255.255.255" */
534 
535 	/* INSIST((addr.len == 0) || (addr.len == 4) || (addr.len == 16)); */
536 
537 	if (addr.len == 0) {
538 		return "<null address>";
539 	}
540 	if (addr.len == 4) {
541 		return inet_ntop(AF_INET, addr.iabuf, pbuf, sizeof(pbuf));
542 	}
543 	if (addr.len == 16) {
544 		return inet_ntop(AF_INET6, addr.iabuf, pbuf, sizeof(pbuf));
545 	}
546 
547 	log_fatal("piaddr():%s:%d: Invalid address length %d.", MDL,
548 		  addr.len);
549 	/* quell compiler warnings */
550 	return NULL;
551 }
552 
553 /* piaddrmask takes an iaddr structure mask, determines the bitlength of
554  * the mask, and then returns the printable CIDR notation of the two.
555  */
556 char *
piaddrmask(struct iaddr * addr,struct iaddr * mask)557 piaddrmask(struct iaddr *addr, struct iaddr *mask) {
558 	int mw;
559 	unsigned int oct, bit;
560 
561 	if ((addr->len != 4) && (addr->len != 16))
562 		log_fatal("piaddrmask():%s:%d: Address length %d invalid",
563 			  MDL, addr->len);
564 	if (addr->len != mask->len)
565 		log_fatal("piaddrmask():%s:%d: Address and mask size mismatch",
566 			  MDL);
567 
568 	/* Determine netmask width in bits. */
569 	for (mw = (mask->len * 8) ; mw > 0 ; ) {
570 		oct = (mw - 1) / 8;
571 		bit = 0x80 >> ((mw - 1) % 8);
572 		if (!mask->iabuf[oct])
573 			mw -= 8;
574 		else if (mask->iabuf[oct] & bit)
575 			break;
576 		else
577 			mw--;
578 	}
579 
580 	if (mw < 0)
581 		log_fatal("Impossible condition at %s:%d.", MDL);
582 
583 	return piaddrcidr(addr, mw);
584 }
585 
586 /* Format an address and mask-length into printable CIDR notation. */
587 char *
piaddrcidr(const struct iaddr * addr,unsigned int bits)588 piaddrcidr(const struct iaddr *addr, unsigned int bits) {
589 	static char
590 	    ret[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128")];
591 		    /* "255.255.255.255/32" */
592 
593 	/* INSIST(addr != NULL); */
594 	/* INSIST((addr->len == 4) || (addr->len == 16)); */
595 	/* INSIST(bits <= (addr->len * 8)); */
596 
597 	if (bits > (addr->len * 8))
598 		return NULL;
599 
600 	sprintf(ret, "%s/%d", piaddr(*addr), bits);
601 
602 	return ret;
603 }
604 
605 /* Validate that the string represents a valid port number and
606  * return it in network byte order
607  */
608 
609 u_int16_t
validate_port(char * port)610 validate_port(char *port) {
611 	long local_port = 0;
612 	long lower = 1;
613 	long upper = 65535;
614 	char *endptr;
615 
616 	errno = 0;
617 	local_port = strtol(port, &endptr, 10);
618 
619 	if ((*endptr != '\0') || (errno == ERANGE) || (errno == EINVAL))
620 		log_fatal ("Invalid port number specification: %s", port);
621 
622 	if (local_port < lower || local_port > upper)
623 		log_fatal("Port number specified is out of range (%ld-%ld).",
624 			  lower, upper);
625 
626 	return htons((u_int16_t)local_port);
627 }
628 
629 /* \brief Validate that the string represents a valid port pair (i.e. n,n+1)
630  *
631  * \param the string to validate
632  * \return the first port number in network byte order
633  */
634 
635 u_int16_t
validate_port_pair(char * port)636 validate_port_pair(char *port) {
637 	long local_port = 0;
638 	long lower = 1;
639 	long upper = 65534;
640 	char *endptr;
641 
642 	errno = 0;
643 	local_port = strtol(port, &endptr, 10);
644 
645 	if ((*endptr != '\0') || (errno == ERANGE) || (errno == EINVAL))
646 		log_fatal ("Invalid port pair specification: %s", port);
647 
648 	if (local_port < lower || local_port > upper)
649 		log_fatal("Port pair specified is out of range (%ld-%ld).",
650 			  lower, upper);
651 
652 	return htons((u_int16_t)local_port);
653 }
654 
655 #ifdef DHCPv6
656 /* Print a v6 address from an in6_addr struct */
657 const char *
pin6_addr(const struct in6_addr * src)658 pin6_addr(const struct in6_addr *src){
659 
660 	if (!src) {
661 		return ("<null>");
662 	}
663 
664 	struct iaddr addr;
665 	addr.len = 16;
666 	memcpy(addr.iabuf, src->s6_addr, 16);
667 	return (piaddr(addr));
668 }
669 #endif
670