|
Description
|
As part of 4354207, the DHCP client was changed to bring the interface
IFF_UP in open_ip_lif() (rather than configure_v4_lease()) so that
broadcast traffic could immediately be sent and received over the
interface. In principle this is fine, but an oversight was made in the
implementation: lif_flags (which shadows the current interface flags)
was never updated. As a result, after this:
/*
* Start from a clean slate.
*/
canonize_lif(lif, B_FALSE);
lifr.lifr_flags |= IFF_UP;
if (ioctl(v4_sock_fd, SIOCSLIFFLAGS, &lifr) == -1) {
errmsg = "cannot bring up";
goto failure;
}
SIOCGLIFFLAGS will include IFF_UP, but lif_flags will not. Thus, any
calls to verify_lif() will hit this test and abandon the interface:
if ((lif->lif_flags ^ lifr.lifr_flags) & IFF_UP) {
dhcpmsg(MSG_DEBUG, "verify_lif: user has %s %s",
lifr.lifr_flags & IFF_UP ? "started up" : "shut down",
lif->lif_name);
return (B_FALSE);
}
In general, this doesn't occur because shortly after calling open_ip_lif(),
we call set_lif_dhcp() which reloads lif_flags. However, in the paths where
that (or other similar reloads) do not occur, we'll eventually run afoul of
the check in verify_lif().
On a related note, the following code is still in configure_v4_lease():
if (ioctl(v4_sock_fd, SIOCGLIFFLAGS, &lifr) == -1) {
dhcpmsg(MSG_ERR, "configure_v4_lease: cannot get interface "
"flags for %s", lif->lif_name);
return (B_FALSE);
}
lifr.lifr_flags |= IFF_UP;
if (ioctl(v4_sock_fd, SIOCSLIFFLAGS, &lifr) == -1) {
dhcpmsg(MSG_ERR, "configure_v4_lease: cannot set interface "
"flags for %s", lif->lif_name);
return (B_FALSE);
}
lif->lif_flags = lifr.lifr_flags;
Since IFF_UP is now set as part of open_ip_lif(), this code is no longer
necessary and should be removed.
|