xref: /minix/external/bsd/dhcp/dist/common/inet.c (revision bb9622b5)
1 /*	$NetBSD: inet.c,v 1.1.1.2 2014/07/12 11:57:44 spz Exp $	*/
2 /* inet.c
3 
4    Subroutines to manipulate internet addresses and ports in a safely portable
5    way... */
6 
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
12  *
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.
16  *
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.
24  *
25  *   Internet Systems Consortium, Inc.
26  *   950 Charter Street
27  *   Redwood City, CA 94063
28  *   <info@isc.org>
29  *   https://www.isc.org/
30  *
31  */
32 
33 #include <sys/cdefs.h>
34 __RCSID("$NetBSD: inet.c,v 1.1.1.2 2014/07/12 11:57:44 spz Exp $");
35 
36 #include "dhcpd.h"
37 
38 /* Return just the network number of an internet address... */
39 
40 struct iaddr subnet_number (addr, mask)
41 	struct iaddr addr;
42 	struct iaddr mask;
43 {
44 	int i;
45 	struct iaddr rv;
46 
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);
52 
53 	rv.len = 0;
54 
55 	/* Both addresses must have the same length... */
56 	if (addr.len != mask.len)
57 		return rv;
58 
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;
63 }
64 
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. */
68 
69 struct iaddr ip_addr (subnet, mask, host_address)
70 	struct iaddr subnet;
71 	struct iaddr mask;
72 	u_int32_t host_address;
73 {
74 	int i, j, k;
75 	u_int32_t swaddr;
76 	struct iaddr rv;
77 	unsigned char habuf [sizeof swaddr];
78 
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);
84 
85 	swaddr = htonl (host_address);
86 	memcpy (habuf, &swaddr, sizeof swaddr);
87 
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;
98 			}
99 			for (k = i - 1; k >= 0; k--) {
100 				if (habuf [k]) {
101 					rv.len = 0;
102 					return rv;
103 				}
104 			}
105 			rv.iabuf [i + j] |= habuf [i];
106 			break;
107 		} else
108 			rv.iabuf [i + j] = habuf [i];
109 	}
110 
111 	return rv;
112 }
113 
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). */
117 
118 struct iaddr broadcast_addr (subnet, mask)
119 	struct iaddr subnet;
120 	struct iaddr mask;
121 {
122 	int i;
123 	struct iaddr rv;
124 
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);
130 
131 	if (subnet.len != mask.len) {
132 		rv.len = 0;
133 		return rv;
134 	}
135 
136 	for (i = 0; i < subnet.len; i++) {
137 		rv.iabuf [i] = subnet.iabuf [i] | (~mask.iabuf [i] & 255);
138 	}
139 	rv.len = subnet.len;
140 
141 	return rv;
142 }
143 
144 u_int32_t host_addr (addr, mask)
145 	struct iaddr addr;
146 	struct iaddr mask;
147 {
148 	int i;
149 	u_int32_t swaddr;
150 	struct iaddr rv;
151 
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);
157 
158 	rv.len = 0;
159 
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];
164 
165 	/* Copy out up to 32 bits... */
166 	memcpy (&swaddr, &rv.iabuf [rv.len - sizeof swaddr], sizeof swaddr);
167 
168 	/* Swap it and return it. */
169 	return ntohl (swaddr);
170 }
171 
172 int addr_eq (addr1, addr2)
173 	struct iaddr addr1, addr2;
174 {
175 	if (addr1.len > sizeof(addr1.iabuf))
176 		log_fatal("addr_eq():%s:%d: Invalid addr length.", MDL);
177 
178 	if (addr1.len != addr2.len)
179 		return 0;
180 	return memcmp (addr1.iabuf, addr2.iabuf, addr1.len) == 0;
181 }
182 
183 /* addr_match
184  *
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.
188  */
189 int
190 addr_match(addr, match)
191 	struct iaddr *addr;
192 	struct iaddrmatch *match;
193 {
194         int i;
195 
196 	if (addr->len != match->addr.len)
197 		return 0;
198 
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;
203 	}
204 	return 1;
205 }
206 
207 /*
208  * Compares the addresses a1 and a2.
209  *
210  * If a1 < a2, returns -1.
211  * If a1 == a2, returns 0.
212  * If a1 > a2, returns 1.
213  *
214  * WARNING: if a1 and a2 differ in length, returns 0.
215  */
216 int
217 addr_cmp(const struct iaddr *a1, const struct iaddr *a2) {
218 	int i;
219 
220 	if (a1->len != a2->len) {
221 		return 0;
222 	}
223 
224 	for (i=0; i<a1->len; i++) {
225 		if (a1->iabuf[i] < a2->iabuf[i]) {
226 			return -1;
227 		}
228 		if (a1->iabuf[i] > a2->iabuf[i]) {
229 			return 1;
230 		}
231 	}
232 
233 	return 0;
234 }
235 
236 /*
237  * Performs a bitwise-OR of two addresses.
238  *
239  * Returns 1 if the result is non-zero, or 0 otherwise.
240  *
241  * WARNING: if a1 and a2 differ in length, returns 0.
242  */
243 int
244 addr_or(struct iaddr *result, const struct iaddr *a1, const struct iaddr *a2) {
245 	int i;
246 	int all_zero;
247 
248 	if (a1->len != a2->len) {
249 		return 0;
250 	}
251 
252 	all_zero = 1;
253 
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;
259 		}
260 	}
261 
262 	return !all_zero;
263 }
264 
265 /*
266  * Performs a bitwise-AND of two addresses.
267  *
268  * Returns 1 if the result is non-zero, or 0 otherwise.
269  *
270  * WARNING: if a1 and a2 differ in length, returns 0.
271  */
272 int
273 addr_and(struct iaddr *result, const struct iaddr *a1, const struct iaddr *a2) {
274 	int i;
275 	int all_zero;
276 
277 	if (a1->len != a2->len) {
278 		return 0;
279 	}
280 
281 	all_zero = 1;
282 
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;
288 		}
289 	}
290 
291 	return !all_zero;
292 }
293 
294 /*
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.
297  *
298  * So, this is valid:
299  *
300  * 127.0.0.0/8
301  *
302  * But this is not:
303  *
304  * 127.0.0.1/8
305  *
306  * Because the final ".1" would get masked out by the /8.
307  */
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;
315 
316 	/*
317 	 * Check our bit boundaries.
318 	 */
319 	if (bits < 0) {
320 		return ISC_FALSE;
321 	}
322 	if (bits > (addr->len * 8)) {
323 		return ISC_FALSE;
324 	}
325 
326 	/*
327 	 * Figure out how many low-order bits need to be zero.
328 	 */
329 	zero_bits = (addr->len * 8) - bits;
330 	zero_bytes = zero_bits / 8;
331 
332 	/*
333 	 * Check to make sure the low-order bytes are zero.
334 	 */
335 	for (i=1; i<=zero_bytes; i++) {
336 		if (addr->iabuf[addr->len-i] != 0) {
337 			return ISC_FALSE;
338 		}
339 	}
340 
341 	/*
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.
347 	 */
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);
352 }
353 
354 /*
355  * range2cidr
356  *
357  * Converts a range of IP addresses to a set of CIDR networks.
358  *
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
364  */
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;
376 
377 	if (result == NULL) {
378 		return DHCP_R_INVALIDARG;
379 	}
380 	if (*result != NULL) {
381 		return DHCP_R_INVALIDARG;
382 	}
383 	if ((lo == NULL) || (hi == NULL) || (lo->len != hi->len)) {
384 		return DHCP_R_INVALIDARG;
385 	}
386 
387 	/*
388 	 * Put our start and end in the right order, if reversed.
389 	 */
390 	if (addr_cmp(lo, hi) > 0) {
391 		const struct iaddr *tmp;
392 		tmp = lo;
393 		lo = hi;
394 		hi = tmp;
395 	}
396 
397 	/*
398 	 * Theory of operation:
399 	 *
400 	 * -------------------
401 	 * Start at the low end, and keep trying larger networks
402 	 * until we get one that is too big (explained below).
403 	 *
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.
407 	 *
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:
411 	 *
412 	 *    addr: 192.168.1.0, mask: 0.0.1.255
413 	 *    bitwise-AND: 0.0.1.0
414 	 *
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:
418 	 *
419 	 *    start: 192.168.1.0, mask: 0.0.1.255, end: 192.168.0.255
420 	 *    bitwise-OR: 192.168.1.255
421 	 *
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.
425 	 *
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.
429 	 */
430 	addr = *lo;
431 	bit = 0;
432 	memset(&mask, 0, sizeof(mask));
433 	mask.len = addr.len;
434 	while (addr_cmp(&addr, hi) <= 0) {
435 		/*
436 		 * Bitwise-OR mask with (1 << bit)
437 		 */
438 		ofs = addr.len - (bit / 8) - 1;
439 		val = 1 << (bit % 8);
440 		if (ofs >= 0) {
441 			mask.iabuf[ofs] |= val;
442 		}
443 
444 		/*
445 		 * See if we're too big, and save this network if so.
446 		 */
447 		addr_or(&end_addr, &addr, &mask);
448 		if ((ofs < 0) ||
449 		    (addr_cmp(&end_addr, hi) > 0) ||
450 		    addr_and(&dummy, &addr, &mask)) {
451 		    	/*
452 			 * Add a new prefix to our list.
453 			 */
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;
460 				}
461 				return ISC_R_NOMEMORY;
462 			}
463 			net->cidrnet.lo_addr = addr;
464 			net->cidrnet.bits = (addr.len * 8) - bit;
465 			net->next = *result;
466 			*result = net;
467 
468 		    	/*
469 			 * Figure out our new starting address,
470 			 * by adding (1 << bit) to our previous
471 			 * starting address.
472 			 */
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;
478 			}
479 			if (ofs < 0) {
480 				/* Gone past last address, we're done. */
481 				break;
482 			}
483 			addr.iabuf[ofs] = tmp;
484 
485 			/*
486 			 * Reset our bit and mask.
487 			 */
488 		    	bit = 0;
489 			memset(mask.iabuf, 0, sizeof(mask.iabuf));
490 			memset(end_addr.iabuf, 0, sizeof(end_addr.iabuf));
491 		} else {
492 			/*
493 			 * If we're not too big, increase our network size.
494 			 */
495 			bit++;
496 		}
497 	}
498 
499 	/*
500 	 * We're done.
501 	 */
502 	return ISC_R_SUCCESS;
503 }
504 
505 /*
506  * Free a list of CIDR networks, such as returned from range2cidr().
507  */
508 isc_result_t
509 free_iaddrcidrnetlist(struct iaddrcidrnetlist **result) {
510 	struct iaddrcidrnetlist *p;
511 
512 	if (result == NULL) {
513 		return DHCP_R_INVALIDARG;
514 	}
515 	if (*result == NULL) {
516 		return DHCP_R_INVALIDARG;
517 	}
518 
519 	while (*result != NULL) {
520 		p = *result;
521 		*result = p->next;
522 		dfree(p, MDL);
523 	}
524 
525 	return ISC_R_SUCCESS;
526 }
527 
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" */
535 
536 	/* INSIST((addr.len == 0) || (addr.len == 4) || (addr.len == 16)); */
537 
538 	if (addr.len == 0) {
539 		return "<null address>";
540 	}
541 	if (addr.len == 4) {
542 		return inet_ntop(AF_INET, addr.iabuf, pbuf, sizeof(pbuf));
543 	}
544 	if (addr.len == 16) {
545 		return inet_ntop(AF_INET6, addr.iabuf, pbuf, sizeof(pbuf));
546 	}
547 
548 	log_fatal("piaddr():%s:%d: Invalid address length %d.", MDL,
549 		  addr.len);
550 	/* quell compiler warnings */
551 	return NULL;
552 }
553 
554 /* piaddrmask takes an iaddr structure mask, determines the bitlength of
555  * the mask, and then returns the printable CIDR notation of the two.
556  */
557 char *
558 piaddrmask(struct iaddr *addr, struct iaddr *mask) {
559 	int mw;
560 	unsigned int oct, bit;
561 
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);
568 
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--;
579 	}
580 
581 	if (mw < 0)
582 		log_fatal("Impossible condition at %s:%d.", MDL);
583 
584 	return piaddrcidr(addr, mw);
585 }
586 
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" */
593 
594 	/* INSIST(addr != NULL); */
595 	/* INSIST((addr->len == 4) || (addr->len == 16)); */
596 	/* INSIST(bits <= (addr->len * 8)); */
597 
598 	if (bits > (addr->len * 8))
599 		return NULL;
600 
601 	sprintf(ret, "%s/%d", piaddr(*addr), bits);
602 
603 	return ret;
604 }
605 
606 /* Validate that the string represents a valid port number and
607  * return it in network byte order
608  */
609 
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;
616 
617 	errno = 0;
618 	local_port = strtol(port, &endptr, 10);
619 
620 	if ((*endptr != '\0') || (errno == ERANGE) || (errno == EINVAL))
621 		log_fatal ("Invalid port number specification: %s", port);
622 
623 	if (local_port < lower || local_port > upper)
624 		log_fatal("Port number specified is out of range (%ld-%ld).",
625 			  lower, upper);
626 
627 	return htons((u_int16_t)local_port);
628 }
629