aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2011-10-28 18:08:15 (GMT)
committerJouni Malinen <j@w1.fi>2011-10-28 18:08:15 (GMT)
commit59d249255c5ea484ac2050f19ecbe84a7d9323f0 (patch)
treeb64f887be96a00c0a45419ff2e0a402516405847
parentd28b43f66f91c28c9fdefdfc17f006a418462bc4 (diff)
downloadhostap-59d249255c5ea484ac2050f19ecbe84a7d9323f0.zip
hostap-59d249255c5ea484ac2050f19ecbe84a7d9323f0.tar.gz
hostap-59d249255c5ea484ac2050f19ecbe84a7d9323f0.tar.bz2
nl80211: Ignore netlink interface down if interface is up
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.
-rw-r--r--src/drivers/driver_nl80211.c8
-rw-r--r--src/drivers/linux_ioctl.c22
-rw-r--r--src/drivers/linux_ioctl.h1
3 files changed, 31 insertions, 0 deletions
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index d962ac9..ed9681c 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -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 "
diff --git a/src/drivers/linux_ioctl.c b/src/drivers/linux_ioctl.c
index 3f7ee29..d7501cf 100644
--- a/src/drivers/linux_ioctl.c
+++ b/src/drivers/linux_ioctl.c
@@ -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;
diff --git a/src/drivers/linux_ioctl.h b/src/drivers/linux_ioctl.h
index a555738..e0bf673 100644
--- a/src/drivers/linux_ioctl.h
+++ b/src/drivers/linux_ioctl.h
@@ -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);