diff options
author | Kenneth R Westerback <krw@cvs.openbsd.org> | 2016-10-06 16:12:44 +0000 |
---|---|---|
committer | Kenneth R Westerback <krw@cvs.openbsd.org> | 2016-10-06 16:12:44 +0000 |
commit | a7de81245dac1153181b3c910384914076713599 (patch) | |
tree | 4ea8e831b735c8cc9a1ec14e8b3999b32e2643c9 /usr.sbin | |
parent | 401c6594aa8e09de76f948f1c16d75578c0c20d6 (diff) |
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.
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/dhcpd/dhcp.c | 55 | ||||
-rw-r--r-- | usr.sbin/dhcpd/dhcpd.h | 4 |
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 |