Add QCA vendor attribute and event to indicate subnet change status
authorRavi Joshi <ravij@qca.qualcomm.com>
Mon, 16 Nov 2015 06:05:05 +0000 (22:05 -0800)
committerJouni Malinen <j@w1.fi>
Fri, 20 Nov 2015 09:03:06 +0000 (11:03 +0200)
This allows offloaded roaming to inform user space of the change in IP
subnet post roaming. The device may have roamed to a network which is in
a different subnet which will result in IP connectivity loss. Indicating
the change in subnet enables the user space to refresh the IP address or
to perform IP subnet validation if unknown status is indicated.

The driver indication is reported with a new event from wpa_supplicant
in the following format:
CTRL-EVENT-SUBNET-STATUS-UPDATE status=<0/1/2>
where
0 = unknown
1 = IP subnet unchanged (can continue to use the old IP address)
2 = IP subnet changed (need to get a new IP address)

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
src/common/wpa_ctrl.h
src/drivers/driver.h
src/drivers/driver_nl80211_event.c
wpa_supplicant/events.c

index 3de4682..3e0a7ec 100644 (file)
@@ -77,6 +77,19 @@ extern "C" {
 /** Regulatory domain channel */
 #define WPA_EVENT_REGDOM_CHANGE "CTRL-EVENT-REGDOM-CHANGE "
 
+/** IP subnet status change notification
+ *
+ * When using an offloaded roaming mechanism where driver/firmware takes care
+ * of roaming and IP subnet validation checks post-roaming, this event can
+ * indicate whether IP subnet has changed.
+ *
+ * The event has a status=<0/1/2> parameter where
+ * 0 = unknown
+ * 1 = IP subnet unchanged (can continue to use the old IP address)
+ * 2 = IP subnet changed (need to get a new IP address)
+ */
+#define WPA_EVENT_SUBNET_STATUS_UPDATE "CTRL-EVENT-SUBNET-STATUS-UPDATE "
+
 /** RSN IBSS 4-way handshakes completed with specified peer */
 #define IBSS_RSN_COMPLETED "IBSS-RSN-COMPLETED "
 
index 09c4fa1..1ed2320 100644 (file)
@@ -4106,6 +4106,12 @@ union wpa_event_data {
                 * ptk_kek_len - The length of ptk_kek
                 */
                size_t ptk_kek_len;
+
+               /**
+                * subnet_status - The subnet status:
+                * 0 = unknown, 1 = unchanged, 2 = changed
+                */
+               u8 subnet_status;
        } assoc_info;
 
        /**
index 721b1b9..e8cdeeb 100644 (file)
@@ -268,7 +268,8 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
                               struct nlattr *authorized,
                               struct nlattr *key_replay_ctr,
                               struct nlattr *ptk_kck,
-                              struct nlattr *ptk_kek)
+                              struct nlattr *ptk_kek,
+                              struct nlattr *subnet_status)
 {
        union wpa_event_data event;
        const u8 *ssid;
@@ -367,6 +368,17 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
                event.assoc_info.ptk_kek_len = nla_len(ptk_kek);
        }
 
+       if (subnet_status) {
+               /*
+                * At least for now, this is only available from
+                * QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS and that
+                * attribute has the same values 0, 1, 2 as are used in the
+                * variable here, so no mapping between different values are
+                * needed.
+                */
+               event.assoc_info.subnet_status = nla_get_u8(subnet_status);
+       }
+
        wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
 }
 
@@ -1600,7 +1612,8 @@ static void qca_nl80211_key_mgmt_auth(struct wpa_driver_nl80211_data *drv,
                           tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED],
                           tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR],
                           tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK],
-                          tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK]);
+                          tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK],
+                          tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS]);
 }
 
 
@@ -2084,7 +2097,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
                                   tb[NL80211_ATTR_MAC],
                                   tb[NL80211_ATTR_REQ_IE],
                                   tb[NL80211_ATTR_RESP_IE],
-                                  NULL, NULL, NULL, NULL);
+                                  NULL, NULL, NULL, NULL, NULL);
                break;
        case NL80211_CMD_CH_SWITCH_NOTIFY:
                mlme_event_ch_switch(drv,
index 9bd791b..547aa98 100644 (file)
@@ -3256,6 +3256,11 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                wpa_supplicant_event_assoc(wpa_s, data);
                if (data && data->assoc_info.authorized)
                        wpa_supplicant_event_assoc_auth(wpa_s, data);
+               if (data) {
+                       wpa_msg(wpa_s, MSG_INFO,
+                               WPA_EVENT_SUBNET_STATUS_UPDATE "status=%u",
+                               data->assoc_info.subnet_status);
+               }
                break;
        case EVENT_DISASSOC:
                wpas_event_disassoc(wpa_s,