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
subnet_number(addr,mask)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
ip_addr(subnet,mask,host_address)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
broadcast_addr(subnet,mask)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
host_addr(addr,mask)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
addr_eq(addr1,addr2)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
addr_match(addr,match)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
addr_cmp(const struct iaddr * a1,const struct iaddr * a2)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
addr_or(struct iaddr * result,const struct iaddr * a1,const struct iaddr * a2)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
addr_and(struct iaddr * result,const struct iaddr * a1,const struct iaddr * a2)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
is_cidr_mask_valid(const struct iaddr * addr,int bits)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
range2cidr(struct iaddrcidrnetlist ** result,const struct iaddr * lo,const struct iaddr * hi)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
free_iaddrcidrnetlist(struct iaddrcidrnetlist ** result)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 *
piaddr(const struct iaddr addr)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 *
piaddrmask(struct iaddr * addr,struct iaddr * mask)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 *
piaddrcidr(const struct iaddr * addr,unsigned int bits)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
validate_port(char * port)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