summaryrefslogtreecommitdiff
path: root/libdhcp
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-09-28 17:01:59 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-09-28 17:01:59 -0600
commitfce80f2dc24ef45142ff92f74ebf809a39e06768 (patch)
tree01c591ca26460e7ca30597a85adff173d1ffc9a0 /libdhcp
parentbbf836c886a348bab4fad92d7ba448d1bbc9c910 (diff)
parent35c0f64218f4aa562f2dcde8eace87962bcab4e4 (diff)
Merge branch 'lukeshu/linkdown'HEADmain
Diffstat (limited to 'libdhcp')
-rw-r--r--libdhcp/dhcp_client.c60
-rw-r--r--libdhcp/tests/test_client.c6
2 files changed, 55 insertions, 11 deletions
diff --git a/libdhcp/dhcp_client.c b/libdhcp/dhcp_client.c
index 359bd9f..208bc1c 100644
--- a/libdhcp/dhcp_client.c
+++ b/libdhcp/dhcp_client.c
@@ -461,10 +461,8 @@ static error dhcp_client_send(struct dhcp_client *client, uint8_t msgtyp, const
log_debugln("state ", state_strs[client->state], ": sending DHCP ", dhcp_msgtyp_str(msgtyp));
error err = LO_CALL(client->sock, sendto, scratch_msg, DHCP_MSG_BASE_SIZE + optlen,
client_broadcasts ? net_ip4_addr_broadcast : client->lease_server_id, DHCP_PORT_SERVER);
- if (!ERROR_IS_NULL(err)) {
- log_debugln("error: sendto: ", (error, err));
+ if (!ERROR_IS_NULL(err))
return err;
- }
client->last_sent_msgtyp = msgtyp;
return ERROR_NULL;
}
@@ -573,7 +571,6 @@ static error dhcp_client_recv(struct dhcp_client *client, struct dhcp_recv_msg *
ignore:
size_t_or_error r = LO_CALL(client->sock, recvfrom, &ret->raw, sizeof(ret->raw), &srv_addr, &srv_port);
if (r.is_err)
- /* msg_len is -errno */
return r.err;
msg_len = r.size_t;
@@ -743,8 +740,15 @@ static void dhcp_client_setstate(struct dhcp_client *client,
uint8_t send_msgtyp, const char *errstr, struct dhcp_recv_msg *scratch_msg) {
if (send_msgtyp) {
error err = dhcp_client_send(client, send_msgtyp, errstr, &scratch_msg->raw);
+ if (!ERROR_IS_NULL(err)) {
+ log_errorln("error: sendto: ", (error, err));
+ if (err.num == E_POSIX_ENETDOWN)
+ newstate = STATE_INIT;
+ }
error_cleanup(&err);
}
+ if (newstate == STATE_INIT)
+ LO_CALL(client->iface, ifcfg, (struct net_iface_config){});
client->state = newstate;
}
@@ -757,6 +761,17 @@ static void dhcp_client_setstate(struct dhcp_client *client,
log_debugln("loop: state=", state_strs[client->state]);
switch (client->state) {
case STATE_INIT:
+ log_debugln("state ", state_strs[client->state], ": wait for link up");
+ uint64_t start = LO_CALL(bootclock, get_time_ns);
+ LO_CALL(client->iface, wait_for_link_up);
+ uint64_t end = LO_CALL(bootclock, get_time_ns);
+ log_debugln("state ", state_strs[client->state], ": link up after ", (duration, end-start));
+ /* Just because we've processed link-up on our end
+ * doesn't mean the router has; 500ms now is better than
+ * the REQUEST packet getting dropped and us having to
+ * wait an entire CONFIG_DHCP_SELECTING_NS before
+ * realizing it. */
+ sleep_for_ms(500);
client->xid = rand_uint32();
client->time_ns_init = LO_CALL(bootclock, get_time_ns);
dhcp_client_setstate(client, STATE_SELECTING, DHCP_MSGTYP_DISCOVER, NULL, scratch_msg);
@@ -776,10 +791,15 @@ static void dhcp_client_setstate(struct dhcp_client *client,
}
break;
case E_NET_ERECV_TIMEOUT:
+ log_errorln("error: recvfrom: ", (error, err), " (action: reset to state=INIT)");
+ dhcp_client_setstate(client, STATE_INIT, 0, NULL, scratch_msg);
+ break;
+ case E_POSIX_ENETDOWN:
+ log_errorln("error: recvfrom: ", (error, err), " (action: reset to state=INIT)");
dhcp_client_setstate(client, STATE_INIT, 0, NULL, scratch_msg);
break;
default:
- log_debugln("error: recvfrom: ", (error, err));
+ log_errorln("error: recvfrom: ", (error, err), " (action: ignore)");
}
break;
case STATE_REQUESTING:
@@ -803,8 +823,12 @@ static void dhcp_client_setstate(struct dhcp_client *client,
/* ignore */
}
break;
+ case E_POSIX_ENETDOWN:
+ log_errorln("error: recvfrom: ", (error, err), " (action: reset to state=INIT)");
+ dhcp_client_setstate(client, STATE_INIT, 0, NULL, scratch_msg);
+ break;
default:
- log_debugln("error: recvfrom: ", (error, err));
+ log_errorln("error: recvfrom: ", (error, err), " (action: ignore)");
}
break;
case STATE_BOUND:
@@ -814,10 +838,15 @@ static void dhcp_client_setstate(struct dhcp_client *client,
/* discard */
break;
case E_NET_ERECV_TIMEOUT:
+ /* Not logging the error here is intentional. */
dhcp_client_setstate(client, STATE_RENEWING, DHCP_MSGTYP_REQUEST, NULL, scratch_msg);
break;
+ case E_POSIX_ENETDOWN:
+ log_errorln("error: recvfrom: ", (error, err), " (action: reset to state=INIT)");
+ dhcp_client_setstate(client, STATE_INIT, 0, NULL, scratch_msg);
+ break;
default:
- log_debugln("error: recvfrom: ", (error, err));
+ log_errorln("error: recvfrom: ", (error, err), " (action: ignore)");
}
break;
case STATE_RENEWING:
@@ -841,11 +870,16 @@ static void dhcp_client_setstate(struct dhcp_client *client,
}
break;
case E_NET_ERECV_TIMEOUT:
+ log_errorln("error: recvfrom: ", (error, err), " (action: forget server, set state=REBINDING)");
client->lease_server_id = net_ip4_addr_zero;
dhcp_client_setstate(client, STATE_REBINDING, DHCP_MSGTYP_REQUEST, NULL, scratch_msg);
break;
+ case E_POSIX_ENETDOWN:
+ log_errorln("error: recvfrom: ", (error, err), " (action: reset to state=INIT)");
+ dhcp_client_setstate(client, STATE_INIT, 0, NULL, scratch_msg);
+ break;
default:
- log_debugln("error: recvfrom: ", (error, err));
+ log_errorln("error: recvfrom: ", (error, err), " (action: ignore)");
}
break;
case STATE_REBINDING:
@@ -866,11 +900,15 @@ static void dhcp_client_setstate(struct dhcp_client *client,
}
break;
case E_NET_ERECV_TIMEOUT:
- LO_CALL(client->iface, ifcfg, (struct net_iface_config){});
- dhcp_client_setstate(client, STATE_BOUND, 0, NULL, scratch_msg);
+ log_errorln("error: recvfrom: ", (error, err), " (action: reset to state=INIT)");
+ dhcp_client_setstate(client, STATE_INIT, 0, NULL, scratch_msg);
+ break;
+ case E_POSIX_ENETDOWN:
+ log_errorln("error: recvfrom: ", (error, err), " (action: reset to state=INIT)");
+ dhcp_client_setstate(client, STATE_INIT, 0, NULL, scratch_msg);
break;
default:
- log_debugln("error: recvfrom: ", (error, err));
+ log_errorln("error: recvfrom: ", (error, err), " (action: ignore)");
}
break;
case STATE_INIT_REBOOT:
diff --git a/libdhcp/tests/test_client.c b/libdhcp/tests/test_client.c
index 772d778..0112e76 100644
--- a/libdhcp/tests/test_client.c
+++ b/libdhcp/tests/test_client.c
@@ -99,6 +99,12 @@ static void test_ifcfg(struct test_iface *LM_UNUSED(self), struct net_iface_conf
cr_exit();
}
+static bool test_is_link_up(struct test_iface *LM_UNUSED(self)) {
+ return true;
+}
+
+static void test_wait_for_link_up(struct test_iface *LM_UNUSED(self)) {}
+
static bool test_arp_ping(struct test_iface *LM_UNUSED(self), struct net_ip4_addr LM_UNUSED(addr)) {
return false;
}