2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-08-22 01:49:35 +00:00

Check for valid prefixes in configuration.

See RT ticket #16944 for more information.
This commit is contained in:
Shane Kerr 2007-06-19 17:06:03 +00:00
parent e847f9833c
commit 9b21e73e3c
4 changed files with 77 additions and 2 deletions

View File

@ -54,6 +54,9 @@ suggested fixes to <dhcp-users@isc.org>.
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.

View File

@ -35,7 +35,7 @@
#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"
@ -297,6 +297,66 @@ addr_and(struct iaddr *result, const struct iaddr *a1, const struct iaddr *a2) {
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
*

View File

@ -2321,6 +2321,7 @@ int addr_or(struct iaddr *result,
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);

View File

@ -34,7 +34,7 @@
#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"
@ -2640,6 +2640,12 @@ parse_subnet6_declaration(struct parse *cfile, struct shared_network *share) {
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.
*/
@ -3703,6 +3709,11 @@ parse_address_range6(struct parse *cfile, struct group *group) {
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);