rfkill: Use rtnetlink ifup/ifdown events
authorJouni Malinen <j@w1.fi>
Mon, 31 May 2010 15:00:27 +0000 (18:00 +0300)
committerJouni Malinen <j@w1.fi>
Mon, 31 May 2010 15:52:17 +0000 (18:52 +0300)
Replace use of rfkill block event with rtnetlink ifdown. This makes
the design more robust since the rfkill event could have been for
another interface while the rtnetlink events are already filtered
based of ifindex. In addition, the new design handles other than
rfkill-triggered ifdown/ifup events, too. rfkill unblocked event
is still needed to try to set the interface back up. If the unblock
was for another interface, ifup will fail and the driver state is
not changed.

src/drivers/driver_nl80211.c
src/drivers/driver_wext.c
src/drivers/driver_wext.h

index 2b7462b..39c1d2d 100644 (file)
@@ -73,6 +73,7 @@ struct wpa_driver_nl80211_data {
        char brname[IFNAMSIZ];
        int ifindex;
        int if_removed;
+       int if_disabled;
        struct rfkill_data *rfkill;
        struct wpa_driver_capa capa;
        int has_capability;
@@ -413,6 +414,19 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
                   (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
                   (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
                   (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
+
+       if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {
+               wpa_printf(MSG_DEBUG, "nl80211: Interface down");
+               drv->if_disabled = 1;
+               wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, NULL);
+       }
+
+       if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) {
+               wpa_printf(MSG_DEBUG, "nl80211: Interface up");
+               drv->if_disabled = 0;
+               wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, NULL);
+       }
+
        /*
         * Some drivers send the association event before the operup event--in
         * this case, lifting operstate in wpa_driver_nl80211_set_operstate()
@@ -1351,9 +1365,11 @@ err1:
 
 static void wpa_driver_nl80211_rfkill_blocked(void *ctx)
 {
-       struct wpa_driver_nl80211_data *drv = ctx;
        wpa_printf(MSG_DEBUG, "nl80211: RFKILL blocked");
-       wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, NULL);
+       /*
+        * This may be for any interface; use ifdown event to disable
+        * interface.
+        */
 }
 
 
@@ -1366,7 +1382,7 @@ static void wpa_driver_nl80211_rfkill_unblocked(void *ctx)
                           "after rfkill unblock");
                return;
        }
-       wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, NULL);
+       /* rtnetlink ifup handler will report interface as enabled */
 }
 
 
@@ -1524,6 +1540,7 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv)
                        wpa_printf(MSG_DEBUG, "nl80211: Could not yet enable "
                                   "interface '%s' due to rfkill",
                                   bss->ifname);
+                       drv->if_disabled = 1;
                        send_rfkill_event = 1;
                } else {
                        wpa_printf(MSG_ERROR, "nl80211: Could not set "
index 2223783..d3629dd 100644 (file)
@@ -635,6 +635,19 @@ static void wpa_driver_wext_event_rtm_newlink(void *ctx, struct ifinfomsg *ifi,
                   (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
                   (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
                   (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
+
+       if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {
+               wpa_printf(MSG_DEBUG, "WEXT: Interface down");
+               drv->if_disabled = 1;
+               wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, NULL);
+       }
+
+       if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) {
+               wpa_printf(MSG_DEBUG, "WEXT: Interface up");
+               drv->if_disabled = 0;
+               wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, NULL);
+       }
+
        /*
         * Some drivers send the association event before the operup event--in
         * this case, lifting operstate in wpa_driver_wext_set_operstate()
@@ -690,9 +703,11 @@ static void wpa_driver_wext_event_rtm_dellink(void *ctx, struct ifinfomsg *ifi,
 
 static void wpa_driver_wext_rfkill_blocked(void *ctx)
 {
-       struct wpa_driver_wext_data *drv = ctx;
        wpa_printf(MSG_DEBUG, "WEXT: RFKILL blocked");
-       wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, NULL);
+       /*
+        * This may be for any interface; use ifdown event to disable
+        * interface.
+        */
 }
 
 
@@ -705,7 +720,7 @@ static void wpa_driver_wext_rfkill_unblocked(void *ctx)
                           "after rfkill unblock");
                return;
        }
-       wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, NULL);
+       /* rtnetlink ifup handler will report interface as enabled */
 }
 
 
@@ -802,6 +817,7 @@ static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv)
                        wpa_printf(MSG_DEBUG, "WEXT: Could not yet enable "
                                   "interface '%s' due to rfkill",
                                   drv->ifname);
+                       drv->if_disabled = 1;
                        send_rfkill_event = 1;
                } else {
                        wpa_printf(MSG_ERROR, "WEXT: Could not set "
index 22d26a6..9176dd8 100644 (file)
@@ -26,6 +26,7 @@ struct wpa_driver_wext_data {
        int ifindex;
        int ifindex2;
        int if_removed;
+       int if_disabled;
        struct rfkill_data *rfkill;
        u8 *assoc_req_ies;
        size_t assoc_req_ies_len;