blob: 6cf8b5e6317ddbfcfc33ba1b573616920d2ae977 [file] [log] [blame]
From 566e20e7740d8f032614c47b93c866a1d2c97840 Mon Sep 17 00:00:00 2001
From: Paul Stewart <pstew@chromium.org>
Date: Mon, 14 Jun 2021 12:32:58 +0000
Subject: [PATCH 15/19] Ensure gateway probe is broadcast
The arp_new() method does not always return a freshly
initialized arp_state structure. For example, if
dhcp_probe_gw() is called while a probe from
start_unicast_arp() is still running, the arp_state
object from the unicast ARP call will be returned by
arp_new(). This can happen when a DHCP renew succeeds
while a unicast "GatewayArp" is still in progress.
In the above scenario we need to make sure the dest_hwlen
field of the arp_state structure is zero. This signals a
broadcast ARP, and will ensure that the callbacks that are
invoked by the ARP state machine know which case we are in.
While here, add a small optimization that skips a
broadcast gateway ARP if a unicast ARP succeeds.
BUG=chromium:531042
TEST=Reconnect to WiFi network where ARP fails
---
src/dhcp.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/dhcp.c b/src/dhcp.c
index c8ec40da..ac339a6a 100644
--- a/src/dhcp.c
+++ b/src/dhcp.c
@@ -2171,6 +2171,8 @@ dhcp_probe_gw_response(struct arp_state *astate, const struct arp_msg *amsg)
if (astate->dest_hwlen) {
/* Response to unicast ARP. */
rpc_notify_unicast_arp(astate->iface);
+ /* Unicast ARP succeeded; no need for broadcast ARP. */
+ astate->iface->options->options &= ~DHCPCD_ARPGW;
} else {
/* Response to arpgw request. */
save_gateway_addr(astate->iface, amsg->sha);
@@ -2199,6 +2201,8 @@ dhcp_probe_gw(struct interface *ifp)
state->offer, state->offer_len, DHO_ROUTER) == 0) {
astate = arp_new(ifp, &gateway_addr);
if (astate) {
+ /* Make sure we're doing a broadcast ARP. */
+ astate->dest_hwlen = 0;
astate->src_addr.s_addr = state->offer->yiaddr;
astate->probed_cb = dhcp_probe_gw_timeout;
astate->conflicted_cb = dhcp_probe_gw_response;
--
2.33.0.800.g4c38ced690-goog