diff options
author | Samuel Tan <samueltan@google.com> | 2015-08-13 16:45:06 -0700 |
---|---|---|
committer | Samuel Tan <samueltan@google.com> | 2015-08-18 13:46:57 -0700 |
commit | b2d21e6cab5a0167e9e4d0698795b38f6c790ab3 (patch) | |
tree | 42dadc94b5c052b52681677bc1c0cb321fd83198 | |
parent | 4eb4220b0441f724353b049e4deab95be99698d5 (diff) | |
download | dhcpcd-6.8.2-b2d21e6cab5a0167e9e4d0698795b38f6c790ab3.tar.gz |
[PATCH] Accept an ACK after a NAK
Cherry-picked from
https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/
master/net-misc/dhcpcd/files/patches/dhcpcd-6.8.2-Accept-an-ACK-after-a-
NAK.patch.
When a NAK is received, wait for a response interval before
acting on it. In doing so, this allows for networks that
may have duelling DHCP servers which both consider themselves
authoritative on a network. Since other DHCP clients also
act in a similar manner, issues of this sort end up undetected
and network administrators thus consider this situation nominal.
BUG: 22956197
Change-Id: I8cceb03f8296abb4ee6bbdc87c222ae9234b3f5f
Reviewed-on: https://chromium-review.googlesource.com/208207
-rw-r--r-- | dhcp.c | 43 |
1 files changed, 28 insertions, 15 deletions
@@ -2631,6 +2631,30 @@ dhcp_arp_conflicted(struct arp_state *astate, const struct arp_msg *amsg) } static void +handle_nak(void *arg) +{ + struct interface *ifp = arg; + struct dhcp_state *state = D_STATE(ifp); + + logger(ifp->ctx, LOG_INFO, "%s: Handling deferred NAK", ifp->name); + if (!(ifp->ctx->options & DHCPCD_TEST)) { + dhcp_drop(ifp, "NAK"); + unlink(state->leasefile); + } + + /* If we constantly get NAKS then we should slowly back off */ + eloop_timeout_add_sec(ifp->ctx->eloop, + state->nakoff, dhcp_discover, ifp); + if (state->nakoff == 0) + state->nakoff = 1; + else { + state->nakoff *= 2; + if (state->nakoff > NAKOFF_MAX) + state->nakoff = NAKOFF_MAX; + } +} + +static void dhcp_handledhcp(struct interface *ifp, struct dhcp_message **dhcpp, const struct in_addr *from) { @@ -2748,8 +2772,6 @@ dhcp_handledhcp(struct interface *ifp, struct dhcp_message **dhcpp, } if (type == DHCP_NAK) { - /* We should restart on a NAK */ - log_dhcp(LOG_WARNING, "NAK:", ifp, dhcp, from); if ((msg = get_option_string(ifp->ctx, dhcp, DHO_MESSAGE))) { logger(ifp->ctx, LOG_WARNING, "%s: message: %s", ifp->name, msg); @@ -2757,21 +2779,11 @@ dhcp_handledhcp(struct interface *ifp, struct dhcp_message **dhcpp, } if (state->state == DHS_INFORM) /* INFORM should not be NAKed */ return; - if (!(ifp->ctx->options & DHCPCD_TEST)) { - dhcp_drop(ifp, "NAK"); - unlink(state->leasefile); - } - /* If we constantly get NAKS then we should slowly back off */ + log_dhcp(LOG_WARNING, "NAK (deferred):", ifp, dhcp, from); eloop_timeout_add_sec(ifp->ctx->eloop, - state->nakoff, dhcp_discover, ifp); - if (state->nakoff == 0) - state->nakoff = 1; - else { - state->nakoff *= 2; - if (state->nakoff > NAKOFF_MAX) - state->nakoff = NAKOFF_MAX; - } + DHCP_BASE, handle_nak, ifp); + return; } @@ -2888,6 +2900,7 @@ dhcp_handledhcp(struct interface *ifp, struct dhcp_message **dhcpp, return; } eloop_timeout_delete(ifp->ctx->eloop, send_discover, ifp); + eloop_timeout_delete(ifp->ctx->eloop, handle_nak, ifp); /* We don't request BOOTP addresses */ if (type) { /* We used to ARP check here, but that seems to be in |