From: Roy Marples Date: Sun, 5 Jul 2009 11:33:46 +0000 (+0000) Subject: Add -W, --whitelist addr/cidr X-Git-Tag: v5.0.6~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bf80d526822f7903b5da1e329627495aa6d34401;p=thirdparty%2Fdhcpcd.git Add -W, --whitelist addr/cidr This only allows packets from the addresses listed and overrides blacklist if set. --- diff --git a/dhcpcd.8.in b/dhcpcd.8.in index 059a35a9..7e712456 100644 --- a/dhcpcd.8.in +++ b/dhcpcd.8.in @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd April 24, 2009 +.Dd July 5, 2009 .Dt DHCPCD 8 SMM .Os .Sh NAME @@ -51,6 +51,7 @@ .Op Fl O , -nooption Ar option .Op Fl Q , -require Ar option .Op Fl S , -static Ar value +.Op Fl W , -whitelist Ar address Ns Op Ar /cidr .Op Fl X , -blacklist Ar address Ns Op Ar /cidr .Op Fl Z , -denyinterfaces Ar pattern .Op interface @@ -465,6 +466,13 @@ Display a list of option codes and the associated variable for use in Variables are prefixed with new_ and old_ unless the option number is -. Variables without an option are part of the DHCP message and cannot be directly requested. +.It Fl W, -whitelist Ar address Ns Op /cidr +Only accept packets from +.Ar address Ns Op /cidr . +.Fl X, -blacklist +is ignored if +.Fl W, -whitelist +is set. .It Fl X, -blacklist Ar address Ns Op Ar /cidr Ignore all packets from .Ar address Ns Op Ar /cidr . diff --git a/dhcpcd.c b/dhcpcd.c index 1b4dd9ae..950dd169 100644 --- a/dhcpcd.c +++ b/dhcpcd.c @@ -430,6 +430,19 @@ blacklisted_ip(const struct if_options *ifo, in_addr_t addr) return 0; } +static int +whitelisted_ip(const struct if_options *ifo, in_addr_t addr) +{ + size_t i; + + if (ifo->whitelist_len == 0) + return -1; + for (i = 0; i < ifo->whitelist_len; i += 2) + if (ifo->whitelist[i] == (addr & ifo->whitelist[i + 1])) + return 1; + return 0; +} + static void handle_dhcp(struct interface *iface, struct dhcp_message **dhcpp) { @@ -585,6 +598,7 @@ handle_dhcp_packet(void *arg) const uint8_t *pp; ssize_t bytes; struct in_addr from; + int i; /* We loop through until our buffer is empty. * The benefit is that if we get >1 DHCP packet in our buffer and @@ -600,7 +614,15 @@ handle_dhcp_packet(void *arg) iface->name, inet_ntoa(from)); continue; } - if (blacklisted_ip(iface->state->options, from.s_addr)) { + i = whitelisted_ip(iface->state->options, from.s_addr); + if (i == 0) { + syslog(LOG_WARNING, + "%s: non whitelisted DHCP packet from %s", + iface->name, inet_ntoa(from)); + continue; + } else if (i != 1 && + blacklisted_ip(iface->state->options, from.s_addr) == 1) + { syslog(LOG_WARNING, "%s: blacklisted DHCP packet from %s", iface->name, inet_ntoa(from)); diff --git a/dhcpcd.conf.5.in b/dhcpcd.conf.5.in index 689a90d5..c9efad72 100644 --- a/dhcpcd.conf.5.in +++ b/dhcpcd.conf.5.in @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd July 4, 2009 +.Dd July 5, 2009 .Dt DHCPCD.CONF 5 SMM .Os .Sh NAME @@ -76,6 +76,13 @@ carrier status. .It Ic blacklist Ar address Ns Op /cidr Ignores all packets from .Ar address Ns Op /cidr . +.It Ic whitelist Ar address Ns Op /cidr +Only accept packets from +.Ar address Ns Op /cidr . +.Ic blacklist +is ignored if +.Ic whitelist +is set. .It Ic clientid Ar string Send the .Ar clientid . diff --git a/if-options.c b/if-options.c index 7a9e5e3d..a22929b3 100644 --- a/if-options.c +++ b/if-options.c @@ -90,6 +90,7 @@ const struct option cf_options[] = { {"static", required_argument, NULL, 'S'}, {"test", no_argument, NULL, 'T'}, {"variables", no_argument, NULL, 'V'}, + {"whitelist", required_argument, NULL, 'W'}, {"blacklist", required_argument, NULL, 'X'}, {"denyinterfaces", required_argument, NULL, 'Z'}, {"arping", required_argument, NULL, O_ARPING}, @@ -653,6 +654,16 @@ parse_option(struct if_options *ifo, int opt, const char *arg) ifo->config[s + 1] = NULL; } break; + case 'W': + if (parse_addr(&addr, &addr2, arg) != 0) + return -1; + if (strchr(arg, '/') == NULL) + addr2.s_addr = INADDR_BROADCAST; + ifo->whitelist = xrealloc(ifo->whitelist, + sizeof(in_addr_t) * (ifo->whitelist_len + 2)); + ifo->whitelist[ifo->whitelist_len++] = addr.s_addr; + ifo->whitelist[ifo->whitelist_len++] = addr2.s_addr; + break; case 'X': if (parse_addr(&addr, &addr2, arg) != 0) return -1; diff --git a/if-options.h b/if-options.h index 396f44ea..3fa86396 100644 --- a/if-options.h +++ b/if-options.h @@ -37,7 +37,7 @@ /* Don't set any optional arguments here so we retain POSIX * compatibility with getopt */ -#define IF_OPTS "bc:def:h:i:kl:m:no:pqr:s:t:u:v:xy:z:ABC:DEF:GI:KLN:O:Q:TVX:Z:" +#define IF_OPTS "bc:def:h:i:kl:m:no:pqr:s:t:u:v:xy:z:ABC:DEF:GI:KLN:O:Q:TVW:X:Z:" #define DEFAULT_TIMEOUT 30 #define DEFAULT_REBOOT 10 @@ -100,6 +100,8 @@ struct if_options { size_t blacklist_len; in_addr_t *blacklist; + size_t whitelist_len; + in_addr_t *whitelist; size_t arping_len; in_addr_t *arping; char *fallback;