|
@@ -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;
|
|
|
}
|
|
|
|
|
|
|