Home | History | Annotate | Line # | Download | only in common
      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 (at) 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 
     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 
     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 
    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 
    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 
    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
    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
    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
    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
    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
    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
    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
    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 *
    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 *
    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 *
    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
    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
    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 *
    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