diff options
author | David Hankins <dhankins@isc.org> | 2006-05-15 15:07:50 +0000 |
---|---|---|
committer | David Hankins <dhankins@isc.org> | 2006-05-15 15:07:50 +0000 |
commit | febbd40203955b523fd5bc8aa62a6274311d92f9 (patch) | |
tree | 17e5066831417fd36c483b56e864a972e3488445 /common | |
parent | 6da113fb953760d28800dc6d9d36ab2a9bc1f220 (diff) | |
download | isc-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.c | 27 | ||||
-rw-r--r-- | common/parse.c | 94 |
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 */ |