Bug 9061 - udhcpc: quick renew and release when link is down doesn't call script to deconfig
Summary: udhcpc: quick renew and release when link is down doesn't call script to deco...
Status: RESOLVED FIXED
Alias: None
Product: Busybox
Classification: Unclassified
Component: Networking (show other bugs)
Version: unspecified
Hardware: All Linux
: P5 normal
Target Milestone: ---
Assignee: unassigned
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-07-01 22:03 UTC by Bin Guo
Modified: 2016-07-04 15:46 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Bin Guo 2016-07-01 22:03:56 UTC
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;
}
Comment 1 Denys Vlasenko 2016-07-03 18:29:13 UTC
Fixed in git, thanks!