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