Change netlink event handling so that the DHCP client will sleep if the

interface carrier is lost or the interface is deconfigured but still exists,
eg via ifconfig down.  If the hardware is removed, then ndhcp will exit.
This commit is contained in:
Nicholas J. Kain 2011-07-02 01:51:32 -04:00
parent 17570e9a38
commit 7104b56ab9

View File

@ -72,9 +72,9 @@ int nl_open(struct client_state_t *cs)
return -1;
}
static void takedown_if(struct client_state_t *cs)
static void restart_if(struct client_state_t *cs)
{
log_line("nl: taking down interface");
log_line("nl: %s back, querying for new lease", client_config.interface);
// XXX: Same as packet.c - merge somehow?
ifchange(NULL, IFCHANGE_DECONFIG);
cs->dhcpState = DS_SELECTING;
@ -84,6 +84,14 @@ static void takedown_if(struct client_state_t *cs)
set_listen_raw(cs);
}
static void sleep_if(struct client_state_t *cs)
{
arp_close_fd(cs);
set_listen_none(cs);
cs->dhcpState = DS_RELEASED;
cs->timeout = -1;
}
static int data_attr_cb(const struct nlattr *attr, void *data)
{
const struct nlattr **tb = data;
@ -135,8 +143,6 @@ static void get_if_index_and_mac(const struct nlmsghdr *nlh,
}
}
// XXX: Rather than exit, go into RELEASE state until a new hardware event
// forces wakeup.
static int data_cb(const struct nlmsghdr *nlh, void *data)
{
struct nlattr *tb[IFLA_MAX+1] = {0};
@ -149,7 +155,9 @@ static int data_cb(const struct nlmsghdr *nlh, void *data)
get_if_index_and_mac(nlh, ifm, (const struct nlattr **)tb);
if (ifm->ifi_index != client_config.ifindex)
break;
// IFF_UP corresponds to ifconfig down or ifconfig up.
if (ifm->ifi_flags & IFF_UP) {
// IFF_RUNNING is the hardware carrier.
if (ifm->ifi_flags & IFF_RUNNING) {
if (cs->ifsPrevState != IFS_UP) {
cs->ifsPrevState = IFS_UP;
@ -162,25 +170,23 @@ static int data_cb(const struct nlmsghdr *nlh, void *data)
else
log_line("nl: interface back, revalidating lease");
// If we don't have a lease, state -> SELECTING.
} else if (cs->dhcpState != DS_SELECTING) {
log_line("nl: interface back, querying for new lease");
takedown_if(cs);
}
}
} else {
if (cs->ifsPrevState != IFS_DOWN) {
// Interface was marked up but not running.
// Get a new lease from scratch.
cs->ifsPrevState = IFS_DOWN;
takedown_if(cs);
}
} else if (cs->dhcpState != DS_SELECTING)
restart_if(cs);
}
} else {
// No hardware carrier.
if (cs->ifsPrevState != IFS_DOWN) {
log_line("Interface carrier down. Going to sleep.");
cs->ifsPrevState = IFS_DOWN;
sleep_if(cs);
}
}
} else {
// User shut down the interface.
if (cs->ifsPrevState != IFS_SHUT) {
log_line("Interface shut down. Going to sleep.");
cs->ifsPrevState = IFS_SHUT;
log_line("Interface shut down; exiting.");
exit(EXIT_SUCCESS);
sleep_if(cs);
}
}
break;