aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Tan <samueltan@google.com>2015-08-13 16:45:06 -0700
committerSamuel Tan <samueltan@google.com>2015-08-18 13:46:57 -0700
commitb2d21e6cab5a0167e9e4d0698795b38f6c790ab3 (patch)
tree42dadc94b5c052b52681677bc1c0cb321fd83198
parent4eb4220b0441f724353b049e4deab95be99698d5 (diff)
downloaddhcpcd-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.c43
1 files changed, 28 insertions, 15 deletions
diff --git a/dhcp.c b/dhcp.c
index 7196f13..e57f6e0 100644
--- a/dhcp.c
+++ b/dhcp.c
@@ -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