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