| Summary: | udhcpc: quick renew and release when link is down doesn't call script to deconfig | ||
|---|---|---|---|
| Product: | Busybox | Reporter: | Bin Guo <gb2312> |
| Component: | Networking | Assignee: | unassigned |
| Status: | RESOLVED FIXED | ||
| Severity: | normal | CC: | busybox-cvs |
| Priority: | P5 | ||
| Version: | unspecified | ||
| Target Milestone: | --- | ||
| Hardware: | All | ||
| OS: | Linux | ||
| Host: | Target: | ||
| Build: | |||
Fixed in git, thanks! |
Observed with 1.15.3 but looks like the code is similar: with udhcpc in BOUND=2 state, when the link goes down and external applications ask udhcpc to renew and release the address, which can be simulated by killall 1 udhpc; killall 2 udhpc then udhcpc gets into RELEASED=6 state without calling script for deconfig. This leaves ip/route still configured with link down and dhcp released. An instrumented networking/udhcp/udhcpc.c showed this trace: # link down! $ killall 1 udhpc; killall 2 udhpc Performing a DHCP renew state: 2 -> 5 Sending renew... Entering released state state: 5 -> 6 <<<<<<<<<<<<<< not calling script!!!! # ip/route still present now This shows: SIGUSR1: perform_renew(): state: BOUND=2 -> RENEW_REQUESTED=5 SIGUSR2: perform_release(): state: RENEW_REQUESTED=5 -> RELEASED=6 RENEW_REQUESTED->RELEASED would not call udhcp_run_script(NULL, "deconfig") I believe the need to call deconfig should be remembered... Related functions: /* Called only on SIGUSR1 */ static void perform_renew(void) { bb_error_msg("performing DHCP renew"); switch (state) { case BOUND: change_listen_mode(LISTEN_KERNEL); case RENEWING: case REBINDING: state = RENEW_REQUESTED; break; case RENEW_REQUESTED: /* impatient are we? fine, square 1 */ udhcp_run_script(NULL, "deconfig"); case REQUESTING: case RELEASED: change_listen_mode(LISTEN_RAW); state = INIT_SELECTING; break; case INIT_SELECTING: break; } } static void perform_release(uint32_t server_addr, uint32_t requested_ip) { char buffer[sizeof("255.255.255.255")]; struct in_addr temp_addr; /* send release packet */ if (state == BOUND || state == RENEWING || state == REBINDING) { temp_addr.s_addr = server_addr; strcpy(buffer, inet_ntoa(temp_addr)); temp_addr.s_addr = requested_ip; bb_error_msg("unicasting a release of %s to %s", inet_ntoa(temp_addr), buffer); send_release(server_addr, requested_ip); /* unicast */ udhcp_run_script(NULL, "deconfig"); } bb_error_msg("entering released state"); change_listen_mode(LISTEN_NONE); state = RELEASED; }