Changes since 4.0.0a1
+- Invalid CIDR representation for IPv6 subnets or ranges now checked
+ for when loading configuration.
+
- Compilation on HP/UX has been repaired. The changes should generally
apply to any architecture that supplies SIOCGLIFCONF but does not
use 'struct lifconf' structures to pass values.
#ifndef lint
static char copyright[] =
-"$Id: inet.c,v 1.13 2007/05/19 19:16:24 dhankins Exp $ Copyright (c) 2004,2005,2007 Internet Systems Consortium. All rights reserved.\n";
+"$Id: inet.c,v 1.14 2007/06/19 17:06:03 shane Exp $ Copyright (c) 2004,2005,2007 Internet Systems Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
return !all_zero;
}
+/*
+ * Check if a bitmask of the given length is valid for the address.
+ * This is not the case if any bits longer than the bitmask are 1.
+ *
+ * So, this is valid:
+ *
+ * 127.0.0.0/8
+ *
+ * But this is not:
+ *
+ * 127.0.0.1/8
+ *
+ * Because the final ".1" would get masked out by the /8.
+ */
+isc_boolean_t
+is_cidr_mask_valid(const struct iaddr *addr, int bits) {
+ int zero_bits;
+ int zero_bytes;
+ int i;
+ char byte;
+ int shift_bits;
+
+ /*
+ * Check our bit boundaries.
+ */
+ if (bits < 0) {
+ return ISC_FALSE;
+ }
+ if (bits > (addr->len * 8)) {
+ return ISC_FALSE;
+ }
+
+ /*
+ * Figure out how many low-order bits need to be zero.
+ */
+ zero_bits = (addr->len * 8) - bits;
+ zero_bytes = zero_bits / 8;
+
+ /*
+ * Check to make sure the low-order bytes are zero.
+ */
+ for (i=1; i<=zero_bytes; i++) {
+ if (addr->iabuf[addr->len-i] != 0) {
+ return ISC_FALSE;
+ }
+ }
+
+ /*
+ * Look to see if any bits not in right-hand bytes are
+ * non-zero, by making a byte that has these bits set to zero
+ * comparing to the original byte. If these two values are
+ * equal, then the right-hand bits are zero, and we are
+ * happy.
+ */
+ shift_bits = zero_bits % 8;
+ if (shift_bits == 0) return ISC_TRUE;
+ byte = addr->iabuf[addr->len-zero_bytes-1];
+ return (((byte >> shift_bits) << shift_bits) == byte);
+}
+
/*
* range2cidr
*
const struct iaddr *a1, const struct iaddr *a2);
int addr_and(struct iaddr *result,
const struct iaddr *a1, const struct iaddr *a2);
+isc_boolean_t is_cidr_mask_valid(const struct iaddr *addr, int bits);
isc_result_t range2cidr(struct iaddrcidrnetlist **result,
const struct iaddr *lo, const struct iaddr *hi);
isc_result_t free_iaddrcidrnetlist(struct iaddrcidrnetlist **result);
#ifndef lint
static char copyright[] =
-"$Id: confpars.c,v 1.167 2007/06/08 14:58:20 dhankins Exp $ Copyright (c) 2004-2007 Internet Systems Consortium. All rights reserved.\n";
+"$Id: confpars.c,v 1.168 2007/06/19 17:06:03 shane Exp $ Copyright (c) 2004-2007 Internet Systems Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
return;
}
+ if (!is_cidr_mask_valid(&subnet->net, subnet->prefix_len)) {
+ parse_warn(cfile, "New subnet mask too short.");
+ skip_to_semi(cfile);
+ return;
+ }
+
/*
* Create a netmask.
*/
skip_to_semi(cfile);
return;
}
+ if (!is_cidr_mask_valid(&lo, bits)) {
+ parse_warn(cfile, "network mask too short");
+ skip_to_semi(cfile);
+ return;
+ }
add_ipv6_pool_to_shared_network(share, &lo, bits);