summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorDavid Hankins <dhankins@isc.org>2006-05-15 15:07:50 +0000
committerDavid Hankins <dhankins@isc.org>2006-05-15 15:07:50 +0000
commitfebbd40203955b523fd5bc8aa62a6274311d92f9 (patch)
tree17e5066831417fd36c483b56e864a972e3488445 /common
parent6da113fb953760d28800dc6d9d36ab2a9bc1f220 (diff)
downloadisc-dhcp-febbd40203955b523fd5bc8aa62a6274311d92f9.tar.gz
- The dhclient 'reject ...;' statement, which rejects leases given by named
server-identifiers, now permits address ranges to be specified in CIDR notation. [ISC-Bugs #1435]
Diffstat (limited to 'common')
-rw-r--r--common/inet.c27
-rw-r--r--common/parse.c94
2 files changed, 119 insertions, 2 deletions
diff --git a/common/inet.c b/common/inet.c
index e272bd21..934eba19 100644
--- a/common/inet.c
+++ b/common/inet.c
@@ -35,7 +35,7 @@
#ifndef lint
static char copyright[] =
-"$Id: inet.c,v 1.10 2005/03/17 20:14:58 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
+"$Id: inet.c,v 1.11 2006/05/15 15:07:49 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@@ -185,6 +185,31 @@ int addr_eq (addr1, addr2)
return memcmp (addr1.iabuf, addr2.iabuf, addr1.len) == 0;
}
+/* addr_match
+ *
+ * compares an IP address against a network/mask combination
+ * by ANDing the IP with the mask and seeing whether the result
+ * matches the masked network value.
+ */
+int
+addr_match(addr, match)
+ struct iaddr *addr;
+ struct iaddrmatch *match;
+{
+ int i;
+
+ if (addr->len != match->addr.len)
+ return 0;
+
+ i = 0;
+ for (i = 0 ; i < addr->len ; i++) {
+ if ((addr->iabuf[i] & match->mask.iabuf[i]) !=
+ match->addr.iabuf[i])
+ return 0;
+ }
+ return 1;
+}
+
char *piaddr (addr)
struct iaddr addr;
{
diff --git a/common/parse.c b/common/parse.c
index 8aefd5d6..247e39b7 100644
--- a/common/parse.c
+++ b/common/parse.c
@@ -34,7 +34,7 @@
#ifndef lint
static char copyright[] =
-"$Id: parse.c,v 1.108 2006/05/11 16:31:29 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
+"$Id: parse.c,v 1.109 2006/05/15 15:07:49 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@@ -322,6 +322,98 @@ int parse_ip_addr (cfile, addr)
}
/*
+ * ip-address-with-subnet :== ip-address |
+ * ip-address "/" NUMBER
+ */
+
+int
+parse_ip_addr_with_subnet(cfile, match)
+ struct parse *cfile;
+ struct iaddrmatch *match;
+{
+ const char *val, *orig;
+ enum dhcp_token token;
+ int prefixlen;
+ int fflen;
+ unsigned char newval, warnmask=0;
+
+ if (parse_ip_addr(cfile, &match->addr)) {
+ /* default to host mask */
+ prefixlen = match->addr.len * 8;
+
+ token = peek_token(&val, NULL, cfile);
+
+ if (token == SLASH) {
+ next_token(&val, NULL, cfile);
+ token = next_token(&val, NULL, cfile);
+
+ if (token != NUMBER) {
+ parse_warn(cfile, "Invalid CIDR prefix length:"
+ " expecting a number.");
+ return 0;
+ }
+
+ prefixlen = atoi(val);
+
+ if (prefixlen < 0 ||
+ prefixlen > (match->addr.len * 8)) {
+ parse_warn(cfile, "subnet prefix is out of "
+ "range [0..%d].",
+ match->addr.len * 8);
+ return 0;
+ }
+ }
+
+ /* construct a suitable mask field */
+
+ /* copy length */
+ match->mask.len = match->addr.len;
+
+ /* count of 0xff bytes in mask */
+ fflen = prefixlen / 8;
+
+ /* set leading mask */
+ memset(match->mask.iabuf, 0xff, fflen);
+
+ /* set zeroes */
+ if (fflen < match->mask.len) {
+ match->mask.iabuf[fflen] =
+ "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe"[prefixlen % 8];
+
+ memset(match->mask.iabuf+fflen+1, 0x00,
+ match->mask.len - fflen - 1);
+
+ /* AND-out insignificant bits from supplied netmask. */
+ orig = piaddr(match->addr);
+ do {
+ newval = match->addr.iabuf[fflen] &
+ match->mask.iabuf[fflen];
+
+ if (newval != match->addr.iabuf[fflen]) {
+ warnmask = 1;
+ match->addr.iabuf[fflen] = newval;
+ }
+ } while (++fflen < match->mask.len);
+
+ if (warnmask) {
+ log_error("Warning: Extraneous bits removed "
+ "in address component of %s/%d.",
+ orig, prefixlen);
+ log_error("New value: %s/%d.",
+ piaddr(match->addr), prefixlen);
+ }
+ }
+
+ return 1;
+ }
+
+ parse_warn(cfile,
+ "expecting ip-address or ip-address/prefixlen");
+
+ return 0; /* let caller pick up pieces */
+}
+
+/*
* hardware-parameter :== HARDWARE hardware-type colon-seperated-hex-list SEMI
* hardware-type :== ETHERNET | TOKEN_RING | FDDI
*/