Remove building with NOCRYPTO option
[minix.git] / external / bsd / dhcp / dist / common / inet.c
blob0986ebe34a7ec52cd3ddd7c693ad7043ccfb477c
1 /* $NetBSD: inet.c,v 1.1.1.2 2014/07/12 11:57:44 spz Exp $ */
2 /* inet.c
4 Subroutines to manipulate internet addresses and ports in a safely portable
5 way... */
7 /*
8 * Copyright (c) 2011,2013,2014 by Internet Systems Consortium, Inc. ("ISC")
9 * Copyright (c) 2007-2009 by Internet Systems Consortium, Inc. ("ISC")
10 * Copyright (c) 2004,2005 by Internet Systems Consortium, Inc. ("ISC")
11 * Copyright (c) 1995-2003 by Internet Software Consortium
13 * Permission to use, copy, modify, and distribute this software for any
14 * purpose with or without fee is hereby granted, provided that the above
15 * copyright notice and this permission notice appear in all copies.
17 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
18 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
20 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
22 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
23 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 * Internet Systems Consortium, Inc.
26 * 950 Charter Street
27 * Redwood City, CA 94063
28 * <info@isc.org>
29 * https://www.isc.org/
33 #include <sys/cdefs.h>
34 __RCSID("$NetBSD: inet.c,v 1.1.1.2 2014/07/12 11:57:44 spz Exp $");
36 #include "dhcpd.h"
38 /* Return just the network number of an internet address... */
40 struct iaddr subnet_number (addr, mask)
41 struct iaddr addr;
42 struct iaddr mask;
44 int i;
45 struct iaddr rv;
47 if (addr.len > sizeof(addr.iabuf))
48 log_fatal("subnet_number():%s:%d: Invalid addr length.", MDL);
49 if (addr.len != mask.len)
50 log_fatal("subnet_number():%s:%d: Addr/mask length mismatch.",
51 MDL);
53 rv.len = 0;
55 /* Both addresses must have the same length... */
56 if (addr.len != mask.len)
57 return rv;
59 rv.len = addr.len;
60 for (i = 0; i < rv.len; i++)
61 rv.iabuf [i] = addr.iabuf [i] & mask.iabuf [i];
62 return rv;
65 /* Combine a network number and a integer to produce an internet address.
66 This won't work for subnets with more than 32 bits of host address, but
67 maybe this isn't a problem. */
69 struct iaddr ip_addr (subnet, mask, host_address)
70 struct iaddr subnet;
71 struct iaddr mask;
72 u_int32_t host_address;
74 int i, j, k;
75 u_int32_t swaddr;
76 struct iaddr rv;
77 unsigned char habuf [sizeof swaddr];
79 if (subnet.len > sizeof(subnet.iabuf))
80 log_fatal("ip_addr():%s:%d: Invalid addr length.", MDL);
81 if (subnet.len != mask.len)
82 log_fatal("ip_addr():%s:%d: Addr/mask length mismatch.",
83 MDL);
85 swaddr = htonl (host_address);
86 memcpy (habuf, &swaddr, sizeof swaddr);
88 /* Combine the subnet address and the host address. If
89 the host address is bigger than can fit in the subnet,
90 return a zero-length iaddr structure. */
91 rv = subnet;
92 j = rv.len - sizeof habuf;
93 for (i = sizeof habuf - 1; i >= 0; i--) {
94 if (mask.iabuf [i + j]) {
95 if (habuf [i] > (mask.iabuf [i + j] ^ 0xFF)) {
96 rv.len = 0;
97 return rv;
99 for (k = i - 1; k >= 0; k--) {
100 if (habuf [k]) {
101 rv.len = 0;
102 return rv;
105 rv.iabuf [i + j] |= habuf [i];
106 break;
107 } else
108 rv.iabuf [i + j] = habuf [i];
111 return rv;
114 /* Given a subnet number and netmask, return the address on that subnet
115 for which the host portion of the address is all ones (the standard
116 broadcast address). */
118 struct iaddr broadcast_addr (subnet, mask)
119 struct iaddr subnet;
120 struct iaddr mask;
122 int i;
123 struct iaddr rv;
125 if (subnet.len > sizeof(subnet.iabuf))
126 log_fatal("broadcast_addr():%s:%d: Invalid addr length.", MDL);
127 if (subnet.len != mask.len)
128 log_fatal("broadcast_addr():%s:%d: Addr/mask length mismatch.",
129 MDL);
131 if (subnet.len != mask.len) {
132 rv.len = 0;
133 return rv;
136 for (i = 0; i < subnet.len; i++) {
137 rv.iabuf [i] = subnet.iabuf [i] | (~mask.iabuf [i] & 255);
139 rv.len = subnet.len;
141 return rv;
144 u_int32_t host_addr (addr, mask)
145 struct iaddr addr;
146 struct iaddr mask;
148 int i;
149 u_int32_t swaddr;
150 struct iaddr rv;
152 if (addr.len > sizeof(addr.iabuf))
153 log_fatal("host_addr():%s:%d: Invalid addr length.", MDL);
154 if (addr.len != mask.len)
155 log_fatal("host_addr():%s:%d: Addr/mask length mismatch.",
156 MDL);
158 rv.len = 0;
160 /* Mask out the network bits... */
161 rv.len = addr.len;
162 for (i = 0; i < rv.len; i++)
163 rv.iabuf [i] = addr.iabuf [i] & ~mask.iabuf [i];
165 /* Copy out up to 32 bits... */
166 memcpy (&swaddr, &rv.iabuf [rv.len - sizeof swaddr], sizeof swaddr);
168 /* Swap it and return it. */
169 return ntohl (swaddr);
172 int addr_eq (addr1, addr2)
173 struct iaddr addr1, addr2;
175 if (addr1.len > sizeof(addr1.iabuf))
176 log_fatal("addr_eq():%s:%d: Invalid addr length.", MDL);
178 if (addr1.len != addr2.len)
179 return 0;
180 return memcmp (addr1.iabuf, addr2.iabuf, addr1.len) == 0;
183 /* addr_match
185 * compares an IP address against a network/mask combination
186 * by ANDing the IP with the mask and seeing whether the result
187 * matches the masked network value.
190 addr_match(addr, match)
191 struct iaddr *addr;
192 struct iaddrmatch *match;
194 int i;
196 if (addr->len != match->addr.len)
197 return 0;
199 for (i = 0 ; i < addr->len ; i++) {
200 if ((addr->iabuf[i] & match->mask.iabuf[i]) !=
201 match->addr.iabuf[i])
202 return 0;
204 return 1;
208 * Compares the addresses a1 and a2.
210 * If a1 < a2, returns -1.
211 * If a1 == a2, returns 0.
212 * If a1 > a2, returns 1.
214 * WARNING: if a1 and a2 differ in length, returns 0.
217 addr_cmp(const struct iaddr *a1, const struct iaddr *a2) {
218 int i;
220 if (a1->len != a2->len) {
221 return 0;
224 for (i=0; i<a1->len; i++) {
225 if (a1->iabuf[i] < a2->iabuf[i]) {
226 return -1;
228 if (a1->iabuf[i] > a2->iabuf[i]) {
229 return 1;
233 return 0;
237 * Performs a bitwise-OR of two addresses.
239 * Returns 1 if the result is non-zero, or 0 otherwise.
241 * WARNING: if a1 and a2 differ in length, returns 0.
243 int
244 addr_or(struct iaddr *result, const struct iaddr *a1, const struct iaddr *a2) {
245 int i;
246 int all_zero;
248 if (a1->len != a2->len) {
249 return 0;
252 all_zero = 1;
254 result->len = a1->len;
255 for (i=0; i<a1->len; i++) {
256 result->iabuf[i] = a1->iabuf[i] | a2->iabuf[i];
257 if (result->iabuf[i] != 0) {
258 all_zero = 0;
262 return !all_zero;
266 * Performs a bitwise-AND of two addresses.
268 * Returns 1 if the result is non-zero, or 0 otherwise.
270 * WARNING: if a1 and a2 differ in length, returns 0.
272 int
273 addr_and(struct iaddr *result, const struct iaddr *a1, const struct iaddr *a2) {
274 int i;
275 int all_zero;
277 if (a1->len != a2->len) {
278 return 0;
281 all_zero = 1;
283 result->len = a1->len;
284 for (i=0; i<a1->len; i++) {
285 result->iabuf[i] = a1->iabuf[i] & a2->iabuf[i];
286 if (result->iabuf[i] != 0) {
287 all_zero = 0;
291 return !all_zero;
295 * Check if a bitmask of the given length is valid for the address.
296 * This is not the case if any bits longer than the bitmask are 1.
298 * So, this is valid:
300 * 127.0.0.0/8
302 * But this is not:
304 * 127.0.0.1/8
306 * Because the final ".1" would get masked out by the /8.
308 isc_boolean_t
309 is_cidr_mask_valid(const struct iaddr *addr, int bits) {
310 int zero_bits;
311 int zero_bytes;
312 int i;
313 char byte;
314 int shift_bits;
317 * Check our bit boundaries.
319 if (bits < 0) {
320 return ISC_FALSE;
322 if (bits > (addr->len * 8)) {
323 return ISC_FALSE;
327 * Figure out how many low-order bits need to be zero.
329 zero_bits = (addr->len * 8) - bits;
330 zero_bytes = zero_bits / 8;
333 * Check to make sure the low-order bytes are zero.
335 for (i=1; i<=zero_bytes; i++) {
336 if (addr->iabuf[addr->len-i] != 0) {
337 return ISC_FALSE;
342 * Look to see if any bits not in right-hand bytes are
343 * non-zero, by making a byte that has these bits set to zero
344 * comparing to the original byte. If these two values are
345 * equal, then the right-hand bits are zero, and we are
346 * happy.
348 shift_bits = zero_bits % 8;
349 if (shift_bits == 0) return ISC_TRUE;
350 byte = addr->iabuf[addr->len-zero_bytes-1];
351 return (((byte >> shift_bits) << shift_bits) == byte);
355 * range2cidr
357 * Converts a range of IP addresses to a set of CIDR networks.
359 * Examples:
360 * 192.168.0.0 - 192.168.0.255 = 192.168.0.0/24
361 * 10.0.0.0 - 10.0.1.127 = 10.0.0.0/24, 10.0.1.0/25
362 * 255.255.255.32 - 255.255.255.255 = 255.255.255.32/27, 255.255.255.64/26,
363 * 255.255.255.128/25
365 isc_result_t
366 range2cidr(struct iaddrcidrnetlist **result,
367 const struct iaddr *lo, const struct iaddr *hi) {
368 struct iaddr addr;
369 struct iaddr mask;
370 int bit;
371 struct iaddr end_addr;
372 struct iaddr dummy;
373 int ofs, val;
374 struct iaddrcidrnetlist *net;
375 int tmp;
377 if (result == NULL) {
378 return DHCP_R_INVALIDARG;
380 if (*result != NULL) {
381 return DHCP_R_INVALIDARG;
383 if ((lo == NULL) || (hi == NULL) || (lo->len != hi->len)) {
384 return DHCP_R_INVALIDARG;
388 * Put our start and end in the right order, if reversed.
390 if (addr_cmp(lo, hi) > 0) {
391 const struct iaddr *tmp;
392 tmp = lo;
393 lo = hi;
394 hi = tmp;
398 * Theory of operation:
400 * -------------------
401 * Start at the low end, and keep trying larger networks
402 * until we get one that is too big (explained below).
404 * We keep a "mask", which is the ones-complement of a
405 * normal netmask. So, a /23 has a netmask of 255.255.254.0,
406 * and a mask of 0.0.1.255.
408 * We know when a network is too big when we bitwise-AND the
409 * mask with the starting address and we get a non-zero
410 * result, like this:
412 * addr: 192.168.1.0, mask: 0.0.1.255
413 * bitwise-AND: 0.0.1.0
415 * A network is also too big if the bitwise-OR of the mask
416 * with the starting address is larger than the end address,
417 * like this:
419 * start: 192.168.1.0, mask: 0.0.1.255, end: 192.168.0.255
420 * bitwise-OR: 192.168.1.255
422 * -------------------
423 * Once we have found a network that is too big, we add the
424 * appropriate CIDR network to our list of found networks.
426 * We then use the next IP address as our low address, and
427 * begin the process of searching for a network that is
428 * too big again, starting with an empty mask.
430 addr = *lo;
431 bit = 0;
432 memset(&mask, 0, sizeof(mask));
433 mask.len = addr.len;
434 while (addr_cmp(&addr, hi) <= 0) {
436 * Bitwise-OR mask with (1 << bit)
438 ofs = addr.len - (bit / 8) - 1;
439 val = 1 << (bit % 8);
440 if (ofs >= 0) {
441 mask.iabuf[ofs] |= val;
445 * See if we're too big, and save this network if so.
447 addr_or(&end_addr, &addr, &mask);
448 if ((ofs < 0) ||
449 (addr_cmp(&end_addr, hi) > 0) ||
450 addr_and(&dummy, &addr, &mask)) {
452 * Add a new prefix to our list.
454 net = dmalloc(sizeof(*net), MDL);
455 if (net == NULL) {
456 while (*result != NULL) {
457 net = (*result)->next;
458 dfree(*result, MDL);
459 *result = net;
461 return ISC_R_NOMEMORY;
463 net->cidrnet.lo_addr = addr;
464 net->cidrnet.bits = (addr.len * 8) - bit;
465 net->next = *result;
466 *result = net;
469 * Figure out our new starting address,
470 * by adding (1 << bit) to our previous
471 * starting address.
473 tmp = addr.iabuf[ofs] + val;
474 while ((ofs >= 0) && (tmp > 255)) {
475 addr.iabuf[ofs] = tmp - 256;
476 ofs--;
477 tmp = addr.iabuf[ofs] + 1;
479 if (ofs < 0) {
480 /* Gone past last address, we're done. */
481 break;
483 addr.iabuf[ofs] = tmp;
486 * Reset our bit and mask.
488 bit = 0;
489 memset(mask.iabuf, 0, sizeof(mask.iabuf));
490 memset(end_addr.iabuf, 0, sizeof(end_addr.iabuf));
491 } else {
493 * If we're not too big, increase our network size.
495 bit++;
500 * We're done.
502 return ISC_R_SUCCESS;
506 * Free a list of CIDR networks, such as returned from range2cidr().
508 isc_result_t
509 free_iaddrcidrnetlist(struct iaddrcidrnetlist **result) {
510 struct iaddrcidrnetlist *p;
512 if (result == NULL) {
513 return DHCP_R_INVALIDARG;
515 if (*result == NULL) {
516 return DHCP_R_INVALIDARG;
519 while (*result != NULL) {
520 p = *result;
521 *result = p->next;
522 dfree(p, MDL);
525 return ISC_R_SUCCESS;
528 /* piaddr() turns an iaddr structure into a printable address. */
529 /* XXX: should use a const pointer rather than passing the structure */
530 const char *
531 piaddr(const struct iaddr addr) {
532 static char
533 pbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
534 /* "255.255.255.255" */
536 /* INSIST((addr.len == 0) || (addr.len == 4) || (addr.len == 16)); */
538 if (addr.len == 0) {
539 return "<null address>";
541 if (addr.len == 4) {
542 return inet_ntop(AF_INET, addr.iabuf, pbuf, sizeof(pbuf));
544 if (addr.len == 16) {
545 return inet_ntop(AF_INET6, addr.iabuf, pbuf, sizeof(pbuf));
548 log_fatal("piaddr():%s:%d: Invalid address length %d.", MDL,
549 addr.len);
550 /* quell compiler warnings */
551 return NULL;
554 /* piaddrmask takes an iaddr structure mask, determines the bitlength of
555 * the mask, and then returns the printable CIDR notation of the two.
557 char *
558 piaddrmask(struct iaddr *addr, struct iaddr *mask) {
559 int mw;
560 unsigned int oct, bit;
562 if ((addr->len != 4) && (addr->len != 16))
563 log_fatal("piaddrmask():%s:%d: Address length %d invalid",
564 MDL, addr->len);
565 if (addr->len != mask->len)
566 log_fatal("piaddrmask():%s:%d: Address and mask size mismatch",
567 MDL);
569 /* Determine netmask width in bits. */
570 for (mw = (mask->len * 8) ; mw > 0 ; ) {
571 oct = (mw - 1) / 8;
572 bit = 0x80 >> ((mw - 1) % 8);
573 if (!mask->iabuf[oct])
574 mw -= 8;
575 else if (mask->iabuf[oct] & bit)
576 break;
577 else
578 mw--;
581 if (mw < 0)
582 log_fatal("Impossible condition at %s:%d.", MDL);
584 return piaddrcidr(addr, mw);
587 /* Format an address and mask-length into printable CIDR notation. */
588 char *
589 piaddrcidr(const struct iaddr *addr, unsigned int bits) {
590 static char
591 ret[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128")];
592 /* "255.255.255.255/32" */
594 /* INSIST(addr != NULL); */
595 /* INSIST((addr->len == 4) || (addr->len == 16)); */
596 /* INSIST(bits <= (addr->len * 8)); */
598 if (bits > (addr->len * 8))
599 return NULL;
601 sprintf(ret, "%s/%d", piaddr(*addr), bits);
603 return ret;
606 /* Validate that the string represents a valid port number and
607 * return it in network byte order
610 u_int16_t
611 validate_port(char *port) {
612 long local_port = 0;
613 long lower = 1;
614 long upper = 65535;
615 char *endptr;
617 errno = 0;
618 local_port = strtol(port, &endptr, 10);
620 if ((*endptr != '\0') || (errno == ERANGE) || (errno == EINVAL))
621 log_fatal ("Invalid port number specification: %s", port);
623 if (local_port < lower || local_port > upper)
624 log_fatal("Port number specified is out of range (%ld-%ld).",
625 lower, upper);
627 return htons((u_int16_t)local_port);