From 4bcbada7647f8e0225b8028461c5d0d467946c1c Mon Sep 17 00:00:00 2001 From: d00f <8052722+DrDoof@users.noreply.github.com> Date: Mon, 7 Sep 2026 22:44:51 +0200 Subject: [PATCH] dhcp: do not leave the old socket behind when starting again dhcp_start() never looked at whether DHCP was already running, and "ip dhcp" calls it without stopping first, so a second start took a fresh slot from uip_udp_conns and left the previous one bound. The leak is the smaller half of it. dhcp_callback() decides whether a call is for it by comparing the local port, not the connection, and every leftover socket still holds port 68, so each one runs the state machine on every poll. The timers live in one shared dhcp_state, so ticks count down once per socket: two starts and the retransmit and renewal timing runs at twice the intended rate. Stop the old one first. dhcp_stop() already does exactly that, and the state test keeps it away from a connection that was never created. --- dhcp.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dhcp.c b/dhcp.c index 6cfa373a..896b1473 100644 --- a/dhcp.c +++ b/dhcp.c @@ -341,6 +341,12 @@ void parse_dhcp(void) void dhcp_start(void) __banked { + /* Starting twice would leave the first socket bound: uip_udp_new() takes + * the next free slot while the old one keeps port 68, and dhcp_callback() + * matches on that port rather than on the connection, so every leftover + * runs the state machine too and the timers count down once per socket. */ + if (dhcp_state.state != DHCP_OFF) + dhcp_stop(); uip_ipaddr(server, 255,255,255,255); dhcp_state.conn = uip_udp_new(&server, HTONS(DHCPC_SERVER_PORT)); dhcp_state.current_ip[0] = dhcp_state.current_ip[1] = dhcp_state.current_ip[2] = dhcp_state.current_ip[3] = 0;