2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-08-29 13:28:14 +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 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 - Compilation on HP/UX has been repaired. The changes should generally
apply to any architecture that supplies SIOCGLIFCONF but does not apply to any architecture that supplies SIOCGLIFCONF but does not
use 'struct lifconf' structures to pass values. use 'struct lifconf' structures to pass values.

View File

@ -35,7 +35,7 @@
#ifndef lint #ifndef lint
static char copyright[] = 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 */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
@ -297,6 +297,66 @@ addr_and(struct iaddr *result, const struct iaddr *a1, const struct iaddr *a2) {
return !all_zero; 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 * range2cidr
* *

View File

@ -2321,6 +2321,7 @@ int addr_or(struct iaddr *result,
const struct iaddr *a1, const struct iaddr *a2); const struct iaddr *a1, const struct iaddr *a2);
int addr_and(struct iaddr *result, int addr_and(struct iaddr *result,
const struct iaddr *a1, const struct iaddr *a2); 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, isc_result_t range2cidr(struct iaddrcidrnetlist **result,
const struct iaddr *lo, const struct iaddr *hi); const struct iaddr *lo, const struct iaddr *hi);
isc_result_t free_iaddrcidrnetlist(struct iaddrcidrnetlist **result); isc_result_t free_iaddrcidrnetlist(struct iaddrcidrnetlist **result);

View File

@ -34,7 +34,7 @@
#ifndef lint #ifndef lint
static char copyright[] = 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 */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
@ -2640,6 +2640,12 @@ parse_subnet6_declaration(struct parse *cfile, struct shared_network *share) {
return; 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. * Create a netmask.
*/ */
@ -3703,6 +3709,11 @@ parse_address_range6(struct parse *cfile, struct group *group) {
skip_to_semi(cfile); skip_to_semi(cfile);
return; 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); add_ipv6_pool_to_shared_network(share, &lo, bits);