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 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