summaryrefslogtreecommitdiff
path: root/sbin/dhclient
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2016-10-06 16:29:18 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2016-10-06 16:29:18 +0000
commit432e4be4b386265a8c7d11952628bcf51e5c46b8 (patch)
tree45594b80c734d225dc12f89f96a261c03717cb16 /sbin/dhclient
parentd690d085048eb7d9e73e77cd86a4869ec7c25810 (diff)
Add support for RFC 6842, which says the client MUST drop packets when
the server provides a client-identifier value and it doesn't match the value the client sent. So stop suppressing client-identifer info in the leases file and when reading the leases file stop discarding leases that don't have current client-identifier info. Don't use them, but keep them around in case the client-identifier info changes back next time. Also construct the default client-identifier (if needed) before reading the leases file.
Diffstat (limited to 'sbin/dhclient')
-rw-r--r--sbin/dhclient/clparse.c42
-rw-r--r--sbin/dhclient/dhclient.c61
-rw-r--r--sbin/dhclient/dispatch.c5
-rw-r--r--sbin/dhclient/options.c19
4 files changed, 73 insertions, 54 deletions
diff --git a/sbin/dhclient/clparse.c b/sbin/dhclient/clparse.c
index c7a6f087dd4..f427eafcb4c 100644
--- a/sbin/dhclient/clparse.c
+++ b/sbin/dhclient/clparse.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clparse.c,v 1.102 2016/09/30 13:20:57 krw Exp $ */
+/* $OpenBSD: clparse.c,v 1.103 2016/10/06 16:29:17 krw Exp $ */
/* Parser for dhclient config and lease files. */
@@ -466,7 +466,6 @@ parse_client_lease_statement(FILE *cfile, int is_static, struct interface_info *
{
struct client_state *client = ifi->client;
struct client_lease *lease, *lp, *pl;
- struct option_data *opt1, *opt2;
int token;
token = next_token(NULL, cfile);
@@ -495,31 +494,28 @@ parse_client_lease_statement(FILE *cfile, int is_static, struct interface_info *
token = next_token(NULL, cfile);
/*
- * If the new lease is for an obsolete client-identifier, toss it.
- */
- opt1 = &lease->options[DHO_DHCP_CLIENT_IDENTIFIER];
- opt2 = &config->send_options[DHO_DHCP_CLIENT_IDENTIFIER];
- if (opt1->len && opt2->len && (opt1->len != opt2->len ||
- memcmp(opt1->data, opt2->data, opt1->len))) {
- note("Obsolete client identifier (%s) in recorded lease",
- pretty_print_option(DHO_DHCP_CLIENT_IDENTIFIER, opt1, 0));
- free_client_lease(lease);
- return;
- }
-
- /*
- * The new lease will supersede a lease of the same type and for
- * the same address or the same SSID.
+ * The new lease will supersede a lease which is of the same type
+ * AND the same ssid AND the same Client Identifier AND the same
+ * IP address.
*/
TAILQ_FOREACH_SAFE(lp, &client->leases, next, pl) {
if (lp->is_static != is_static)
continue;
- if ((strcmp(lp->ssid, ifi->ssid) == 0) ||
- (lp->address.s_addr == lease->address.s_addr)) {
- TAILQ_REMOVE(&client->leases, lp, next);
- lp->is_static = 0; /* Else it won't be freed. */
- free_client_lease(lp);
- }
+ if (strcmp(lp->ssid, ifi->ssid) != 0)
+ continue;
+ if ((lease->options[DHO_DHCP_CLIENT_IDENTIFIER].len != 0) &&
+ ((lp->options[DHO_DHCP_CLIENT_IDENTIFIER].len !=
+ lease->options[DHO_DHCP_CLIENT_IDENTIFIER].len) ||
+ memcmp(lp->options[DHO_DHCP_CLIENT_IDENTIFIER].data,
+ lease->options[DHO_DHCP_CLIENT_IDENTIFIER].data,
+ lp->options[DHO_DHCP_CLIENT_IDENTIFIER].len)))
+ continue;
+ if (lp->address.s_addr != lease->address.s_addr)
+ continue;
+
+ TAILQ_REMOVE(&client->leases, lp, next);
+ lp->is_static = 0; /* Else it won't be freed. */
+ free_client_lease(lp);
}
/*
diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c
index 692643c8754..40edc43c02e 100644
--- a/sbin/dhclient/dhclient.c
+++ b/sbin/dhclient/dhclient.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dhclient.c,v 1.391 2016/09/29 15:29:06 krw Exp $ */
+/* $OpenBSD: dhclient.c,v 1.392 2016/10/06 16:29:17 krw Exp $ */
/*
* Copyright 2004 Henning Brauer <henning@openbsd.org>
@@ -430,6 +430,7 @@ int
main(int argc, char *argv[])
{
struct interface_info *ifi;
+ struct option_data *opt;
struct ifreq ifr;
struct ieee80211_nwid nwid;
struct stat sb;
@@ -506,6 +507,7 @@ main(int argc, char *argv[])
ifi->index = if_nametoindex(ifi->name);
if (ifi->index == 0)
error("%s: no such interface", ifi->name);
+ get_hw_address(ifi);
tzset();
@@ -555,6 +557,29 @@ main(int argc, char *argv[])
read_client_conf(ifi);
+ /*
+ * Set default client identifier, if needed, *before* reading
+ * the leases file! Changes to the lladdr will trigger a restart
+ * and go through here again.
+ *
+ * Check both len && data so
+ *
+ * send dhcp-client-identifier "";
+ *
+ * can be used to suppress sending the default client
+ * identifier.
+ */
+ opt = &config->send_options[DHO_DHCP_CLIENT_IDENTIFIER];
+ if (opt->len == 0 && opt->data == NULL) {
+ opt->data = calloc(1, ETHER_ADDR_LEN + 1);
+ if (opt->data == NULL)
+ error("no memory for default client identifier");
+ opt->data[0] = HTYPE_ETHER;
+ memcpy(&opt->data[1], ifi->hw_address.ether_addr_octet,
+ ETHER_ADDR_LEN);
+ opt->len = ETHER_ADDR_LEN + 1;
+ }
+
if ((pw = getpwnam("_dhcp")) == NULL)
error("no such user: _dhcp");
@@ -732,32 +757,13 @@ state_reboot(void *xifi)
struct client_state *client = ifi->client;
char ifname[IF_NAMESIZE];
struct client_lease *lp;
- struct option_data *opt;
time_t cur_time;
+ int i;
cancel_timeout();
deleting.s_addr = INADDR_ANY;
adding.s_addr = INADDR_ANY;
- get_hw_address(ifi);
- opt = &config->send_options[DHO_DHCP_CLIENT_IDENTIFIER];
- /*
- * Check both len && data so
- * send dhcp-client-identifier "";
- * can be used to suppress sending the default client
- * identifier.
- */
- if (opt->len == 0 && opt->data == NULL) {
- /* Build default client identifier. */
- opt->data = calloc(1, ETHER_ADDR_LEN + 1);
- if (opt->data != NULL) {
- opt->data[0] = HTYPE_ETHER;
- memcpy(&opt->data[1], ifi->hw_address.ether_addr_octet,
- ETHER_ADDR_LEN);
- opt->len = ETHER_ADDR_LEN + 1;
- }
- }
-
time(&cur_time);
if (client->active) {
if (client->active->expiry <= cur_time)
@@ -768,9 +774,15 @@ state_reboot(void *xifi)
}
/* Run through the list of leases and see if one can be used. */
+ i = DHO_DHCP_CLIENT_IDENTIFIER;
TAILQ_FOREACH(lp, &client->leases, next) {
if (strcmp(lp->ssid, ifi->ssid) != 0)
continue;
+ if ((lp->options[i].len != 0) && ((lp->options[i].len !=
+ config->send_options[i].len) ||
+ memcmp(lp->options[i].data, config->send_options[i].data,
+ lp->options[i].len)))
+ continue;
if (addressinuse(ifi, lp->address, ifname) &&
strncmp(ifname, ifi->name, IF_NAMESIZE) != 0)
continue;
@@ -2004,12 +2016,7 @@ lease_as_string(struct interface_info *ifi, char *type,
}
for (i = 0; i < 256; i++) {
- if (i == DHO_DHCP_CLIENT_IDENTIFIER) {
- /* Ignore any CLIENT_IDENTIFIER from server. */
- opt = &config->send_options[i];
- } else
- opt = &lease->options[i];
-
+ opt = &lease->options[i];
if (opt->len == 0)
continue;
diff --git a/sbin/dhclient/dispatch.c b/sbin/dhclient/dispatch.c
index b05b576e4ab..555d3436a3f 100644
--- a/sbin/dhclient/dispatch.c
+++ b/sbin/dhclient/dispatch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dispatch.c,v 1.110 2016/09/29 00:40:08 krw Exp $ */
+/* $OpenBSD: dispatch.c,v 1.111 2016/10/06 16:29:17 krw Exp $ */
/*
* Copyright 2004 Henning Brauer <henning@openbsd.org>
@@ -86,8 +86,7 @@ get_hw_address(struct interface_info *ifi)
found = 0;
for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
if ((ifa->ifa_flags & IFF_LOOPBACK) ||
- (ifa->ifa_flags & IFF_POINTOPOINT) ||
- (!(ifa->ifa_flags & IFF_UP)))
+ (ifa->ifa_flags & IFF_POINTOPOINT))
continue;
if (strcmp(ifi->name, ifa->ifa_name) != 0)
diff --git a/sbin/dhclient/options.c b/sbin/dhclient/options.c
index 2a85ea50126..93aa1f2b3b0 100644
--- a/sbin/dhclient/options.c
+++ b/sbin/dhclient/options.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: options.c,v 1.78 2016/09/02 15:44:26 mpi Exp $ */
+/* $OpenBSD: options.c,v 1.79 2016/10/06 16:29:17 krw Exp $ */
/* DHCP options parsing and reassembly. */
@@ -711,6 +711,22 @@ do_packet(struct interface_info *ifi, unsigned int from_port,
(unsigned char *)packet->sname,
sizeof(packet->sname));
}
+
+ /*
+ * RFC 6842 says if the server sends a client identifier
+ * that doesn't match then the packet must be dropped.
+ */
+ i = DHO_DHCP_CLIENT_IDENTIFIER;
+ if ((options[i].len != 0) &&
+ ((options[i].len != config->send_options[i].len) ||
+ memcmp(options[i].data, config->send_options[i].data,
+ options[i].len) != 0)) {
+#ifdef DEBUG
+ debug("Discarding packet with client-identifier '%s'",
+ pretty_print_option(i, &options[i], 0));
+#endif
+ goto done;
+ }
}
type = "<unknown>";
@@ -757,6 +773,7 @@ do_packet(struct interface_info *ifi, unsigned int from_port,
free(info);
+done:
for (i = 0; i < 256; i++)
free(options[i].data);
}