diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c index a7f4ead5d..6aac4276a 100644 --- a/src/drivers/driver_wext.c +++ b/src/drivers/driver_wext.c @@ -154,6 +154,8 @@ enum { static int wpa_driver_wext_flush_pmkid(void *priv); static int wpa_driver_wext_get_range(void *priv); +static void wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv); + static int wpa_driver_wext_send_oper_ifla(struct wpa_driver_wext_data *drv, int linkmode, int operstate) @@ -689,7 +691,8 @@ static void wpa_driver_wext_event_wireless(struct wpa_driver_wext_data *drv, } -static void wpa_driver_wext_event_link(void *ctx, char *buf, size_t len, +static void wpa_driver_wext_event_link(struct wpa_driver_wext_data *drv, + void *ctx, char *buf, size_t len, int del) { union wpa_event_data event; @@ -706,10 +709,68 @@ static void wpa_driver_wext_event_link(void *ctx, char *buf, size_t len, event.interface_status.ifname, del ? "removed" : "added"); + if (os_strcmp(drv->ifname, event.interface_status.ifname) == 0) { + if (del) + drv->if_removed = 1; + else + drv->if_removed = 0; + } + wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event); } +static int wpa_driver_wext_own_ifname(struct wpa_driver_wext_data *drv, + struct nlmsghdr *h) +{ + struct ifinfomsg *ifi; + int attrlen, nlmsg_len, rta_len; + struct rtattr *attr; + + ifi = NLMSG_DATA(h); + + nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); + + attrlen = h->nlmsg_len - nlmsg_len; + if (attrlen < 0) + return 0; + + attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); + + rta_len = RTA_ALIGN(sizeof(struct rtattr)); + while (RTA_OK(attr, attrlen)) { + if (attr->rta_type == IFLA_IFNAME) { + if (os_strcmp(((char *) attr) + rta_len, drv->ifname) + == 0) + return 1; + else + break; + } + attr = RTA_NEXT(attr, attrlen); + } + + return 0; +} + + +static int wpa_driver_wext_own_ifindex(struct wpa_driver_wext_data *drv, + int ifindex, struct nlmsghdr *h) +{ + if (drv->ifindex == ifindex || drv->ifindex2 == ifindex) + return 1; + + if (drv->if_removed && wpa_driver_wext_own_ifname(drv, h)) { + drv->ifindex = if_nametoindex(drv->ifname); + wpa_printf(MSG_DEBUG, "WEXT: Update ifindex for a removed " + "interface"); + wpa_driver_wext_finish_drv_init(drv); + return 1; + } + + return 0; +} + + static void wpa_driver_wext_event_rtm_newlink(struct wpa_driver_wext_data *drv, void *ctx, struct nlmsghdr *h, size_t len) @@ -723,8 +784,7 @@ static void wpa_driver_wext_event_rtm_newlink(struct wpa_driver_wext_data *drv, ifi = NLMSG_DATA(h); - if (drv->ifindex != ifi->ifi_index && drv->ifindex2 != ifi->ifi_index) - { + if (!wpa_driver_wext_own_ifindex(drv, ifi->ifi_index, h)) { wpa_printf(MSG_DEBUG, "Ignore event for foreign ifindex %d", ifi->ifi_index); return; @@ -763,7 +823,7 @@ static void wpa_driver_wext_event_rtm_newlink(struct wpa_driver_wext_data *drv, drv, ctx, ((char *) attr) + rta_len, attr->rta_len - rta_len); } else if (attr->rta_type == IFLA_IFNAME) { - wpa_driver_wext_event_link(ctx, + wpa_driver_wext_event_link(drv, ctx, ((char *) attr) + rta_len, attr->rta_len - rta_len, 0); } @@ -796,7 +856,7 @@ static void wpa_driver_wext_event_rtm_dellink(struct wpa_driver_wext_data *drv, rta_len = RTA_ALIGN(sizeof(struct rtattr)); while (RTA_OK(attr, attrlen)) { if (attr->rta_type == IFLA_IFNAME) { - wpa_driver_wext_event_link(ctx, + wpa_driver_wext_event_link(drv, ctx, ((char *) attr) + rta_len, attr->rta_len - rta_len, 1); } @@ -977,7 +1037,7 @@ int wpa_driver_wext_set_ifflags(struct wpa_driver_wext_data *drv, int flags) */ void * wpa_driver_wext_init(void *ctx, const char *ifname) { - int s, flags; + int s; struct sockaddr_nl local; struct wpa_driver_wext_data *drv; @@ -1018,6 +1078,16 @@ void * wpa_driver_wext_init(void *ctx, const char *ifname) drv->mlme_sock = -1; + wpa_driver_wext_finish_drv_init(drv); + + return drv; +} + + +static void wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv) +{ + int flags; + if (wpa_driver_wext_get_ifflags(drv, &flags) != 0) printf("Could not get interface '%s' flags\n", drv->ifname); else if (!(flags & IFF_UP)) { @@ -1051,7 +1121,7 @@ void * wpa_driver_wext_init(void *ctx, const char *ifname) drv->ifindex = if_nametoindex(drv->ifname); - if (os_strncmp(ifname, "wlan", 4) == 0) { + if (os_strncmp(drv->ifname, "wlan", 4) == 0) { /* * Host AP driver may use both wlan# and wifi# interface in * wireless events. Since some of the versions included WE-18 @@ -1061,14 +1131,12 @@ void * wpa_driver_wext_init(void *ctx, const char *ifname) * driver are not in use anymore. */ char ifname2[IFNAMSIZ + 1]; - os_strlcpy(ifname2, ifname, sizeof(ifname2)); + os_strlcpy(ifname2, drv->ifname, sizeof(ifname2)); os_memcpy(ifname2, "wifi", 4); wpa_driver_wext_alternative_ifindex(drv, ifname2); } wpa_driver_wext_send_oper_ifla(drv, 1, IF_OPER_DORMANT); - - return drv; } diff --git a/src/drivers/driver_wext.h b/src/drivers/driver_wext.h index 590c1e156..b89c2cb2f 100644 --- a/src/drivers/driver_wext.h +++ b/src/drivers/driver_wext.h @@ -25,6 +25,7 @@ struct wpa_driver_wext_data { char ifname[IFNAMSIZ + 1]; int ifindex; int ifindex2; + int if_removed; u8 *assoc_req_ies; size_t assoc_req_ies_len; u8 *assoc_resp_ies;