From 2626cf3b71f259ad793fdb031df219c6e2f1c971 Mon Sep 17 00:00:00 2001 From: sam Date: Fri, 29 Jul 2005 05:57:28 +0000 Subject: [PATCH] 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 --- usr.sbin/wpa/wpa_supplicant/driver_freebsd.c | 36 ++++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c b/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c index ed85fa28a922..65cf0f385cf6 100644 --- a/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c +++ b/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c @@ -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));