summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkrw <krw@openbsd.org>2016-10-06 16:12:43 +0000
committerkrw <krw@openbsd.org>2016-10-06 16:12:43 +0000
commit2c9b957aebe55ac9067bc03a9e7e1250222e92b7 (patch)
tree7af0ad72abd60f3859b097936d2ab97efbdd4416
parentEnable hardware VLAN tagging (diff)
downloadwireguard-openbsd-2c9b957aebe55ac9067bc03a9e7e1250222e92b7.tar.xz
wireguard-openbsd-2c9b957aebe55ac9067bc03a9e7e1250222e92b7.zip
Add support for RFC 6842. RFC 2131 said the server MUST NOT echo
the client-identifier value. RFC 6842 says the server MUST echo it. Echoing the information disambiguates packets for relays and clients when chaddr is 0. Similar to what dhcpv6 does.
-rw-r--r--usr.sbin/dhcpd/dhcp.c55
-rw-r--r--usr.sbin/dhcpd/dhcpd.h4
2 files changed, 53 insertions, 6 deletions
diff --git a/usr.sbin/dhcpd/dhcp.c b/usr.sbin/dhcpd/dhcp.c
index b1b1f33cd4c..9db0106124d 100644
--- a/usr.sbin/dhcpd/dhcp.c
+++ b/usr.sbin/dhcpd/dhcp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dhcp.c,v 1.48 2016/10/05 00:50:00 krw Exp $ */
+/* $OpenBSD: dhcp.c,v 1.49 2016/10/06 16:12:43 krw Exp $ */
/*
* Copyright (c) 1995, 1996, 1997, 1998, 1999
@@ -589,7 +589,9 @@ nak_lease(struct packet *packet, struct iaddr *cip)
struct dhcp_packet raw;
unsigned char nak = DHCPNAK;
struct packet outgoing;
- struct tree_cache *options[256], dhcpnak_tree, dhcpmsg_tree, server_tree;
+ struct tree_cache *options[256];
+ struct tree_cache dhcpnak_tree, dhcpmsg_tree;
+ struct tree_cache client_tree, server_tree;
memset(options, 0, sizeof options);
memset(&outgoing, 0, sizeof outgoing);
@@ -614,7 +616,8 @@ nak_lease(struct packet *packet, struct iaddr *cip)
options[i]->buf_size = strlen(dhcp_message);
options[i]->timeout = -1;
options[i]->tree = NULL;
- options[i]->flags = 0;
+ options[i]->flags = 0;
+
/* Include server identifier in the NAK. At least one
* router vendor depends on it when using dhcp relay proxy mode.
*/
@@ -629,6 +632,18 @@ nak_lease(struct packet *packet, struct iaddr *cip)
options[i]->flags = 0;
}
+ /* Echo back the client-identifier as RFC 6842 mandates. */
+ i = DHO_DHCP_CLIENT_IDENTIFIER;
+ if (packet->options[i].len) {
+ options[i] = &client_tree;
+ options[i]->value = packet->options[i].data,
+ options[i]->len = packet->options[i].len;
+ options[i]->buf_size = packet->options[i].len;
+ options[i]->timeout = -1;
+ options[i]->tree = NULL;
+ options[i]->flags = 0;
+ }
+
/* Do not use the client's requested parameter list. */
i = DHO_DHCP_PARAMETER_REQUEST_LIST;
if (packet->options[i].data) {
@@ -777,6 +792,27 @@ ack_lease(struct packet *packet, struct lease *lease, unsigned int offer,
lease->client_hostname = 0;
}
+ /* Replace the lease client identifier with a new one. */
+ i = DHO_DHCP_CLIENT_IDENTIFIER;
+ if (packet->options[i].len && lease->client_identifier &&
+ (strlen(lease->client_identifier) == packet->options[i].len) &&
+ !memcmp(lease->client_identifier, packet->options[i].data,
+ packet->options[i].len)) {
+ /* Same client identifier. */
+ } else if (packet->options[i].len) {
+ free(lease->client_identifier);
+ lease->client_identifier = malloc(packet->options[i].len);
+ if (!lease->client_identifier)
+ error("no memory for client identifier.\n");
+ lease->client_identifier_len = packet->options[i].len;
+ memcpy(lease->client_identifier, packet->options[i].data,
+ packet->options[i].len);
+ } else if (lease->client_identifier) {
+ free(lease->client_identifier);
+ lease->client_identifier = NULL;
+ lease->client_identifier_len = 0;
+ }
+
/*
* Choose a filename; first from the host_decl, if any, then from
* the user class, then from the vendor class.
@@ -1201,9 +1237,18 @@ ack_lease(struct packet *packet, struct lease *lease, unsigned int offer,
state->options[i]->tree = NULL;
}
- /* RFC 2131: MUST NOT send client identifier option in OFFER/ACK! */
+ /* Echo back the client-identifier as RFC 6842 mandates. */
i = DHO_DHCP_CLIENT_IDENTIFIER;
- memset(&state->options[i], 0, sizeof(state->options[i]));
+ if (lease->client_identifier) {
+ state->options[i] = new_tree_cache("dhcp-client-identifier");
+ state->options[i]->flags = TC_TEMPORARY;
+ state->options[i]->value = lease->client_identifier;
+ state->options[i]->len = lease->client_identifier_len;
+ state->options[i]->buf_size = lease->client_identifier_len;
+ state->options[i]->timeout = -1;
+ state->options[i]->tree = NULL;
+ } else
+ memset(&state->options[i], 0, sizeof(state->options[i]));
lease->state = state;
diff --git a/usr.sbin/dhcpd/dhcpd.h b/usr.sbin/dhcpd/dhcpd.h
index 28a53741a9b..23e3f527aaf 100644
--- a/usr.sbin/dhcpd/dhcpd.h
+++ b/usr.sbin/dhcpd/dhcpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dhcpd.h,v 1.54 2016/08/05 14:02:23 krw Exp $ */
+/* $OpenBSD: dhcpd.h,v 1.55 2016/10/06 16:12:43 krw Exp $ */
/*
* Copyright (c) 1995, 1996, 1997, 1998, 1999
@@ -136,11 +136,13 @@ struct lease {
unsigned char uid_buf[32];
char *hostname;
char *client_hostname;
+ uint8_t *client_identifier;
struct host_decl *host;
struct subnet *subnet;
struct shared_network *shared_network;
struct hardware hardware_addr;
+ int client_identifier_len;
int flags;
#define STATIC_LEASE 1
#define BOOTP_LEASE 2