• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/ucode/lib/netaddr.c

  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