]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
nl80211: Ignore netlink interface down if interface is up
authorJouni Malinen <j@w1.fi>
Fri, 28 Oct 2011 18:08:15 +0000 (21:08 +0300)
committerJouni Malinen <j@w1.fi>
Fri, 28 Oct 2011 18:08:15 +0000 (21:08 +0300)
The netlink event processing is delayed since they are only returned
after control returns to eloop. This can result in netlink down events
being processed at a point when the interface has is actually still
there (the first event on new interface is down) and that can result in
odd behavior especially when the resulting interface-disabled event is
delivered to AP mode interface with wpa_supplicant.

Work around this by filtering netlink down events if the matching
interface is up at the time the netlink event is processed. This fixes
an issue brought up by commit 36d84860bbe09641f782fcc21b09e5a6952b4629.

src/drivers/driver_nl80211.c
src/drivers/linux_ioctl.c
src/drivers/linux_ioctl.h

index d962ac988b7cb1e87c5e2591ea51b68dde544e82..ed9681cb91fa616130c38b2f1bf8bef73f6c8747 100644 (file)
@@ -601,6 +601,14 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
                   (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
 
        if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {
+               char namebuf[IFNAMSIZ];
+               if (if_indextoname(ifi->ifi_index, namebuf) &&
+                   linux_iface_up(drv->global->ioctl_sock,
+                                  drv->first_bss.ifname) > 0) {
+                       wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
+                                  "event since interface %s is up", namebuf);
+                       return;
+               }
                wpa_printf(MSG_DEBUG, "nl80211: Interface down");
                if (drv->ignore_if_down_event) {
                        wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
index 3f7ee291dedc714f7cb0232a1c3bb08a03ba76e6..d7501cf047bb48d540a4861d062712ee2f40c88a 100644 (file)
@@ -60,6 +60,28 @@ int linux_set_iface_flags(int sock, const char *ifname, int dev_up)
 }
 
 
+int linux_iface_up(int sock, const char *ifname)
+{
+       struct ifreq ifr;
+       int ret;
+
+       if (sock < 0)
+               return -1;
+
+       os_memset(&ifr, 0, sizeof(ifr));
+       os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
+
+       if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
+               ret = errno ? -errno : -999;
+               wpa_printf(MSG_ERROR, "Could not read interface %s flags: %s",
+                          ifname, strerror(errno));
+               return ret;
+       }
+
+       return !!(ifr.ifr_flags & IFF_UP);
+}
+
+
 int linux_get_ifhwaddr(int sock, const char *ifname, u8 *addr)
 {
        struct ifreq ifr;
index a5557383d8fe193987f9143a4e47098f040990ce..e0bf673bcec7e668089bc01443a75edb530c9bde 100644 (file)
@@ -16,6 +16,7 @@
 #define LINUX_IOCTL_H
 
 int linux_set_iface_flags(int sock, const char *ifname, int dev_up);
+int linux_iface_up(int sock, const char *ifname);
 int linux_get_ifhwaddr(int sock, const char *ifname, u8 *addr);
 int linux_set_ifhwaddr(int sock, const char *ifname, const u8 *addr);
 int linux_br_add(int sock, const char *brname);