Correct problems with handling interfaces that go away (e.g. when

a card is ejected).  wpa_supplicant requires that internal events
for interfaces coming+going include a name but after an interface
is removed you cannot use if_indextoname to map the interface index
in the RTM_IFINFO (or RTM_IFANNOUNCE) msg to an interface name.
Instead record the interface index in the driver-private data area
and use that to filter msgs from the routing socket.  This insures
that when we have a message to process we know the interface name.
The end result is that we can now dispatch an "interface removed"
event that is understood when notified than an interface went away
(where previously the event dispatched was ignored because the
interface name was unrecognized).

This change also insures we only process events for our interface.

The only downside is that we can no longer wait for an interface
to arrive as we need to map the interface name to an index at
startup.  This is not important as wpa_supplicant should be launched
by devd and not include a separate mechanism for doing interface
discovery.

MFC after:	3 days
This commit is contained in:
sam 2005-07-29 05:57:28 +00:00
parent 5bf3752adf
commit 2626cf3b71

View File

@ -39,6 +39,7 @@ struct wpa_driver_bsd_data {
int sock; /* open socket for 802.11 ioctls */
int route; /* routing socket for events */
char ifname[IFNAMSIZ+1]; /* interface name */
unsigned int ifindex; /* interface index */
void *ctx;
};
@ -420,6 +421,7 @@ wpa_driver_bsd_scan(void *priv, const u8 *ssid, size_t ssid_len)
static void
wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
{
struct wpa_driver_bsd_data *drv = sock_ctx;
char buf[2048];
struct if_announcemsghdr *ifan;
struct if_msghdr *ifm;
@ -441,17 +443,15 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
"understood\n", rtm->rtm_version);
return;
}
memset(&event, 0, sizeof(event));
switch (rtm->rtm_type) {
case RTM_IFANNOUNCE:
ifan = (struct if_announcemsghdr *) rtm;
memset(&event, 0, sizeof(event));
/* XXX name buffer must be >= IFNAMSIZ */
/* XXX check return value */
if_indextoname(ifan->ifan_index, event.interface_status.ifname);
switch (ifan->ifan_what) {
case IFAN_ARRIVAL:
event.interface_status.ievent = EVENT_INTERFACE_ADDED;
if (ifan->ifan_index != drv->ifindex)
break;
strlcpy(event.interface_status.ifname, drv->ifname,
sizeof(event.interface_status.ifname));
switch (ifan->ifan_what) {
case IFAN_DEPARTURE:
event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
default:
@ -465,6 +465,8 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
break;
case RTM_IEEE80211:
ifan = (struct if_announcemsghdr *) rtm;
if (ifan->ifan_index != drv->ifindex)
break;
switch (ifan->ifan_what) {
case RTM_IEEE80211_ASSOC:
case RTM_IEEE80211_REASSOC:
@ -496,9 +498,11 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
break;
case RTM_IFINFO:
ifm = (struct if_msghdr *) rtm;
if (ifm->ifm_index != drv->ifindex)
break;
if ((rtm->rtm_flags & RTF_UP) == 0) {
if_indextoname(ifm->ifm_index,
event.interface_status.ifname);
strlcpy(event.interface_status.ifname, drv->ifname,
sizeof(event.interface_status.ifname));
event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN",
event.interface_status.ifname);
@ -646,6 +650,18 @@ wpa_driver_bsd_init(void *ctx, const char *ifname)
if (drv == NULL)
return NULL;
memset(drv, 0, sizeof(*drv));
/*
* NB: We require the interface name be mappable to an index.
* This implies we do not support having wpa_supplicant
* wait for an interface to appear. This seems ok; that
* doesn't belong here; it's really the job of devd.
*/
drv->ifindex = if_nametoindex(ifname);
if (drv->ifindex == 0) {
wpa_printf(MSG_DEBUG, "%s: interface %s does not exist",
__func__, ifname);
goto fail1;
}
drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
if (drv->sock < 0)
goto fail1;
@ -653,7 +669,7 @@ wpa_driver_bsd_init(void *ctx, const char *ifname)
if (drv->route < 0)
goto fail;
eloop_register_read_sock(drv->route,
wpa_driver_bsd_event_receive, ctx, NULL);
wpa_driver_bsd_event_receive, ctx, drv);
drv->ctx = ctx;
strncpy(drv->ifname, ifname, sizeof(drv->ifname));