summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkrw <krw@openbsd.org>2020-04-26 14:02:23 +0000
committerkrw <krw@openbsd.org>2020-04-26 14:02:23 +0000
commitbaa7a83da466a84b823fe06a0f7f368cc23baa89 (patch)
tree08622bb8edee85efde3eaf0e4836577a7a66aa59
parentfix the description; from andras farkas (diff)
downloadwireguard-openbsd-baa7a83da466a84b823fe06a0f7f368cc23baa89.tar.xz
wireguard-openbsd-baa7a83da466a84b823fe06a0f7f368cc23baa89.zip
Tighten up NAK handling. Inform unwind when the active lease is
discarded. Update leases file when active lease is discarded. Discard NAK'ed offers even if there is no active lease. Always transition to INIT. Issues discovered after inappropriate behaviour resported by Alexander Markert and Pierre Emeriaud.
-rw-r--r--sbin/dhclient/dhclient.c45
1 files changed, 27 insertions, 18 deletions
diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c
index 3fefa0fd1c7..3e8331240ac 100644
--- a/sbin/dhclient/dhclient.c
+++ b/sbin/dhclient/dhclient.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dhclient.c,v 1.662 2020/04/24 18:07:06 krw Exp $ */
+/* $OpenBSD: dhclient.c,v 1.663 2020/04/26 14:02:23 krw Exp $ */
/*
* Copyright 2004 Henning Brauer <henning@openbsd.org>
@@ -937,6 +937,11 @@ dhcpack(struct interface_info *ifi, struct option_data *options,
void
dhcpnak(struct interface_info *ifi, const char *src)
{
+ struct client_lease *ll, *pl;
+ time_t cur_time;
+
+ time(&cur_time);
+
if (ifi->state != S_REBOOTING &&
ifi->state != S_REQUESTING &&
ifi->state != S_RENEWING) {
@@ -945,24 +950,28 @@ dhcpnak(struct interface_info *ifi, const char *src)
return;
}
- if (ifi->active == NULL) {
- log_debug("%s: unexpected DHCPNAK from %s - no active lease",
- log_procname, src);
- return;
- }
-
log_debug("%s: DHCPNAK from %s", log_procname, src);
- revoke_proposal(ifi->configured);
- /* XXX Do we really want to remove a NAK'd lease from the database? */
- TAILQ_REMOVE(&ifi->lease_db, ifi->active, next);
- free_client_lease(ifi->active);
-
- ifi->active = NULL;
- free(ifi->configured);
- ifi->configured = NULL;
- free(ifi->unwind_info);
- ifi->unwind_info = NULL;
+ /* Remove expired leases and the NAK'd address from the database. */
+ TAILQ_FOREACH_SAFE(ll, &ifi->lease_db, next, pl) {
+ if (lease_expiry(ll) < cur_time || (
+ ifi->ssid_len == ll->ssid_len &&
+ memcmp(ifi->ssid, ll->ssid, ll->ssid_len) == 0 &&
+ ll->address.s_addr == ifi->requested_address.s_addr)) {
+ if (ll == ifi->active) {
+ tell_unwind(NULL, ifi->flags);
+ free(ifi->unwind_info);
+ ifi->unwind_info = NULL;
+ revoke_proposal(ifi->configured);
+ free(ifi->configured);
+ ifi->configured = NULL;
+ ifi->active = NULL;
+ }
+ TAILQ_REMOVE(&ifi->lease_db, ll, next);
+ free_client_lease(ll);
+ write_lease_db(&ifi->lease_db);
+ }
+ }
/* Stop sending DHCPREQUEST packets. */
cancel_timeout(ifi);
@@ -1674,7 +1683,6 @@ make_request(struct interface_info *ifi, struct client_lease *lease)
}
if (ifi->state == S_REQUESTING ||
ifi->state == S_REBOOTING) {
- ifi->requested_address = lease->address;
i = DHO_DHCP_REQUESTED_ADDRESS;
options[i].data = (char *)&lease->address.s_addr;
options[i].len = sizeof(lease->address.s_addr);
@@ -1713,6 +1721,7 @@ make_request(struct interface_info *ifi, struct client_lease *lease)
* If we own the address we're requesting, put it in ciaddr. Otherwise
* set ciaddr to zero.
*/
+ ifi->requested_address = lease->address;
if (ifi->state == S_BOUND ||
ifi->state == S_RENEWING)
packet->ciaddr.s_addr = lease->address.s_addr;