summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2009-07-05 11:33:46 +0000
committerRoy Marples <roy@marples.name>2009-07-05 11:33:46 +0000
commitbf80d526822f7903b5da1e329627495aa6d34401 (patch)
treef9a4cd5daed617034ddaf21f17665bdfa33262fc
parenta95ad17c17dd38bbb4e7386fa7c78abbbbc30d7c (diff)
downloaddhcpcd-bf80d526822f7903b5da1e329627495aa6d34401.tar.xz
Add -W, --whitelist addr/cidr
This only allows packets from the addresses listed and overrides blacklist if set.
-rw-r--r--dhcpcd.8.in10
-rw-r--r--dhcpcd.c24
-rw-r--r--dhcpcd.conf.5.in9
-rw-r--r--if-options.c11
-rw-r--r--if-options.h4
5 files changed, 54 insertions, 4 deletions
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;