aboutsummaryrefslogtreecommitdiffstats
path: root/src/drivers/driver_wext.c
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2008-07-24 22:30:53 (GMT)
committerJouni Malinen <j@w1.fi>2008-07-24 22:30:53 (GMT)
commit3fbda8f943fff3e8afd649663bdcbba9cbfd6ee3 (patch)
tree4e94225fd4ac4b687218a8d55297a113459ddc7e /src/drivers/driver_wext.c
parent27e120c46d21065ad22692fe69b1944ce73088b6 (diff)
downloadhostap-3fbda8f943fff3e8afd649663bdcbba9cbfd6ee3.zip
hostap-3fbda8f943fff3e8afd649663bdcbba9cbfd6ee3.tar.gz
hostap-3fbda8f943fff3e8afd649663bdcbba9cbfd6ee3.tar.bz2
WEXT: Fixed re-initialization of removed and re-inserted interface
Network device ifindex will change when the interface is re-inserted. driver_wext.c will need to accept netlink events from "unknown" (based on ifindex) interfaces when a previously used card was removed earlier. If the previously removed interface is added back, the driver_wext data need to be updated to match with the new ifindex value. In addition, the initial setup tasks for the card (set interface up, update ifindex, set mode, etc.) from wpa_driver_wext_init() need to be run again.
Diffstat (limited to 'src/drivers/driver_wext.c')
-rw-r--r--src/drivers/driver_wext.c88
1 files changed, 78 insertions, 10 deletions
diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c
index a7f4ead..6aac427 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;
}