1 /* 2 Copyright 2015-2018 Jo-Philipp Wich <jo@mein.io> 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 /** 18 * # Network Address 19 * 20 * The `netaddr` module provides functions and the `netaddr.range` object type 21 * for parsing, validating and manipulating IP addresses, network prefixes and 22 * MAC addresses. 23 * 24 * Address ranges are represented by `netaddr.range` instances which carry the 25 * address, its family and a prefix size (CIDR notation). Instances are 26 * created with the `new()`, `IPv4()`, `IPv6()` or `MAC()` functions: 27 * 28 * ```javascript 29 * import * as netaddr from 'netaddr'; 30 * 31 * const addr = netaddr.new('10.24.0.1/24'); 32 * const addr = netaddr.new('10.24.0.1/255.255.255.0'); 33 * const addr = netaddr.new('10.24.0.1', '255.255.255.0'); // separate netmask 34 * const addr = netaddr.new('10.24.0.1/24', 16); // override netmask 35 * 36 * const addr6 = netaddr.new('fe80::221:63ff:fe75:aa17/64'); 37 * const addr6 = netaddr.new('fe80::221:63ff:fe75:aa17/ffff:ffff:ffff:ffff::'); 38 * 39 * const mac = netaddr.new('00:11:22:cc:dd:ee'); 40 * const mac = netaddr.MAC('C0:B6:F9:00:00:00/24'); 41 * ``` 42 * 43 * The `checkv4()`, `checkv6()` and `checkmac()` functions provide 44 * non-throwing validation, returning the canonical string representation of 45 * the given address or `null` if the argument is not a valid address of the 46 * respective family: 47 * 48 * ```javascript 49 * netaddr.checkv4('127.0.0.1'); // "127.0.0.1" 50 * netaddr.checkv6('::1'); // "::1" 51 * netaddr.checkmac('00:11:22:cc:dd:ee'); // "00:11:22:CC:DD:EE" 52 * netaddr.checkv4('nonsense'); // null 53 * ``` 54 * 55 * @module netaddr 56 */ 57 58 #include <stdio.h> 59 #include <stdint.h> 60 #include <stdbool.h> 61 #include <errno.h> 62 #include <string.h> 63 #include <limits.h> 64 #include <math.h> 65 66 #include <net/if.h> 67 #include <arpa/inet.h> 68 69 #ifndef AF_PACKET 70 #define AF_PACKET 17 71 #endif 72 73 #include "ucode/module.h" 74 75 76 #define AF_BITS(f) \ 77 ((f) == AF_INET ? 32 : \ 78 ((f) == AF_INET6 ? 128 : \ 79 ((f) == AF_PACKET ? 48 : 0))) 80 81 #define AF_BYTES(f) \ 82 ((f) == AF_INET ? 4 : \ 83 ((f) == AF_INET6 ? 16 : \ 84 ((f) == AF_PACKET ? 6 : 0))) 85 86 typedef struct { 87 union { 88 struct in_addr v4; 89 struct in6_addr v6; 90 uint8_t mac[6]; 91 uint8_t u8[16]; 92 } addr; 93 uint32_t scope; 94 uint16_t family; 95 int16_t bits; 96 } range_t; 97 98 static const char *range_type = "netaddr.range"; 99 100 /* 101 * range parsing / formatting 102 */ 103 104 static bool 105 parse_mac(const char *mac, uint8_t *mac_addr) 106 { 107 unsigned long int n; 108 char *e, sep = 0; 109 int i; 110 111 for (i = 0; i < 6; i++) { 112 if (i > 0) { 113 if (sep == 0 && (mac[0] == ':' || mac[0] == '-')) 114 sep = mac[0]; 115 116 if (sep == 0 || mac[0] != sep) 117 return false; 118 119 mac++; 120 } 121 122 n = strtoul(mac, &e, 16); 123 124 if (n > 0xFF) 125 return false; 126 127 mac += (e - mac); 128 mac_addr[i] = n; 129 } 130 131 if (mac[0] != 0) 132 return false; 133 134 return true; 135 } 136 137 static bool 138 parse_mask(int family, const char *mask, int16_t *bits) 139 { 140 char *e; 141 union { 142 struct in_addr v4; 143 struct in6_addr v6; 144 uint8_t mac[6]; 145 uint8_t u8[16]; 146 } m; 147 148 if (family == AF_INET && inet_pton(AF_INET, mask, &m.v4)) { 149 for (*bits = 0, m.v4.s_addr = ntohl(m.v4.s_addr); 150 *bits < AF_BITS(AF_INET) && (m.v4.s_addr << *bits) & 0x80000000; 151 ++*bits); 152 } 153 else if ((family == AF_INET6 && inet_pton(AF_INET6, mask, &m.v6)) || 154 (family == AF_PACKET && parse_mac(mask, m.mac))) { 155 for (*bits = 0; 156 *bits < AF_BITS(family) && (m.u8[*bits / 8] << (*bits % 8)) & 128; 157 ++*bits); 158 } 159 else { 160 *bits = strtoul(mask, &e, 10); 161 162 if (e == mask || *e != 0 || *bits > AF_BITS(family)) 163 return false; 164 } 165 166 return true; 167 } 168 169 static bool 170 parse_range(const char *dest, range_t *pp) 171 { 172 char *p, *s, buf[INET6_ADDRSTRLEN * 2 + 2]; 173 174 strncpy(buf, dest, sizeof(buf) - 1); 175 buf[sizeof(buf) - 1] = '\0'; 176 177 p = strchr(buf, '/'); 178 179 if (p) 180 *p++ = 0; 181 182 s = strchr(buf, '%'); 183 184 if (s) 185 *s++ = 0; 186 187 if (inet_pton(AF_INET, buf, &pp->addr.v4)) 188 pp->family = AF_INET; 189 else if (inet_pton(AF_INET6, buf, &pp->addr.v6)) 190 pp->family = AF_INET6; 191 else if (parse_mac(buf, pp->addr.mac)) 192 pp->family = AF_PACKET; 193 else 194 return false; 195 196 if (s) { 197 if (pp->family != AF_INET6) 198 return false; 199 200 if (!(pp->addr.v6.s6_addr[0] == 0xFE && 201 pp->addr.v6.s6_addr[1] >= 0x80 && 202 pp->addr.v6.s6_addr[2] <= 0xBF)) 203 return false; 204 205 pp->scope = if_nametoindex(s); 206 207 if (pp->scope == 0) 208 return false; 209 } 210 else { 211 pp->scope = 0; 212 } 213 214 if (p) { 215 if (!parse_mask(pp->family, p, &pp->bits)) 216 return false; 217 } 218 else { 219 pp->bits = AF_BITS(pp->family); 220 } 221 222 return true; 223 } 224 225 static uc_value_t * 226 format_range(uc_vm_t *vm, range_t *p) 227 { 228 uc_stringbuf_t *buf = ucv_stringbuf_new(); 229 char tmp[INET6_ADDRSTRLEN + IF_NAMESIZE + 1]; 230 231 if (p->family == AF_PACKET) { 232 ucv_stringbuf_printf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", 233 p->addr.mac[0], 234 p->addr.mac[1], 235 p->addr.mac[2], 236 p->addr.mac[3], 237 p->addr.mac[4], 238 p->addr.mac[5]); 239 240 if (p->scope != 0) { 241 if (if_indextoname(p->scope, tmp) != NULL) 242 ucv_stringbuf_printf(buf, "%%%s", tmp); 243 } 244 245 if (p->bits < AF_BITS(AF_PACKET)) 246 ucv_stringbuf_printf(buf, "/%d", p->bits); 247 } 248 else { 249 size_t len; 250 251 if (!inet_ntop(p->family, &p->addr.v6, tmp, sizeof(tmp))) 252 goto err; 253 254 len = strlen(tmp); 255 256 if (p->scope != 0 && if_indextoname(p->scope, tmp + len + 1) != NULL) { 257 tmp[len++] = '%'; 258 len += strlen(tmp + len); 259 } 260 261 ucv_stringbuf_addstr(buf, tmp, len); 262 263 if (p->bits < AF_BITS(p->family)) 264 ucv_stringbuf_printf(buf, "/%d", p->bits); 265 } 266 267 return ucv_stringbuf_finish(buf); 268 269 err: 270 ucv_put(ucv_stringbuf_finish(buf)); 271 272 return NULL; 273 } 274 275 /* 276 * range value accessors 277 */ 278 279 static inline range_t * 280 get_this_range(uc_vm_t *vm) 281 { 282 range_t **p = uc_fn_this(range_type); 283 284 return p ? *p : NULL; 285 } 286 287 /* Accept a range instance or a string convertible to one, returning a pointer 288 * to the internal range of the instance or to *out for parsed strings */ 289 static range_t * 290 check_range(uc_vm_t *vm, uc_value_t *arg, range_t *out, int family) 291 { 292 if (ucv_type(arg) == UC_RESOURCE) { 293 void **p = ucv_resource_dataptr(arg, range_type); 294 295 if (p && *(range_t **)p && 296 (!family || (*(range_t **)p)->family == family)) 297 return *(range_t **)p; 298 299 return NULL; 300 } 301 302 if (ucv_type(arg) == UC_STRING) { 303 if (parse_range(ucv_string_get(arg), out) && 304 (!family || out->family == family)) 305 return out; 306 } 307 308 return NULL; 309 } 310 311 static bool 312 check_bits(uc_vm_t *vm, uc_value_t *arg, range_t *p, int16_t *bits) 313 { 314 uint64_t n; 315 int16_t s16; 316 317 if (arg == NULL) { 318 *bits = p->bits; 319 return true; 320 } 321 322 if (ucv_type(arg) == UC_INTEGER || ucv_type(arg) == UC_DOUBLE) { 323 n = ucv_to_unsigned(arg); 324 325 if (errno != 0 || n > AF_BITS(p->family)) 326 return false; 327 328 *bits = (int16_t)n; 329 return true; 330 } 331 332 if (ucv_type(arg) == UC_STRING) { 333 if (!parse_mask(p->family, ucv_string_get(arg), &s16)) 334 return false; 335 336 *bits = s16; 337 return true; 338 } 339 340 return false; 341 } 342 343 static uc_value_t * 344 new_range(uc_vm_t *vm, range_t *rng) 345 { 346 range_t *p = xalloc(sizeof(*p)); 347 348 *p = *rng; 349 350 return ucv_resource_new(ucv_resource_type_lookup(vm, range_type), p); 351 } 352 353 /* 354 * scope handling 355 */ 356 357 static uint32_t 358 parse_scope(uc_vm_t *vm, uc_value_t *scope, range_t *p, bool strict) 359 { 360 uint32_t idx = (uint32_t)-1; 361 362 /* 363 * the scope carries the interface the address is bound to; it is 364 * valid for MAC addresses and for IPv6 link-local addresses 365 * (fe80::/10), matching the %scope handling in parse_range() 366 */ 367 if (p->family == AF_PACKET || 368 (p->family == AF_INET6 && 369 p->addr.v6.s6_addr[0] == 0xFE && 370 p->addr.v6.s6_addr[1] >= 0x80 && 371 p->addr.v6.s6_addr[2] <= 0xBF)) { 372 if (ucv_type(scope) == UC_INTEGER) { 373 uint64_t n = ucv_to_unsigned(scope); 374 375 /* 376 * like the socket module, the integer scope id is 377 * taken as-is without resolving it to an interface 378 */ 379 if (errno == 0 && n <= UINT32_MAX) 380 idx = (uint32_t)n; 381 } 382 else if (ucv_type(scope) == UC_STRING) { 383 idx = if_nametoindex(ucv_string_get(scope)); 384 idx = (idx == 0) ? (uint32_t)-1 : idx; 385 } 386 387 if (idx == (uint32_t)-1 && strict) { 388 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, 389 "Invalid scope"); 390 391 return 0; 392 } 393 } 394 395 return idx; 396 } 397 398 /* 399 * module functions 400 */ 401 402 static bool 403 parse_addr(uc_vm_t *vm, uc_value_t *addr, int family, range_t *out) 404 { 405 uint64_t n; 406 size_t i, len; 407 408 if (ucv_type(addr) == UC_ARRAY) { 409 int fam; 410 411 switch (ucv_array_length(addr)) { 412 case 4: 413 fam = AF_INET; 414 break; 415 416 case 6: 417 fam = AF_PACKET; 418 break; 419 420 case 16: 421 fam = AF_INET6; 422 break; 423 424 default: 425 return false; 426 } 427 428 if (family && family != fam) 429 return false; 430 431 out->family = fam; 432 out->bits = AF_BITS(fam); 433 434 for (i = 0, len = ucv_array_length(addr); i < len; i++) { 435 uc_value_t *v = ucv_array_get(addr, i); 436 437 if (ucv_type(v) != UC_INTEGER && ucv_type(v) != UC_DOUBLE) 438 return false; 439 440 n = ucv_to_unsigned(v); 441 442 if (errno != 0 || n > 255) 443 return false; 444 445 out->addr.u8[i] = n; 446 } 447 448 return true; 449 } 450 451 if (ucv_type(addr) == UC_OBJECT) { 452 /* 453 * sockaddr-like object: { family, address, interface } 454 * 455 * family: optional, one of AF_INET, AF_INET6, AF_PACKET; 456 * guessed from the address if omitted 457 * address: mandatory address string 458 * interface: optional, AF_INET6 scope (name or index) 459 */ 460 uc_value_t *v, *addrv; 461 char buf[INET6_ADDRSTRLEN * 2 + 2]; 462 bool found; 463 int fam = family; 464 465 addrv = ucv_object_get(addr, "address", &found); 466 467 if (!found || ucv_type(addrv) != UC_STRING) 468 return false; 469 470 v = ucv_object_get(addr, "family", &found); 471 472 if (found) { 473 if (ucv_type(v) != UC_INTEGER) 474 return false; 475 476 switch (ucv_int64_get(v)) { 477 case AF_INET: 478 case AF_INET6: 479 case AF_PACKET: 480 fam = (int)ucv_int64_get(v); 481 break; 482 483 default: 484 return false; 485 } 486 } 487 else 488 fam = (strchr(ucv_string_get(addrv), ':') != NULL) 489 ? AF_INET6 : AF_INET; 490 491 if (family && family != fam) 492 return false; 493 494 if (ucv_string_length(addrv) + 1 > sizeof(buf)) 495 return false; 496 497 memcpy(buf, ucv_string_get(addrv), 498 ucv_string_length(addrv) + 1); 499 500 if (!parse_range(buf, out)) 501 return false; 502 503 /* parse_range may have auto-detected a different family */ 504 if (out->family != fam) 505 return false; 506 507 v = ucv_object_get(addr, "interface", &found); 508 509 if (found) { 510 if (out->family != AF_INET6) 511 return false; 512 513 /* 514 * the scope is only valid for link-local addresses, 515 * matching the %scope handling in parse_range() 516 */ 517 if (!(out->addr.v6.s6_addr[0] == 0xFE && 518 out->addr.v6.s6_addr[1] >= 0x80 && 519 out->addr.v6.s6_addr[2] <= 0xBF)) 520 return false; 521 522 out->scope = parse_scope(vm, v, out, true); 523 } 524 525 return true; 526 } 527 528 if (ucv_type(addr) == UC_INTEGER || ucv_type(addr) == UC_DOUBLE) { 529 n = ucv_to_unsigned(addr); 530 531 if (errno != 0) 532 return false; 533 534 switch (family) { 535 case AF_INET: 536 out->family = AF_INET; 537 out->addr.v4.s_addr = htonl((uint32_t)n); 538 break; 539 540 case AF_INET6: 541 out->family = AF_INET6; 542 out->addr.v6.s6_addr[12] = n / 0x1000000; 543 out->addr.v6.s6_addr[13] = n % 0x1000000 / 0x10000; 544 out->addr.v6.s6_addr[14] = n % 0x10000 / 0x100; 545 out->addr.v6.s6_addr[15] = n % 0x100; 546 break; 547 548 default: 549 out->family = AF_PACKET; 550 out->addr.mac[2] = n / 0x1000000; 551 out->addr.mac[3] = n % 0x1000000 / 0x10000; 552 out->addr.mac[4] = n % 0x10000 / 0x100; 553 out->addr.mac[5] = n % 0x100; 554 break; 555 } 556 557 out->bits = AF_BITS(out->family); 558 return true; 559 } 560 561 if (ucv_type(addr) == UC_STRING && 562 parse_range(ucv_string_get(addr), out) && 563 (!family || out->family == family)) 564 return true; 565 566 return false; 567 } 568 569 /** 570 * Construct a new `netaddr.range` instance, auto-detecting the address family. 571 * 572 * Raises a runtime exception if the given argument does not represent a 573 * valid address or if the given optional netmask is of a different family. 574 * 575 * @function module:netaddr#new 576 * 577 * @param {string|number|number[]|object} address 578 * A valid IPv4 or IPv6 address, optionally with prefix size (CIDR notation) 579 * or netmask separated by slash, an unsigned number, an array of bytes, or 580 * a sockaddr-like object (see below). 581 * Numbers are interpreted as MAC addresses, except when used with the 582 * {@link module:netaddr#v4} or {@link module:netaddr#v6} constructors. The 583 * address family of byte arrays is determined by their length: `4` for 584 * IPv4, `6` for MAC and `16` for IPv6. 585 * 586 * A sockaddr-like object has the following properties: 587 * 588 * - `address` (string, mandatory): the address value 589 * - `family` (number, optional): `AF_INET` (2), `AF_INET6` (10) or 590 * `AF_PACKET` (17, MAC); guessed from `address` if omitted 591 * - `interface` (string|number, optional): scope for `AF_INET6` addresses, 592 * either an interface name or index 593 * 594 * @param {string|number} [netmask] 595 * A valid IPv4 or IPv6 netmask or a number containing a prefix size in bits 596 * (`0..32` for IPv4, `0..128` for IPv6). Overrides the mask embedded in the 597 * first argument if specified. 598 * 599 * @returns {module:netaddr.range} 600 * 601 * @example 602 * const addr = netaddr.new('10.24.0.1/24'); 603 * const addr = netaddr.new('10.24.0.1/255.255.255.0'); 604 * const addr = netaddr.new('10.24.0.1', '255.255.255.0'); // separate netmask 605 * const addr = netaddr.new('10.24.0.1/24', 16); // override netmask 606 * 607 * const addr6 = netaddr.new('fe80::221:63ff:fe75:aa17/64'); 608 * const addr6 = netaddr.new('fe80::221:63ff:fe75:aa17/ffff:ffff:ffff:ffff::'); 609 * 610 * const mac = netaddr.new('00:11:22:cc:dd:ee'); 611 * const mac = netaddr.new(0x001122ccddeeff); 612 * 613 * const addr = netaddr.new([ 10, 24, 0, 1 ]); // IPv4 614 * const addr6 = netaddr.new([ 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ]); 615 * 616 * const addr = netaddr.new({ address: '10.24.0.1' }); // family guessed 617 * const addr = netaddr.new({ family: 2, address: '10.24.0.1' }); 618 * const addr6 = netaddr.new({ family: 10, address: 'fe80::1', interface: 'lo' }); 619 */ 620 static uc_value_t * 621 uc_netaddr_new(uc_vm_t *vm, size_t nargs) 622 { 623 uc_value_t *addr = uc_fn_arg(0); 624 range_t rng = { }; 625 626 if (!parse_addr(vm, addr, 0, &rng)) { 627 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, 628 "Invalid address"); 629 630 return NULL; 631 } 632 633 /* 634 * Numbers cannot carry an embedded netmask, ignore the second 635 * constructor argument (matches the LuCI reference behavior). 636 */ 637 if (nargs > 1 && ucv_type(addr) == UC_STRING) { 638 int16_t bits; 639 640 if (!check_bits(vm, uc_fn_arg(1), &rng, &bits)) { 641 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, 642 "Invalid netmask"); 643 644 return NULL; 645 } 646 647 rng.bits = bits; 648 } 649 650 return new_range(vm, &rng); 651 } 652 653 /** 654 * Construct a new IPv4 `netaddr.range` instance. 655 * 656 * Raises a runtime exception if the given argument does not represent a 657 * valid IPv4 address or if the given optional netmask is of a different 658 * family. 659 * 660 * @function module:netaddr#v4 661 * 662 * @param {string|number|number[]|object} address 663 * A valid IPv4 address, optionally with prefix size (CIDR notation) or 664 * netmask separated by slash, an unsigned number representing the address 665 * in host byte order, an array of exactly `4` bytes, or a sockaddr-like 666 * object with `family` `AF_INET` (or an address guessed as IPv4). 667 * 668 * @param {string|number} [netmask] 669 * A valid IPv4 netmask or a number containing a prefix size between `0` 670 * and `32` bit. Overrides the mask embedded in the first argument if 671 * specified. 672 * 673 * @returns {module:netaddr.range} 674 * 675 * @example 676 * const addr = netaddr.IPv4('10.24.0.1/24'); 677 * const addr = netaddr.IPv4('10.24.0.1/255.255.255.0'); 678 * const addr = netaddr.IPv4('10.24.0.1', '255.255.255.0'); // separate netmask 679 * const addr = netaddr.IPv4('10.24.0.1/24', 16); // override netmask 680 */ 681 static uc_value_t * 682 uc_netaddr_v4(uc_vm_t *vm, size_t nargs) 683 { 684 uc_value_t *addr = uc_fn_arg(0); 685 range_t rng = { }; 686 687 if (!parse_addr(vm, addr, AF_INET, &rng)) { 688 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, 689 "Invalid IPv4 address"); 690 691 return NULL; 692 } 693 694 if (nargs > 1 && ucv_type(addr) == UC_STRING) { 695 int16_t bits; 696 697 if (!check_bits(vm, uc_fn_arg(1), &rng, &bits)) { 698 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, 699 "Invalid netmask"); 700 701 return NULL; 702 } 703 704 rng.bits = bits; 705 } 706 707 return new_range(vm, &rng); 708 } 709 710 /** 711 * Construct a new IPv6 `netaddr.range` instance. 712 * 713 * Raises a runtime exception if the given argument does not represent a 714 * valid IPv6 address or if the given optional netmask is of a different 715 * family. 716 * 717 * @function module:netaddr#v6 718 * 719 * @param {string|number|number[]|object} address 720 * A valid IPv6 address, optionally with prefix size (CIDR notation) or 721 * netmask separated by slash, an unsigned number representing the last 722 * 32 bit of the address, an array of exactly `16` bytes, or a 723 * sockaddr-like object with `family` `AF_INET6` (or an address guessed as 724 * IPv6), optionally carrying an `interface` scope. 725 * 726 * @param {string|number} [netmask] 727 * A valid IPv6 netmask or a number containing a prefix size between `0` 728 * and `128` bit. Overrides the mask embedded in the first argument if 729 * specified. 730 * 731 * @param {string|number} [scope] 732 * An optional address scope for link-local addresses (`fe80::/10`), 733 * either an interface name or numeric index. 734 * 735 * @returns {module:netaddr.range} 736 * 737 * @example 738 * const addr6 = netaddr.IPv6('fe80::221:63ff:fe75:aa17/64'); 739 * const addr6 = netaddr.IPv6('fe80::221:63ff:fe75:aa17/ffff:ffff:ffff:ffff::'); 740 * const addr6 = netaddr.IPv6('fe80::221:63ff:fe75:aa17', 'ffff:ffff:ffff:ffff::'); 741 * const addr6 = netaddr.IPv6('fe80::221:63ff:fe75:aa17/64', 128); // override 742 * const addr6 = netaddr.IPv6('fe80::221:63ff:fe75:aa17', 64, 'eth0'); 743 */ 744 static uc_value_t * 745 uc_netaddr_v6(uc_vm_t *vm, size_t nargs) 746 { 747 uc_value_t *addr = uc_fn_arg(0); 748 range_t rng = { }; 749 750 if (!parse_addr(vm, addr, AF_INET6, &rng)) { 751 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, 752 "Invalid IPv6 address"); 753 754 return NULL; 755 } 756 757 if (nargs > 1 && ucv_type(addr) == UC_STRING) { 758 int16_t bits; 759 760 if (!check_bits(vm, uc_fn_arg(1), &rng, &bits)) { 761 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, 762 "Invalid netmask"); 763 764 return NULL; 765 } 766 767 rng.bits = bits; 768 } 769 770 if (nargs > 2 && ucv_type(addr) == UC_STRING) { 771 uint32_t scope = parse_scope(vm, uc_fn_arg(2), &rng, true); 772 773 if (scope != (uint32_t)-1) 774 rng.scope = scope; 775 } 776 777 return new_range(vm, &rng); 778 } 779 780 /** 781 * Construct a new MAC `netaddr.range` instance. 782 * 783 * Raises a runtime exception if the given argument does not represent a 784 * valid ethernet MAC address or if the given optional mask is of a 785 * different family. 786 * 787 * @function module:netaddr#mac 788 * 789 * @param {string|number|number[]|object} address 790 * A valid ethernet MAC address, optionally with prefix size (CIDR 791 * notation) or mask separated by slash, an unsigned number representing 792 * the last 32 bit of the address, an array of exactly `6` bytes, or a 793 * sockaddr-like object with `family` `AF_PACKET`. 794 * 795 * @param {string|number} [netmask] 796 * A valid MAC address mask or a number containing a prefix size between 797 * `0` and `48` bit. Overrides the mask embedded in the first argument if 798 * specified. 799 * 800 * @returns {module:netaddr.range} 801 * 802 * @example 803 * const intel_macs = netaddr.MAC('C0:B6:F9:00:00:00/24'); 804 * const intel_macs = netaddr.MAC('C0:B6:F9:00:00:00/FF:FF:FF:0:0:0'); 805 * const intel_macs = netaddr.MAC('C0:B6:F9:00:00:00', 'FF:FF:FF:0:0:0'); 806 * const intel_macs = netaddr.MAC('C0:B6:F9:00:00:00/24', 48); // override mask 807 */ 808 static uc_value_t * 809 uc_netaddr_mac(uc_vm_t *vm, size_t nargs) 810 { 811 uc_value_t *addr = uc_fn_arg(0); 812 range_t rng = { }; 813 814 if (!parse_addr(vm, addr, AF_PACKET, &rng)) { 815 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, 816 "Invalid MAC address"); 817 818 return NULL; 819 } 820 821 if (nargs > 1 && ucv_type(addr) == UC_STRING) { 822 int16_t bits; 823 824 if (!check_bits(vm, uc_fn_arg(1), &rng, &bits)) { 825 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, 826 "Invalid netmask"); 827 828 return NULL; 829 } 830 831 rng.bits = bits; 832 } 833 834 return new_range(vm, &rng); 835 } 836 837 static uc_value_t * 838 uc_netaddr_check(uc_vm_t *vm, size_t nargs, int family) 839 { 840 uc_value_t *arg = uc_fn_arg(0); 841 range_t rng = { }; 842 843 if (ucv_type(arg) == UC_RESOURCE) { 844 void **p = ucv_resource_dataptr(arg, range_type); 845 846 if (!p || !*(range_t **)p || (*(range_t **)p)->family != family) 847 return NULL; 848 849 return format_range(vm, *(range_t **)p); 850 } 851 852 if (ucv_type(arg) == UC_STRING && 853 parse_range(ucv_string_get(arg), &rng) && 854 rng.family == family) 855 return format_range(vm, &rng); 856 857 return NULL; 858 } 859 860 /** 861 * Verify an IPv4 address. 862 * 863 * Checks whether the given argument is a preexisting `netaddr.range` IPv4 address 864 * instance or a string literal convertible to an IPv4 address and returns a 865 * plain string containing the canonical representation of the address. 866 * 867 * Returns `null` if the argument is not a valid IPv4 address. This function 868 * is intended to aid in safely verifying address literals without having to 869 * deal with exceptions. 870 * 871 * @function module:netaddr#checkv4 872 * 873 * @param {string|module:netaddr.range} address 874 * A valid IPv4 address or existing `netaddr.range` IPv4 instance. 875 * 876 * @returns {?string} 877 * 878 * @example 879 * netaddr.checkv4(netaddr.new('127.0.0.1')); // "127.0.0.1" 880 * netaddr.checkv4('127.0.0.1'); // "127.0.0.1" 881 * netaddr.checkv4('nonsense'); // null 882 * netaddr.checkv4(123); // null 883 * netaddr.checkv4(null); // null 884 */ 885 static uc_value_t * 886 uc_netaddr_checkv4(uc_vm_t *vm, size_t nargs) 887 { 888 return uc_netaddr_check(vm, nargs, AF_INET); 889 } 890 891 /** 892 * Verify an IPv6 address. 893 * 894 * Checks whether the given argument is a preexisting `netaddr.range` IPv6 address 895 * instance or a string literal convertible to an IPv6 address and returns a 896 * plain string containing the canonical representation of the address. 897 * 898 * Returns `null` if the argument is not a valid IPv6 address. This function 899 * is intended to aid in safely verifying address literals without having to 900 * deal with exceptions. 901 * 902 * @function module:netaddr#checkv6 903 * 904 * @param {string|module:netaddr.range} address 905 * A valid IPv6 address or existing `netaddr.range` IPv6 instance. 906 * 907 * @returns {?string} 908 * 909 * @example 910 * netaddr.checkv6(netaddr.new('0:0:0:0:0:0:0:1')); // "::1" 911 * netaddr.checkv6('0:0:0:0:0:0:0:1'); // "::1" 912 * netaddr.checkv6('nonsense'); // null 913 * netaddr.checkv6(123); // null 914 * netaddr.checkv6(null); // null 915 */ 916 static uc_value_t * 917 uc_netaddr_checkv6(uc_vm_t *vm, size_t nargs) 918 { 919 return uc_netaddr_check(vm, nargs, AF_INET6); 920 } 921 922 /** 923 * Verify an ethernet MAC address. 924 * 925 * Checks whether the given argument is a preexisting `netaddr.range` MAC address 926 * instance or a string literal convertible to an ethernet MAC and returns a 927 * plain string containing the canonical representation of the address. 928 * 929 * Returns `null` if the argument is not a valid MAC address. This function 930 * is intended to aid in safely verifying address literals without having to 931 * deal with exceptions. 932 * 933 * @function module:netaddr#checkmac 934 * 935 * @param {string|module:netaddr.range} address 936 * A valid MAC address or existing `netaddr.range` MAC instance. 937 * 938 * @returns {?string} 939 * 940 * @example 941 * netaddr.checkmac(netaddr.new('00-11-22-cc-dd-ee')); // "00:11:22:CC:DD:EE" 942 * netaddr.checkmac('00:11:22:cc:dd:ee'); // "00:11:22:CC:DD:EE" 943 * netaddr.checkmac('nonsense'); // null 944 * netaddr.checkmac(123); // null 945 * netaddr.checkmac(null); // null 946 */ 947 static uc_value_t * 948 uc_netaddr_checkmac(uc_vm_t *vm, size_t nargs) 949 { 950 return uc_netaddr_check(vm, nargs, AF_PACKET); 951 } 952 953 /* 954 * range methods 955 */ 956 957 /** 958 * Represents an IP address or address range as created by `new()`, 959 * `v4()`, `v6()` or `mac()`. 960 * 961 * Instances carry the address, its family (`4` for IPv4, `6` for IPv6 962 * and `1` for MAC addresses) and a prefix size in bits (`32` for IPv4, 963 * `128` for IPv6 and `48` for MAC addresses by default). 964 * 965 * Instances provide a `tostring()` method which is also used by `print()` 966 * and string interpolation to render the address in canonical form, 967 * including the prefix size if it is smaller than the family's full width. 968 * 969 * In addition, instances support property access through `__get__()` and 970 * `__set__()` metamethods: 971 * 972 * - Numeric keys read or write the individual address bytes, e.g. 973 * `addr[0]` reads the first address byte and `addr[0] = 10` rewrites it. 974 * Negative indices count from the end of the address. 975 * - The `bits` property reads or writes the prefix size in bits. 976 * - The `family` property reads the address family (numeric `AF_*` value). 977 * - The `scope` property reads or writes the address scope (the numeric 978 * interface index) for IPv6 and MAC address instances. 979 * - The `scopeid` property reads or writes the address scope given an 980 * interface name or numeric index, silently ignoring non-link-local 981 * IPv6 addresses. 982 * - The `netmask` property reads the netmask as a string, e.g. 983 * `"255.255.255.0"` for a `/24` prefix. 984 * - The `host` property reads the host address as a new range (full-width 985 * prefix). 986 * - The `mapped4` property reads the mapped IPv4 address as a new range, 987 * or `null` if the instance is not an IPv6 mapped IPv4 address. 988 * - The `unscopename` property reads the interface name of the address 989 * scope (or an empty string if no scope is set). 990 * - The `size` property reads the number of addresses in this range, or 991 * `null` if the value does not fit into a 64 bit signed integer. 992 * 993 * @class module:netaddr.range 994 * @hideconstructor 995 * 996 * @property {number} bits 997 * The prefix size in bits (read/write). `32` for IPv4, `128` for IPv6, 998 * `48` for MAC addresses. 999 * 1000 * @property {number} family 1001 * The address family (read-only): `4` for IPv4, `6` for IPv6, 1002 * `1` for MAC addresses. 1003 * 1004 * @property {number} scope 1005 * The address scope as a numeric interface index (read/write). 1006 * Only meaningful for IPv6 and MAC address instances. 1007 * 1008 * @property {?string} scopeid 1009 * The address scope as an interface name (read/write). Accepts an 1010 * interface name or numeric index for assignment. `null` if no scope 1011 * is set. Only meaningful for IPv6 and MAC address instances. 1012 * 1013 * @property {string} netmask 1014 * The netmask as a string, e.g. `"255.255.255.0"` (read-only). 1015 * 1016 * @property {module:netaddr.range} host 1017 * The host address as a new range with a full-width prefix (read-only). 1018 * 1019 * @property {?module:netaddr.range} mapped4 1020 * The mapped IPv4 address as a new range, or `null` if the instance 1021 * is not an IPv6 mapped IPv4 address (read-only). 1022 * 1023 * @property {string} unscopename 1024 * The interface name of the address scope, or an empty string if no 1025 * scope is set (read-only). 1026 * 1027 * @property {?number} size 1028 * The number of addresses in this range, or `null` if the value does 1029 * not fit into a 64 bit signed integer (read-only). 1030 * 1031 * @see {@link module:netaddr#new|new()} 1032 * @see {@link module:netaddr#v4|v4()} 1033 * @see {@link module:netaddr#v6|v6()} 1034 * @see {@link module:netaddr#mac|mac()} 1035 * 1036 * @example 1037 * 1038 * const addr = netaddr.new('192.168.1.1/24'); 1039 * 1040 * addr.is4(); // true 1041 * addr.network(); // "192.168.1.0" 1042 * addr.maxhost(); // "192.168.1.254" 1043 * 1044 * addr.bits; // 24 1045 * addr[0]; // 192 1046 * addr.netmask; // "255.255.255.0" 1047 * addr.host; // netaddr.range "192.168.1.1" 1048 * addr.size; // 256 1049 * 1050 * addr[3] = 10; // "192.168.1.10/24" 1051 * addr.bits = 16; // "192.168.0.0/16" 1052 * 1053 * print(addr); // "192.168.0.0/16" 1054 */ 1055 1056 /** 1057 * Checks whether the CIDR instance is an IPv4 address range. 1058 * 1059 * @function module:netaddr.range#is4 1060 * 1061 * @returns {boolean} `true` if the CIDR is an IPv4 range, else `false` 1062 */ 1063 static uc_value_t * 1064 uc_netaddr_range_is4(uc_vm_t *vm, size_t nargs) 1065 { 1066 range_t *p = get_this_range(vm); 1067 1068 return ucv_boolean_new(p->family == AF_INET); 1069 } 1070 1071 /** 1072 * Checks whether the CIDR instance is within the private RFC1918 address 1073 * space. 1074 * 1075 * @function module:netaddr.range#is4rfc1918 1076 * 1077 * @returns {boolean} `true` if the entire range of this CIDR lies within 1078 * one of the ranges `10.0.0.0-10.255.255.255`, `172.16.0.0-172.31.0.0` or 1079 * `192.168.0.0-192.168.255.255`, else `false` 1080 * 1081 * @example 1082 * const addr = netaddr.new('192.168.45.2/24'); 1083 * addr.is4rfc1918(); // true 1084 */ 1085 static uc_value_t * 1086 uc_netaddr_range_is4rfc1918(uc_vm_t *vm, size_t nargs) 1087 { 1088 range_t *p = get_this_range(vm); 1089 uint32_t a = htonl(p->addr.v4.s_addr); 1090 1091 return ucv_boolean_new((p->family == AF_INET && 1092 ((a >= 0x0A000000 && a <= 0x0AFFFFFF) || 1093 (a >= 0xAC100000 && a <= 0xAC1FFFFF) || 1094 (a >= 0xC0A80000 && a <= 0xC0A8FFFF)))); 1095 } 1096 1097 /** 1098 * Checks whether the CIDR instance is an IPv4 link local (Zeroconf) 1099 * address. 1100 * 1101 * @function module:netaddr.range#is4linklocal 1102 * 1103 * @returns {boolean} `true` if the entire range of this CIDR lies within 1104 * the range `169.254.0.0-169.254.255.255`, else `false` 1105 * 1106 * @example 1107 * const addr = netaddr.new('169.254.34.125'); 1108 * addr.is4linklocal(); // true 1109 */ 1110 static uc_value_t * 1111 uc_netaddr_range_is4linklocal(uc_vm_t *vm, size_t nargs) 1112 { 1113 range_t *p = get_this_range(vm); 1114 uint32_t a = htonl(p->addr.v4.s_addr); 1115 1116 return ucv_boolean_new((p->family == AF_INET && 1117 a >= 0xA9FE0000 && 1118 a <= 0xA9FEFFFF)); 1119 } 1120 1121 /** 1122 * Checks whether the CIDR instance is an IPv6 address range. 1123 * 1124 * @function module:netaddr.range#is6 1125 * 1126 * @returns {boolean} `true` if the CIDR is an IPv6 range, else `false` 1127 */ 1128 static uc_value_t * 1129 uc_netaddr_range_is6(uc_vm_t *vm, size_t nargs) 1130 { 1131 range_t *p = get_this_range(vm); 1132 1133 return ucv_boolean_new(p->family == AF_INET6); 1134 } 1135 1136 /** 1137 * Checks whether the CIDR instance is an IPv6 link local address. 1138 * 1139 * @function module:netaddr.range#is6linklocal 1140 * 1141 * @returns {boolean} `true` if the entire range of this CIDR lies within 1142 * the `fe80::/10` range, else `false` 1143 * 1144 * @example 1145 * const addr = netaddr.new('fe92:53a:3216:af01:221:63ff:fe75:aa17/64'); 1146 * addr.is6linklocal(); // true 1147 */ 1148 static uc_value_t * 1149 uc_netaddr_range_is6linklocal(uc_vm_t *vm, size_t nargs) 1150 { 1151 range_t *p = get_this_range(vm); 1152 1153 return ucv_boolean_new((p->family == AF_INET6 && 1154 p->addr.v6.s6_addr[0] == 0xFE && 1155 p->addr.v6.s6_addr[1] >= 0x80 && 1156 p->addr.v6.s6_addr[1] <= 0xBF)); 1157 } 1158 1159 static bool 1160 is_mapped4(range_t *p) 1161 { 1162 return (p->family == AF_INET6 && 1163 p->addr.v6.s6_addr[0] == 0 && 1164 p->addr.v6.s6_addr[1] == 0 && 1165 p->addr.v6.s6_addr[2] == 0 && 1166 p->addr.v6.s6_addr[3] == 0 && 1167 p->addr.v6.s6_addr[4] == 0 && 1168 p->addr.v6.s6_addr[5] == 0 && 1169 p->addr.v6.s6_addr[6] == 0 && 1170 p->addr.v6.s6_addr[7] == 0 && 1171 p->addr.v6.s6_addr[8] == 0 && 1172 p->addr.v6.s6_addr[9] == 0 && 1173 p->addr.v6.s6_addr[10] == 0xFF && 1174 p->addr.v6.s6_addr[11] == 0xFF); 1175 } 1176 1177 /** 1178 * Checks whether the CIDR instance is an IPv6 mapped IPv4 address. 1179 * 1180 * @function module:netaddr.range#is6mapped4 1181 * 1182 * @returns {boolean} `true` if the address is an IPv6 mapped IPv4 address 1183 * in the form `::ffff:1.2.3.4` 1184 * 1185 * @example 1186 * const addr = netaddr.new('::ffff:192.168.1.1'); 1187 * addr.is6mapped4(); // true 1188 */ 1189 static uc_value_t * 1190 uc_netaddr_range_is6mapped4(uc_vm_t *vm, size_t nargs) 1191 { 1192 range_t *p = get_this_range(vm); 1193 1194 return ucv_boolean_new(is_mapped4(p)); 1195 } 1196 1197 /** 1198 * Checks whether the CIDR instance is an ethernet MAC address range. 1199 * 1200 * @function module:netaddr.range#ismac 1201 * 1202 * @returns {boolean} `true` if the CIDR is a MAC address range, else 1203 * `false` 1204 */ 1205 static uc_value_t * 1206 uc_netaddr_range_ismac(uc_vm_t *vm, size_t nargs) 1207 { 1208 range_t *p = get_this_range(vm); 1209 1210 return ucv_boolean_new(p->family == AF_PACKET); 1211 } 1212 1213 /** 1214 * Checks whether the CIDR instance is a locally administered (LAA) MAC 1215 * address. 1216 * 1217 * @function module:netaddr.range#ismaclocal 1218 * 1219 * @returns {boolean} `true` if the MAC address sets the locally 1220 * administered bit 1221 * 1222 * @example 1223 * const mac = netaddr.new('02:C0:FF:EE:00:01'); 1224 * mac.ismaclocal(); // true 1225 */ 1226 static uc_value_t * 1227 uc_netaddr_range_ismaclocal(uc_vm_t *vm, size_t nargs) 1228 { 1229 range_t *p = get_this_range(vm); 1230 1231 return ucv_boolean_new((p->family == AF_PACKET && 1232 (p->addr.mac[0] & 0x2))); 1233 } 1234 1235 /** 1236 * Checks whether the CIDR instance is a multicast MAC address. 1237 * 1238 * @function module:netaddr.range#ismacmcast 1239 * 1240 * @returns {boolean} `true` if the MAC address sets the multicast bit 1241 * 1242 * @example 1243 * const mac = netaddr.new('01:00:5E:7F:00:10'); 1244 * mac.ismacmcast(); // true 1245 */ 1246 static uc_value_t * 1247 uc_netaddr_range_ismacmcast(uc_vm_t *vm, size_t nargs) 1248 { 1249 range_t *p = get_this_range(vm); 1250 1251 return ucv_boolean_new((p->family == AF_PACKET && 1252 (p->addr.mac[0] & 0x1))); 1253 } 1254 1255 static int 1256 range_cmp(range_t *a, range_t *b) 1257 { 1258 if (a->family != b->family) 1259 return (a->family - b->family); 1260 1261 return memcmp(&a->addr.v6, &b->addr.v6, AF_BYTES(a->family)); 1262 } 1263 1264 /** 1265 * Checks whether this CIDR instance is lower than the given argument. 1266 * 1267 * The comparison follows these rules: 1268 * 1269 * - An IPv4 address is always lower than an IPv6 address and IPv6 1270 * addresses are considered lower than MAC addresses 1271 * - Prefix sizes are ignored 1272 * 1273 * @function module:netaddr.range#lower 1274 * 1275 * @param {string|module:netaddr.range} addr 1276 * An `netaddr.range` instance or a string convertible by `new()` to compare 1277 * against. 1278 * 1279 * @returns {?boolean} `true` if this CIDR is lower than the given 1280 * address, else `false`. Returns `null` if the argument cannot be 1281 * converted to a CIDR instance. 1282 * 1283 * @example 1284 * const addr = netaddr.new('192.168.1.1'); 1285 * addr.lower(addr); // false 1286 * addr.lower('10.10.10.10/24'); // false 1287 * addr.lower(netaddr.new('::1')); // true 1288 * addr.lower(netaddr.new('192.168.200.1')); // true 1289 * addr.lower(netaddr.new('00:14:22:01:23:45')); // true 1290 */ 1291 static uc_value_t * 1292 uc_netaddr_range_lower(uc_vm_t *vm, size_t nargs) 1293 { 1294 range_t *p = get_this_range(vm); 1295 range_t b = { }; 1296 range_t *bptr; 1297 1298 bptr = check_range(vm, uc_fn_arg(0), &b, 0); 1299 1300 if (!bptr) 1301 return NULL; 1302 1303 return ucv_boolean_new(range_cmp(p, bptr) < 0); 1304 } 1305 1306 /** 1307 * Checks whether this CIDR instance is higher than the given argument. 1308 * 1309 * The comparison follows these rules: 1310 * 1311 * - An IPv4 address is always lower than an IPv6 address and IPv6 1312 * addresses are considered lower than MAC addresses 1313 * - Prefix sizes are ignored 1314 * 1315 * @function module:netaddr.range#higher 1316 * 1317 * @param {string|module:netaddr.range} addr 1318 * An `netaddr.range` instance or a string convertible by `new()` to compare 1319 * against. 1320 * 1321 * @returns {?boolean} `true` if this CIDR is higher than the given 1322 * address, else `false`. Returns `null` if the argument cannot be 1323 * converted to a CIDR instance. 1324 * 1325 * @example 1326 * const addr = netaddr.new('192.168.1.1'); 1327 * addr.higher(addr); // false 1328 * addr.higher('10.10.10.10/24'); // true 1329 * addr.higher(netaddr.new('::1')); // false 1330 * addr.higher(netaddr.new('192.168.200.1')); // false 1331 * addr.higher(netaddr.new('00:14:22:01:23:45')); // false 1332 */ 1333 static uc_value_t * 1334 uc_netaddr_range_higher(uc_vm_t *vm, size_t nargs) 1335 { 1336 range_t *p = get_this_range(vm); 1337 range_t b = { }; 1338 range_t *bptr; 1339 1340 bptr = check_range(vm, uc_fn_arg(0), &b, 0); 1341 1342 if (!bptr) 1343 return NULL; 1344 1345 return ucv_boolean_new(range_cmp(p, bptr) > 0); 1346 } 1347 1348 /** 1349 * Checks whether this CIDR instance is equal to the given argument. 1350 * 1351 * @function module:netaddr.range#equal 1352 * 1353 * @param {string|module:netaddr.range} addr 1354 * An `netaddr.range` instance or a string convertible by `new()` to compare 1355 * against. 1356 * 1357 * @returns {?boolean} `true` if this CIDR is equal to the given address, 1358 * else `false`. Returns `null` if the argument cannot be converted to a 1359 * CIDR instance. 1360 * 1361 * @example 1362 * const addr = netaddr.new('192.168.1.1'); 1363 * addr.equal(addr); // true 1364 * addr.equal('192.168.1.1'); // true 1365 * addr.equal(netaddr.new('::1')); // false 1366 * 1367 * const addr6 = netaddr.new('::1'); 1368 * addr6.equal('0:0:0:0:0:0:0:1/64'); // true 1369 * 1370 * const mac = netaddr.new('00:14:22:01:23:45'); 1371 * mac.equal('0:14:22:1:23:45'); // true 1372 */ 1373 static uc_value_t * 1374 uc_netaddr_range_equal(uc_vm_t *vm, size_t nargs) 1375 { 1376 range_t *p = get_this_range(vm); 1377 range_t b = { }; 1378 range_t *bptr; 1379 1380 bptr = check_range(vm, uc_fn_arg(0), &b, 0); 1381 1382 if (!bptr) 1383 return NULL; 1384 1385 return ucv_boolean_new(range_cmp(p, bptr) == 0); 1386 } 1387 1388 /** 1389 * Get or set the prefix size of this CIDR instance. 1390 * 1391 * If the optional mask parameter is given, the prefix size of this CIDR is 1392 * altered, else the current prefix size is returned. 1393 * 1394 * @function module:netaddr.range#prefix 1395 * 1396 * @param {number|string} [mask] 1397 * A number containing the number of bits (`0..32` for IPv4, `0..128` for 1398 * IPv6 or `0..48` for MAC addresses) or a string containing a valid 1399 * netmask. 1400 * 1401 * @returns {number} The bit count of the (new) prefix size 1402 * 1403 * @example 1404 * const range = netaddr.new('192.168.1.1/255.255.255.0'); 1405 * range.prefix(); // 24 1406 * 1407 * range.prefix(16); 1408 * range.prefix(); // 16 1409 * 1410 * range.prefix('255.255.255.255'); 1411 * range.prefix(); // 32 1412 */ 1413 static uc_value_t * 1414 uc_netaddr_range_prefix(uc_vm_t *vm, size_t nargs) 1415 { 1416 range_t *p = get_this_range(vm); 1417 int16_t bits; 1418 1419 if (nargs > 0) { 1420 if (!check_bits(vm, uc_fn_arg(0), p, &bits)) { 1421 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, 1422 "Invalid netmask"); 1423 1424 return NULL; 1425 } 1426 1427 p->bits = bits; 1428 } 1429 1430 return ucv_int64_new(p->bits); 1431 } 1432 1433 static void 1434 apply_mask(range_t *p, int bits, bool inv) 1435 { 1436 uint8_t b, i; 1437 1438 if (bits <= 0) { 1439 memset(&p->addr.u8, inv * 0xFF, AF_BYTES(p->family)); 1440 } 1441 else if (p->family == AF_INET && bits <= AF_BITS(AF_INET)) { 1442 if (inv) 1443 p->addr.v4.s_addr |= ntohl((1 << (AF_BITS(AF_INET) - bits)) - 1); 1444 else 1445 p->addr.v4.s_addr &= ntohl(~((1 << (AF_BITS(AF_INET) - bits)) - 1)); 1446 } 1447 else if (bits <= AF_BITS(p->family)) { 1448 for (i = 0; i < AF_BYTES(p->family); i++) { 1449 b = (bits > 8) ? 8 : bits; 1450 if (inv) 1451 p->addr.u8[i] |= ~((uint8_t)(0xFF << (8 - b))); 1452 else 1453 p->addr.u8[i] &= (uint8_t)(0xFF << (8 - b)); 1454 bits -= b; 1455 } 1456 } 1457 } 1458 1459 /** 1460 * Derive the network address of this CIDR instance. 1461 * 1462 * Returns a new CIDR instance representing the network address of this 1463 * instance with all host parts masked out. The used prefix size can be 1464 * overridden by the optional mask parameter. 1465 * 1466 * @function module:netaddr.range#network 1467 * 1468 * @param {number|string} [mask] 1469 * A number containing the number of bits (`0..32` for IPv4, `0..128` for 1470 * IPv6 or `0..48` for MAC addresses) or a string containing a valid 1471 * netmask. 1472 * 1473 * @returns {module:netaddr.range} A CIDR instance representing the network 1474 * address 1475 * 1476 * @example 1477 * const range = netaddr.new('192.168.62.243/255.255.0.0'); 1478 * range.network(); // "192.168.0.0" 1479 * range.network(24); // "192.168.62.0" 1480 * range.network('255.255.255.0'); // "192.168.62.0" 1481 * 1482 * const range6 = netaddr.new('fd9b:62b3:9cc5:0:221:63ff:fe75:aa17/64'); 1483 * range6.network(); // "fd9b:62b3:9cc5::" 1484 */ 1485 static uc_value_t * 1486 uc_netaddr_range_network(uc_vm_t *vm, size_t nargs) 1487 { 1488 range_t *p1 = get_this_range(vm); 1489 range_t p2 = *p1; 1490 int16_t bits; 1491 1492 if (nargs > 0) { 1493 if (!check_bits(vm, uc_fn_arg(0), p1, &bits)) { 1494 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, 1495 "Invalid netmask"); 1496 1497 return NULL; 1498 } 1499 } 1500 else { 1501 bits = p1->bits; 1502 } 1503 1504 p2.bits = AF_BITS(p1->family); 1505 apply_mask(&p2, bits, false); 1506 1507 return new_range(vm, &p2); 1508 } 1509 1510 /** 1511 * Derive the netmask of this CIDR instance. 1512 * 1513 * Constructs a CIDR instance representing the netmask of this instance. 1514 * The used prefix size can be overridden by the optional mask parameter. 1515 * 1516 * @function module:netaddr.range#mask 1517 * 1518 * @param {number|string} [mask] 1519 * A number containing the number of bits (`0..32` for IPv4, `0..128` for 1520 * IPv6 or `0..48` for MAC addresses) or a string containing a valid 1521 * netmask. 1522 * 1523 * @returns {module:netaddr.range} A CIDR instance representing the netmask 1524 * 1525 * @example 1526 * const range = netaddr.new('172.19.37.45/16'); 1527 * range.mask(); // "255.255.0.0" 1528 * range.mask(24); // "255.255.255.0" 1529 * range.mask('255.0.0.0'); // "255.0.0.0" 1530 */ 1531 static uc_value_t * 1532 uc_netaddr_range_mask(uc_vm_t *vm, size_t nargs) 1533 { 1534 range_t *p1 = get_this_range(vm); 1535 range_t p2 = { }; 1536 int16_t bits; 1537 1538 if (nargs > 0) { 1539 if (!check_bits(vm, uc_fn_arg(0), p1, &bits)) { 1540 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, 1541 "Invalid netmask"); 1542 1543 return NULL; 1544 } 1545 } 1546 else { 1547 bits = p1->bits; 1548 } 1549 1550 p2.scope = 0; 1551 p2.bits = AF_BITS(p1->family); 1552 p2.family = p1->family; 1553 1554 memset(&p2.addr.v6.s6_addr, 0xFF, sizeof(p2.addr.v6.s6_addr)); 1555 apply_mask(&p2, bits, false); 1556 1557 return new_range(vm, &p2); 1558 } 1559 1560 /** 1561 * Derive the broadcast address of this CIDR instance. 1562 * 1563 * Constructs a CIDR instance representing the broadcast address of this 1564 * instance. The used prefix size can be overridden by the optional mask 1565 * parameter. 1566 * 1567 * This function has no effect on IPv6 or MAC address instances, it will 1568 * return `null` in this case. 1569 * 1570 * @function module:netaddr.range#broadcast 1571 * 1572 * @param {number|string} [mask] 1573 * A number containing the number of bits (`0..32` for IPv4) or a string 1574 * containing a valid netmask. 1575 * 1576 * @returns {?module:netaddr.range} A new CIDR instance representing the 1577 * broadcast address if this instance is an IPv4 range, else `null` 1578 * 1579 * @example 1580 * const range = netaddr.new('172.19.37.45/16'); 1581 * range.broadcast(); // "172.19.255.255" 1582 * range.broadcast(24); // "172.19.37.255" 1583 * range.broadcast('255.0.0.0'); // "172.255.255.255" 1584 */ 1585 static uc_value_t * 1586 uc_netaddr_range_broadcast(uc_vm_t *vm, size_t nargs) 1587 { 1588 range_t *p1 = get_this_range(vm); 1589 range_t p2; 1590 int16_t bits; 1591 1592 if (p1->family != AF_INET) 1593 return NULL; 1594 1595 if (nargs > 0) { 1596 if (!check_bits(vm, uc_fn_arg(0), p1, &bits)) { 1597 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, 1598 "Invalid netmask"); 1599 1600 return NULL; 1601 } 1602 } 1603 else { 1604 bits = p1->bits; 1605 } 1606 1607 p2 = *p1; 1608 p2.bits = AF_BITS(AF_INET); 1609 apply_mask(&p2, bits, true); 1610 1611 return new_range(vm, &p2); 1612 } 1613 1614 /** 1615 * Derive the scoped address of this CIDR instance. 1616 * 1617 * Constructs a copy of the given IPv6 or MAC address instance carrying 1618 * the associated address scope, if any. 1619 * 1620 * This function has no effect on IPv4 instances, it will return `null` 1621 * in this case. If no scope is associated with the address, `null` is 1622 * returned. 1623 * 1624 * @function module:netaddr.range#scoped 1625 * 1626 * @returns {?module:netaddr.range} A new CIDR instance representing the 1627 * scoped address 1628 * 1629 * @example 1630 * const addr = netaddr.new('fe80::1234'); 1631 * addr.scope = 2; 1632 * addr.scoped(); // "fe80::1234%eth0" (if index 2 is eth0) 1633 */ 1634 static uc_value_t * 1635 uc_netaddr_range_scoped(uc_vm_t *vm, size_t nargs) 1636 { 1637 range_t *p1 = get_this_range(vm); 1638 range_t p2; 1639 1640 if (p1->family == AF_INET || p1->scope == 0) 1641 return NULL; 1642 1643 p2 = *p1; 1644 1645 return new_range(vm, &p2); 1646 } 1647 /** 1648 * Derive the unscoped IPv6 address of this CIDR instance. 1649 * 1650 * Constructs a copy of the given IPv6 CIDR instance and drops the 1651 * associated address scope information. 1652 * 1653 * This function has no effect on IPv4 instances or MAC address instances, 1654 * it will return `null` in this case. 1655 * 1656 * @function module:netaddr.range#unscoped 1657 * 1658 * @returns {?module:netaddr.range} A new CIDR instance representing the 1659 * unscoped IPv6 address 1660 * 1661 * @example 1662 * const addr = netaddr.new('fe80::1234%eth0'); 1663 * addr.unscoped(); // "fe80::1234" 1664 */ 1665 static uc_value_t * 1666 uc_netaddr_range_unscoped(uc_vm_t *vm, size_t nargs) 1667 { 1668 range_t *p1 = get_this_range(vm); 1669 range_t p2; 1670 1671 if (p1->family != AF_INET6) 1672 return NULL; 1673 1674 p2 = *p1; 1675 p2.scope = 0; 1676 1677 return new_range(vm, &p2); 1678 } 1679 1680 /** 1681 * Derive the MAC address of this IPv6 link local CIDR instance. 1682 * 1683 * Constructs a CIDR instance representing the MAC address contained in the 1684 * IPv6 link local address of this instance. 1685 * 1686 * This function has no effect on IPv4 instances, MAC address instances or 1687 * IPv6 instances which are not a link local address, it will return `null` 1688 * in this case. 1689 * 1690 * @function module:netaddr.range#tomac 1691 * 1692 * @returns {?module:netaddr.range} A new CIDR instance representing the MAC 1693 * address if this instance is an IPv6 link local address, else `null` 1694 * 1695 * @example 1696 * const addr = netaddr.new('fe80::6666:b3ff:fe47:e1b9'); 1697 * addr.tomac(); // "64:66:B3:47:E1:B9" 1698 */ 1699 static uc_value_t * 1700 uc_netaddr_range_tomac(uc_vm_t *vm, size_t nargs) 1701 { 1702 range_t *p1 = get_this_range(vm); 1703 range_t p2 = { }; 1704 1705 if (p1->family != AF_INET6 || 1706 p1->addr.u8[0] != 0xFE || 1707 p1->addr.u8[1] != 0x80 || 1708 p1->addr.u8[2] != 0x00 || 1709 p1->addr.u8[3] != 0x00 || 1710 p1->addr.u8[4] != 0x00 || 1711 p1->addr.u8[5] != 0x00 || 1712 p1->addr.u8[6] != 0x00 || 1713 p1->addr.u8[7] != 0x00 || 1714 p1->addr.u8[11] != 0xFF || 1715 p1->addr.u8[12] != 0xFE) 1716 return NULL; 1717 1718 p2.scope = 0; 1719 p2.family = AF_PACKET; 1720 p2.bits = AF_BITS(AF_PACKET); 1721 p2.addr.u8[0] = p1->addr.u8[8] ^ 0x02; 1722 p2.addr.u8[1] = p1->addr.u8[9]; 1723 p2.addr.u8[2] = p1->addr.u8[10]; 1724 p2.addr.u8[3] = p1->addr.u8[13]; 1725 p2.addr.u8[4] = p1->addr.u8[14]; 1726 p2.addr.u8[5] = p1->addr.u8[15]; 1727 1728 return new_range(vm, &p2); 1729 } 1730 1731 /** 1732 * Derive the IPv6 link local address from this MAC address CIDR instance. 1733 * 1734 * Constructs a CIDR instance representing the IPv6 link local address of 1735 * the MAC address represented by this instance. 1736 * 1737 * This function has no effect on IPv4 instances or IPv6 instances, it will 1738 * return `null` in this case. 1739 * 1740 * @function module:netaddr.range#tolinklocal 1741 * 1742 * @returns {?module:netaddr.range} A new CIDR instance representing the IPv6 1743 * link local address 1744 * 1745 * @example 1746 * const mac = netaddr.new('64:66:B3:47:E1:B9'); 1747 * mac.tolinklocal(); // "fe80::6666:b3ff:fe47:e1b9" 1748 */ 1749 static uc_value_t * 1750 uc_netaddr_range_tolinklocal(uc_vm_t *vm, size_t nargs) 1751 { 1752 range_t *p1 = get_this_range(vm); 1753 range_t p2 = { }; 1754 1755 if (p1->family != AF_PACKET) 1756 return NULL; 1757 1758 p2.scope = p1->scope; 1759 p2.family = AF_INET6; 1760 p2.bits = AF_BITS(AF_INET6); 1761 p2.addr.u8[0] = 0xFE; 1762 p2.addr.u8[1] = 0x80; 1763 p2.addr.u8[2] = 0x00; 1764 p2.addr.u8[3] = 0x00; 1765 p2.addr.u8[4] = 0x00; 1766 p2.addr.u8[5] = 0x00; 1767 p2.addr.u8[6] = 0x00; 1768 p2.addr.u8[7] = 0x00; 1769 p2.addr.u8[8] = p1->addr.u8[0] ^ 0x02; 1770 p2.addr.u8[9] = p1->addr.u8[1]; 1771 p2.addr.u8[10] = p1->addr.u8[2]; 1772 p2.addr.u8[11] = 0xFF; 1773 p2.addr.u8[12] = 0xFE; 1774 p2.addr.u8[13] = p1->addr.u8[3]; 1775 p2.addr.u8[14] = p1->addr.u8[4]; 1776 p2.addr.u8[15] = p1->addr.u8[5]; 1777 1778 return new_range(vm, &p2); 1779 } 1780 1781 /** 1782 * Test whether this CIDR contains the given range. 1783 * 1784 * @function module:netaddr.range#contains 1785 * 1786 * @param {string|module:netaddr.range} addr 1787 * An `netaddr.range` instance or a string convertible by `new()` to test. 1788 * 1789 * @returns {?boolean} `true` if this instance fully contains the given 1790 * address, else `false`. Returns `null` if the argument cannot be 1791 * converted to a CIDR instance. 1792 * 1793 * @example 1794 * const range = netaddr.new('10.24.0.0/255.255.0.0'); 1795 * range.contains('10.24.5.1'); // true 1796 * range.contains('::1'); // false 1797 * range.contains('10.0.0.0/8'); // false 1798 * 1799 * const range6 = netaddr.new('fe80::/10'); 1800 * range6.contains('fe80::221:63f:fe75:aa17/64'); // true 1801 * range6.contains('fd9b:6b3:c5:0:221:63f:fe75:aa17/64'); // false 1802 * 1803 * const intel_macs = netaddr.MAC('C0:B6:F9:00:00:00/24'); 1804 * intel_macs.contains('C0:B6:F9:A3:C:11'); // true 1805 * intel_macs.contains('64:66:B3:47:E1:B9'); // false 1806 */ 1807 static uc_value_t * 1808 uc_netaddr_range_contains(uc_vm_t *vm, size_t nargs) 1809 { 1810 range_t *p1 = get_this_range(vm); 1811 range_t b = { }; 1812 range_t *p2; 1813 range_t a = *p1; 1814 bool rv = false; 1815 1816 p2 = check_range(vm, uc_fn_arg(0), &b, 0); 1817 1818 if (p2 && p1->family == p2->family && p1->bits <= p2->bits) { 1819 apply_mask(&a, p1->bits, false); 1820 apply_mask(p2, p1->bits, false); 1821 1822 rv = !memcmp(&a.addr.v6, &p2->addr.v6, AF_BYTES(a.family)); 1823 } 1824 1825 return ucv_boolean_new(rv); 1826 } 1827 1828 #define BYTE(a, i) \ 1829 (a)->addr.u8[AF_BYTES((a)->family) - (i) - 1] 1830 1831 static uc_value_t * 1832 uc_netaddr_range_add_sub(uc_vm_t *vm, size_t nargs, bool add) 1833 { 1834 range_t *p1 = get_this_range(vm); 1835 uc_value_t *arg = uc_fn_arg(0); 1836 range_t b = { }; 1837 range_t *p2; 1838 range_t r = *p1; 1839 bool inplace = (nargs > 1 && ucv_type(uc_fn_arg(1)) == UC_BOOLEAN && 1840 ucv_boolean_get(uc_fn_arg(1))); 1841 bool ok = true; 1842 uint8_t i, carry; 1843 uint32_t a, b32; 1844 1845 p2 = check_range(vm, arg, &b, p1->family); 1846 1847 if (p2) { 1848 if (p1->family == AF_INET) { 1849 a = ntohl(p1->addr.v4.s_addr); 1850 b32 = ntohl(p2->addr.v4.s_addr); 1851 1852 /* would over/underflow */ 1853 if ((add && (UINT32_MAX - a) < b32) || (!add && a < b32)) { 1854 r.addr.v4.s_addr = add ? htonl(0xFFFFFFFF) : htonl(0); 1855 ok = false; 1856 } 1857 else { 1858 r.addr.v4.s_addr = add ? htonl(a + b32) : htonl(a - b32); 1859 } 1860 } 1861 else { 1862 for (i = 0, carry = 0; i < AF_BYTES(p1->family); i++) { 1863 if (add) { 1864 BYTE(&r, i) = BYTE(p1, i) + BYTE(p2, i) + carry; 1865 carry = (BYTE(p1, i) + BYTE(p2, i) + carry) / 256; 1866 } 1867 else { 1868 BYTE(&r, i) = (uint8_t)(BYTE(p1, i) - BYTE(p2, i) - carry); 1869 carry = (BYTE(p1, i) < (BYTE(p2, i) + carry)); 1870 } 1871 } 1872 1873 /* would over/underflow */ 1874 if (carry) { 1875 memset(&r.addr.u8, add ? 0xFF : 0x00, AF_BYTES(r.family)); 1876 ok = false; 1877 } 1878 } 1879 } 1880 else if (ucv_type(arg) == UC_INTEGER || ucv_type(arg) == UC_DOUBLE) { 1881 uint64_t n = ucv_to_unsigned(arg); 1882 1883 if (errno != 0 || 1884 (AF_BITS(p1->family) < 64 1885 && n > (1ULL << AF_BITS(p1->family)) - 1)) { 1886 memset(&r.addr.u8, add ? 0xFF : 0x00, AF_BYTES(p1->family)); 1887 ok = false; 1888 } 1889 else if (p1->family == AF_INET) { 1890 uint32_t a = ntohl(p1->addr.v4.s_addr); 1891 1892 if ((add && (UINT32_MAX - a) < n) || (!add && a < n)) { 1893 r.addr.v4.s_addr = add ? htonl(0xFFFFFFFF) : htonl(0); 1894 ok = false; 1895 } 1896 else { 1897 r.addr.v4.s_addr = add ? htonl(a + (uint32_t)n) 1898 : htonl(a - (uint32_t)n); 1899 } 1900 } 1901 else { 1902 for (i = 0, carry = 0; i < AF_BYTES(p1->family); i++) { 1903 uint8_t d = (uint8_t)(n & 0xFF); 1904 1905 if (add) { 1906 BYTE(&r, i) = BYTE(p1, i) + d + carry; 1907 carry = (BYTE(p1, i) + d + carry) / 256; 1908 } 1909 else { 1910 BYTE(&r, i) = (uint8_t)(BYTE(p1, i) - d - carry); 1911 carry = (BYTE(p1, i) < (d + carry)); 1912 } 1913 1914 n >>= 8; 1915 } 1916 1917 if (carry) { 1918 memset(&r.addr.u8, add ? 0xFF : 0x00, AF_BYTES(r.family)); 1919 ok = false; 1920 } 1921 } 1922 } 1923 else { 1924 return NULL; 1925 } 1926 1927 if (inplace) { 1928 *p1 = r; 1929 return ucv_boolean_new(ok); 1930 } 1931 1932 return new_range(vm, &r); 1933 } 1934 1935 /** 1936 * Add the given amount to this CIDR instance. If the result would overflow 1937 * the maximum address space, the result is set to the highest possible 1938 * address. 1939 * 1940 * @function module:netaddr.range#add 1941 * 1942 * @param {number|string|module:netaddr.range} amount 1943 * A numeric value, an `netaddr.range` instance or a string convertible by 1944 * `new()`. 1945 * 1946 * @param {boolean} [inplace] 1947 * If `true`, modify this instance instead of returning a new derived CIDR 1948 * instance. 1949 * 1950 * @returns {module:netaddr.range|boolean|null} 1951 * When adding inplace: `true` if the addition succeeded or `false` when 1952 * the addition overflowed. When deriving a new CIDR: a new instance 1953 * representing the value of this instance plus the added amount or the 1954 * highest possible address if the addition overflowed the available 1955 * address space. Returns `null` if the amount argument is not 1956 * convertible. 1957 * 1958 * @example 1959 * const addr = netaddr.new('192.168.1.1/24'); 1960 * addr.add(250); // "192.168.1.251/24" 1961 * addr.add('0.0.99.0'); // "192.168.100.1/24" 1962 * 1963 * addr.add(256, true); // true 1964 * addr; // "192.168.2.1/24" 1965 * 1966 * addr.add('255.0.0.0', true); // false (overflow) 1967 * addr; // "255.255.255.255/24" 1968 * 1969 * const addr6 = netaddr.new('fe80::221:63f:fe75:aa17/64'); 1970 * addr6.add(256); // "fe80::221:63f:fe75:ab17/64" 1971 * 1972 * const mac = netaddr.new('00:14:22:01:23:45'); 1973 * mac.add(256); // "00:14:22:01:24:45" 1974 */ 1975 static uc_value_t * 1976 uc_netaddr_range_add(uc_vm_t *vm, size_t nargs) 1977 { 1978 return uc_netaddr_range_add_sub(vm, nargs, true); 1979 } 1980 1981 /** 1982 * Subtract the given amount from this CIDR instance. If the result would 1983 * underflow the lowest possible address, the result is set to the lowest 1984 * possible address. 1985 * 1986 * @function module:netaddr.range#sub 1987 * 1988 * @param {number|string|module:netaddr.range} amount 1989 * A numeric value, an `netaddr.range` instance or a string convertible by 1990 * `new()`. 1991 * 1992 * @param {boolean} [inplace] 1993 * If `true`, modify this instance instead of returning a new derived CIDR 1994 * instance. 1995 * 1996 * @returns {module:netaddr.range|boolean|null} 1997 * When subtracting inplace: `true` if the subtraction succeeded or 1998 * `false` when the subtraction underflowed. When deriving a new CIDR: a 1999 * new instance representing the value of this instance minus the 2000 * subtracted amount or the lowest address if the subtraction underflowed. 2001 * Returns `null` if the amount argument is not convertible. 2002 * 2003 * @example 2004 * const addr = netaddr.new('192.168.1.1/24'); 2005 * addr.sub(256); // "192.168.0.1/24" 2006 * addr.sub('0.168.0.0'); // "192.0.1.1/24" 2007 * 2008 * addr.sub(256, true); // true 2009 * addr; // "192.168.0.1/24" 2010 * 2011 * addr.sub('255.0.0.0', true); // false (underflow) 2012 * addr; // "0.0.0.0/24" 2013 * 2014 * const addr6 = netaddr.new('fe80::221:63f:fe75:aa17/64'); 2015 * addr6.sub(256); // "fe80::221:63f:fe75:aa17/64" 2016 * 2017 * const mac = netaddr.new('00:14:22:01:23:45'); 2018 * mac.sub(256); // "00:14:22:01:22:45" 2019 */ 2020 static uc_value_t * 2021 uc_netaddr_range_sub(uc_vm_t *vm, size_t nargs) 2022 { 2023 return uc_netaddr_range_add_sub(vm, nargs, false); 2024 } 2025 2026 /** 2027 * Derive the lowest usable host address of this CIDR instance. 2028 * 2029 * For IPv4 ranges this is the network address plus one, except for 2030 * point-to-point `/31` ranges where the network address itself is the 2031 * first usable host; for IPv6 ranges the lowest address in the range 2032 * (the "network" address); for host addresses and MAC addresses the 2033 * address itself. 2034 * 2035 * @function module:netaddr.range#minhost 2036 * 2037 * @returns {module:netaddr.range} A new CIDR instance representing the lowest 2038 * usable host address of this instance 2039 * 2040 * @example 2041 * const range = netaddr.new('172.19.37.45/16'); 2042 * range.minhost(); // "172.19.0.1" 2043 */ 2044 static uc_value_t * 2045 uc_netaddr_range_minhost(uc_vm_t *vm, size_t nargs) 2046 { 2047 range_t *p1 = get_this_range(vm); 2048 range_t r = *p1; 2049 uint8_t i, rest, carry; 2050 2051 apply_mask(&r, r.bits, false); 2052 2053 /* 2054 * skip the network address for IPv4 ranges, except for /31 2055 * point-to-point ranges where the network address itself is the 2056 * first usable host 2057 */ 2058 if (r.family == AF_INET && 2059 r.bits < AF_BITS(AF_INET) && r.bits != 31) { 2060 r.bits = AF_BITS(AF_INET); 2061 r.addr.v4.s_addr = htonl(ntohl(r.addr.v4.s_addr) + 1); 2062 } 2063 else if (r.family == AF_INET && r.bits == 31) { 2064 r.bits = AF_BITS(AF_INET); 2065 } 2066 else if (r.bits < AF_BITS(r.family)) { 2067 r.bits = AF_BITS(r.family); 2068 2069 for (i = 0, carry = 1; i < AF_BYTES(r.family); i++) { 2070 rest = (BYTE(&r, i) + carry) > 255; 2071 BYTE(&r, i) += carry; 2072 carry = rest; 2073 } 2074 } 2075 2076 return new_range(vm, &r); 2077 } 2078 2079 /** 2080 * Derive the highest usable host address of this CIDR instance. 2081 * 2082 * For IPv4 ranges this is the broadcast address minus one, except for 2083 * point-to-point `/31` ranges where the broadcast address itself is the 2084 * last usable host; for IPv6 ranges the highest address in the range 2085 * (the "broadcast" address); for host addresses and MAC addresses the 2086 * address itself. 2087 * 2088 * @function module:netaddr.range#maxhost 2089 * 2090 * @returns {module:netaddr.range} A new CIDR instance representing the highest 2091 * usable host address of this instance 2092 * 2093 * @example 2094 * const range = netaddr.new('172.19.37.45/16'); 2095 * range.maxhost(); // "172.19.255.254" 2096 */ 2097 static uc_value_t * 2098 uc_netaddr_range_maxhost(uc_vm_t *vm, size_t nargs) 2099 { 2100 range_t *p1 = get_this_range(vm); 2101 range_t r = *p1; 2102 2103 apply_mask(&r, r.bits, true); 2104 2105 /* 2106 * skip the broadcast address for IPv4 ranges, except for /31 2107 * point-to-point ranges where the broadcast address itself is the 2108 * last usable host 2109 */ 2110 if (r.family == AF_INET && 2111 r.bits < AF_BITS(AF_INET) && r.bits != 31) { 2112 r.bits = AF_BITS(AF_INET); 2113 r.addr.v4.s_addr = htonl(ntohl(r.addr.v4.s_addr) - 1); 2114 } 2115 else if (r.family == AF_INET && r.bits == 31) { 2116 r.bits = AF_BITS(AF_INET); 2117 } 2118 else { 2119 r.bits = AF_BITS(r.family); 2120 } 2121 2122 return new_range(vm, &r); 2123 } 2124 2125 /** 2126 * Get the string representation of this CIDR instance. 2127 * 2128 * @function module:netaddr.range#string 2129 * 2130 * @returns {string} A string representation of this CIDR 2131 * 2132 * @example 2133 * const addr = netaddr.new('172.19.37.45/16'); 2134 * addr.string(); // "172.19.37.45/16" 2135 */ 2136 static uc_value_t * 2137 uc_netaddr_range_string(uc_vm_t *vm, size_t nargs) 2138 { 2139 range_t *p = get_this_range(vm); 2140 2141 return format_range(vm, p); 2142 } 2143 2144 /** 2145 * Get the string representation of this CIDR instance. 2146 * 2147 * This method is invoked by `print()` and string interpolation to render 2148 * the instance, see {@link module:netaddr.range#string|string()}. 2149 * 2150 * @function module:netaddr.range#tostring 2151 * 2152 * @returns {string} A string representation of this CIDR 2153 * 2154 * @example 2155 * const addr = netaddr.new('172.19.37.45/16'); 2156 * 2157 * print(addr); // "172.19.37.45/16" 2158 * `${addr}`; // "172.19.37.45/16" 2159 */ 2160 static uc_value_t * 2161 uc_netaddr_range_tostring(uc_vm_t *vm, size_t nargs) 2162 { 2163 return uc_netaddr_range_string(vm, nargs); 2164 } 2165 2166 /* 2167 * range property access (__get__ / __set__ metamethods) 2168 */ 2169 2170 static int64_t 2171 key_to_index(uc_value_t *key) 2172 { 2173 const char *k; 2174 int64_t idx; 2175 double d; 2176 char *e; 2177 2178 if (ucv_type(key) == UC_DOUBLE) { 2179 d = ucv_double_get(key); 2180 2181 if (trunc(d) != d) 2182 return INT64_MIN; 2183 2184 return (int64_t)d; 2185 } 2186 else if (ucv_type(key) == UC_INTEGER) { 2187 return ucv_int64_get(key); 2188 } 2189 else if (ucv_type(key) == UC_STRING) { 2190 errno = 0; 2191 k = ucv_string_get(key); 2192 idx = strtoll(k, &e, 0); 2193 2194 if (errno != 0 || e == k || *e != 0) 2195 return INT64_MIN; 2196 2197 return idx; 2198 } 2199 2200 return INT64_MIN; 2201 } 2202 2203 static int64_t 2204 get_range_byte_index(range_t *p, uc_value_t *key) 2205 { 2206 int64_t idx = key_to_index(key); 2207 int64_t len = AF_BYTES(p->family); 2208 2209 if (idx == INT64_MIN) 2210 return INT64_MIN; 2211 2212 if (idx < 0) 2213 idx += len; 2214 2215 if (idx < 0 || idx >= len) 2216 return INT64_MIN; 2217 2218 return idx; 2219 } 2220 2221 /** 2222 * Property access for `netaddr.range` instances. 2223 * 2224 * Invoked by the interpreter for property reads which do not match a 2225 * method of this type, e.g. `addr[0]`, `addr.bits` or `addr.netmask`. 2226 * 2227 * The following keys are supported: 2228 * 2229 * | Key | Description | 2230 * | --- | --- | 2231 * | `0 .. n-1` | The individual address bytes, negative indices count from the end | 2232 * | `bits` | The prefix size in bits | 2233 * | `family` | The address family (`AF_INET`, `AF_INET6` or `AF_PACKET`) | 2234 * | `scope` | The address scope (numeric interface index) for IPv6 and MAC instances | 2235 * | `scopeid` | The address scope as an interface name (or `null` if not set) | 2236 * | `netmask` | The netmask as a string, e.g. `"255.255.255.0"` | 2237 * | `host` | The host address as a new range (full-width prefix) | 2238 * | `mapped4` | The mapped IPv4 address as a new range (or `null` if not a mapped IPv4) | 2239 * | `unscopename` | The interface name of the address scope (or an empty string) | 2240 * | `size` | The number of addresses in this range (or `null` if too large) | 2241 * 2242 * @function module:netaddr.range#__get__ 2243 * 2244 * @param {number|string} key 2245 * The property key to read. 2246 * 2247 * @returns {number|string|null} 2248 * 2249 * @example 2250 * const addr = netaddr.new('192.168.1.1/24'); 2251 * 2252 * addr[0]; // 192 2253 * addr[-1]; // 1 2254 * addr.bits; // 24 2255 * addr.family; // 2 2256 * addr.netmask; // "255.255.255.0" 2257 * addr.host; // netaddr.range "192.168.1.1" (full-width prefix) 2258 * addr.size; // 256 2259 */ 2260 static uc_value_t * 2261 uc_netaddr_range_get(uc_vm_t *vm, size_t nargs) 2262 { 2263 range_t *p = get_this_range(vm); 2264 uc_value_t *key = uc_fn_arg(0); 2265 int64_t idx; 2266 2267 if (ucv_type(key) == UC_INTEGER || ucv_type(key) == UC_DOUBLE) { 2268 idx = get_range_byte_index(p, key); 2269 2270 return (idx == INT64_MIN) ? NULL 2271 : ucv_int64_new(p->addr.u8[idx]); 2272 } 2273 2274 if (ucv_type(key) == UC_STRING) { 2275 const char *k = ucv_string_get(key); 2276 2277 if (!strcmp(k, "bits")) 2278 return ucv_int64_new(p->bits); 2279 2280 if (!strcmp(k, "family")) { 2281 switch (p->family) { 2282 case AF_INET: 2283 return ucv_int64_new(4); 2284 2285 case AF_INET6: 2286 return ucv_int64_new(6); 2287 2288 default: 2289 return ucv_int64_new(1); 2290 } 2291 } 2292 2293 if (!strcmp(k, "scope")) 2294 return ucv_int64_new(p->scope); 2295 2296 if (!strcmp(k, "scopeid")) { 2297 char ifname[IF_NAMESIZE]; 2298 2299 if ((p->family == AF_INET6 || p->family == AF_PACKET) && 2300 p->scope != 0 && 2301 if_indextoname(p->scope, ifname) != NULL) 2302 return ucv_string_new(ifname); 2303 2304 return NULL; 2305 } 2306 2307 if (!strcmp(k, "netmask")) { 2308 range_t m = { }; 2309 2310 m.scope = 0; 2311 m.bits = AF_BITS(p->family); 2312 m.family = p->family; 2313 2314 memset(&m.addr.v6.s6_addr, 0xFF, sizeof(m.addr.v6.s6_addr)); 2315 apply_mask(&m, p->bits, false); 2316 2317 return format_range(vm, &m); 2318 } 2319 2320 if (!strcmp(k, "host")) { 2321 range_t h = *p; 2322 2323 h.bits = AF_BITS(p->family); 2324 2325 return new_range(vm, &h); 2326 } 2327 2328 if (!strcmp(k, "mapped4")) { 2329 if (!is_mapped4(p)) 2330 return NULL; 2331 2332 range_t m = { }; 2333 2334 m.scope = 0; 2335 m.family = AF_INET; 2336 m.bits = (p->bits > AF_BITS(AF_INET)) ? AF_BITS(AF_INET) : p->bits; 2337 memcpy(&m.addr.v4, p->addr.v6.s6_addr + 12, sizeof(m.addr.v4)); 2338 2339 return new_range(vm, &m); 2340 } 2341 2342 if (!strcmp(k, "unscopename")) { 2343 char ifname[IF_NAMESIZE]; 2344 2345 if (p->family == AF_INET || p->scope == 0 || 2346 if_indextoname(p->scope, ifname) == NULL) 2347 return ucv_string_new(""); 2348 2349 return ucv_string_new(ifname); 2350 } 2351 2352 if (!strcmp(k, "size")) { 2353 int rest = AF_BITS(p->family) - p->bits; 2354 2355 /* 2^63 does not fit into a signed 64 bit integer */ 2356 if (rest < 0 || rest >= 63) 2357 return NULL; 2358 2359 return ucv_int64_new(1LL << rest); 2360 } 2361 } 2362 2363 return NULL; 2364 } 2365 2366 /** 2367 * Property assignment for `netaddr.range` instances. 2368 * 2369 * Invoked by the interpreter for property writes, e.g. `addr[0] = 10` or 2370 * `addr.bits = 16`. 2371 * 2372 * The following keys are supported: 2373 * 2374 * - Numeric keys write the individual address bytes (value range `0..255`, 2375 * negative indices count from the end of the address). 2376 * - The `bits` key sets the prefix size in bits (`0..32` for IPv4, 2377 * `0..128` for IPv6, `0..48` for MAC addresses). 2378 * - The `scope` key sets the address scope (numeric interface index) 2379 * for IPv6 and MAC address instances. 2380 * - The `scopeid` key sets the address scope to the given interface 2381 * name or numeric index for IPv6 and MAC address instances. 2382 * - The `host`, `mapped4`, `unscopename` and `size` keys are read-only 2383 * computed properties; writes to them are silently ignored. 2384 * 2385 * Writes to other keys or with invalid values are silently ignored. 2386 * 2387 * @function module:netaddr.range#__set__ 2388 * 2389 * @param {number|string} key 2390 * The property key to write. 2391 * 2392 * @param {number} value 2393 * The value to assign. 2394 * 2395 * @returns {null} Always returns `null`, the return value is discarded by 2396 * the interpreter. 2397 * 2398 * @example 2399 * const addr = netaddr.new('192.168.1.1/24'); 2400 * 2401 * addr[3] = 10; // "192.168.1.10/24" 2402 * addr[-1] = 10; // "192.168.1.10/24" 2403 * addr.bits = 16; // "192.168.1.10/16" 2404 */ 2405 static uc_value_t * 2406 uc_netaddr_range_set(uc_vm_t *vm, size_t nargs) 2407 { 2408 range_t *p = get_this_range(vm); 2409 uc_value_t *key = uc_fn_arg(0); 2410 uc_value_t *val = uc_fn_arg(1); 2411 int64_t idx; 2412 uint64_t n; 2413 2414 if (ucv_type(key) == UC_INTEGER || ucv_type(key) == UC_DOUBLE) { 2415 if (ucv_type(val) != UC_INTEGER && ucv_type(val) != UC_DOUBLE) 2416 return NULL; 2417 2418 idx = get_range_byte_index(p, key); 2419 2420 if (idx == INT64_MIN) 2421 return NULL; 2422 2423 n = ucv_to_unsigned(val); 2424 2425 if (errno == 0 && n <= 0xFF) 2426 p->addr.u8[idx] = (uint8_t)n; 2427 } 2428 else if (ucv_type(key) == UC_STRING) { 2429 const char *k = ucv_string_get(key); 2430 2431 if (!strcmp(k, "bits")) { 2432 int16_t bits; 2433 2434 if (check_bits(vm, val, p, &bits)) 2435 p->bits = bits; 2436 } 2437 else if (!strcmp(k, "scope")) { 2438 if ((p->family == AF_INET6 || p->family == AF_PACKET) && 2439 (ucv_type(val) == UC_INTEGER || ucv_type(val) == UC_DOUBLE)) { 2440 n = ucv_to_unsigned(val); 2441 2442 if (errno == 0 && n <= UINT32_MAX) 2443 p->scope = (uint32_t)n; 2444 } 2445 } 2446 else if (!strcmp(k, "scopeid")) { 2447 if (p->family == AF_INET6 || p->family == AF_PACKET) { 2448 uint32_t idx = parse_scope(vm, val, p, false); 2449 2450 if (idx != (uint32_t)-1) 2451 p->scope = idx; 2452 } 2453 } 2454 /* 2455 * host, mapped4, unscopename and size are read-only computed 2456 * properties, writes to them are silently ignored 2457 */ 2458 } 2459 2460 return NULL; 2461 } 2462 2463 static const uc_function_list_t range_fns[] = { 2464 { "is4", uc_netaddr_range_is4 }, 2465 { "is4rfc1918", uc_netaddr_range_is4rfc1918 }, 2466 { "is4linklocal", uc_netaddr_range_is4linklocal }, 2467 { "is6", uc_netaddr_range_is6 }, 2468 { "is6linklocal", uc_netaddr_range_is6linklocal }, 2469 { "is6mapped4", uc_netaddr_range_is6mapped4 }, 2470 { "ismac", uc_netaddr_range_ismac }, 2471 { "ismaclocal", uc_netaddr_range_ismaclocal }, 2472 { "ismacmcast", uc_netaddr_range_ismacmcast }, 2473 { "lower", uc_netaddr_range_lower }, 2474 { "higher", uc_netaddr_range_higher }, 2475 { "equal", uc_netaddr_range_equal }, 2476 { "prefix", uc_netaddr_range_prefix }, 2477 { "network", uc_netaddr_range_network }, 2478 { "mask", uc_netaddr_range_mask }, 2479 { "broadcast", uc_netaddr_range_broadcast }, 2480 { "scoped", uc_netaddr_range_scoped }, 2481 { "unscoped", uc_netaddr_range_unscoped }, 2482 { "tomac", uc_netaddr_range_tomac }, 2483 { "tolinklocal", uc_netaddr_range_tolinklocal }, 2484 { "contains", uc_netaddr_range_contains }, 2485 { "add", uc_netaddr_range_add }, 2486 { "sub", uc_netaddr_range_sub }, 2487 { "minhost", uc_netaddr_range_minhost }, 2488 { "maxhost", uc_netaddr_range_maxhost }, 2489 { "string", uc_netaddr_range_string }, 2490 { "tostring", uc_netaddr_range_tostring }, 2491 { "__get__", uc_netaddr_range_get }, 2492 { "__set__", uc_netaddr_range_set }, 2493 }; 2494 2495 static const uc_function_list_t ip_fns[] = { 2496 { "new", uc_netaddr_new }, 2497 { "v4", uc_netaddr_v4 }, 2498 { "v6", uc_netaddr_v6 }, 2499 { "mac", uc_netaddr_mac }, 2500 { "checkv4", uc_netaddr_checkv4 }, 2501 { "checkv6", uc_netaddr_checkv6 }, 2502 { "checkmac", uc_netaddr_checkmac }, 2503 }; 2504 2505 void 2506 uc_module_init(uc_vm_t *vm, uc_value_t *scope) 2507 { 2508 uc_type_declare(vm, range_type, range_fns, free); 2509 uc_function_list_register(scope, ip_fns); 2510 } 2511
This page was automatically generated by LXR 0.3.1. • OpenWrt