Add QCA vendor attribute and event to indicate subnet change status

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>
This commit is contained in:
Ravi Joshi 2015-11-15 22:05:05 -08:00 committed by Jouni Malinen
parent 6fb8b4bf84
commit f32227ed9e
4 changed files with 40 additions and 3 deletions

View file

@ -77,6 +77,19 @@ extern "C" {
/** Regulatory domain channel */ /** Regulatory domain channel */
#define WPA_EVENT_REGDOM_CHANGE "CTRL-EVENT-REGDOM-CHANGE " #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 */ /** RSN IBSS 4-way handshakes completed with specified peer */
#define IBSS_RSN_COMPLETED "IBSS-RSN-COMPLETED " #define IBSS_RSN_COMPLETED "IBSS-RSN-COMPLETED "

View file

@ -4106,6 +4106,12 @@ union wpa_event_data {
* ptk_kek_len - The length of ptk_kek * ptk_kek_len - The length of ptk_kek
*/ */
size_t ptk_kek_len; size_t ptk_kek_len;
/**
* subnet_status - The subnet status:
* 0 = unknown, 1 = unchanged, 2 = changed
*/
u8 subnet_status;
} assoc_info; } assoc_info;
/** /**

View file

@ -268,7 +268,8 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
struct nlattr *authorized, struct nlattr *authorized,
struct nlattr *key_replay_ctr, struct nlattr *key_replay_ctr,
struct nlattr *ptk_kck, struct nlattr *ptk_kck,
struct nlattr *ptk_kek) struct nlattr *ptk_kek,
struct nlattr *subnet_status)
{ {
union wpa_event_data event; union wpa_event_data event;
const u8 *ssid; 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); 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); 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_AUTHORIZED],
tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR], 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_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_MAC],
tb[NL80211_ATTR_REQ_IE], tb[NL80211_ATTR_REQ_IE],
tb[NL80211_ATTR_RESP_IE], tb[NL80211_ATTR_RESP_IE],
NULL, NULL, NULL, NULL); NULL, NULL, NULL, NULL, NULL);
break; break;
case NL80211_CMD_CH_SWITCH_NOTIFY: case NL80211_CMD_CH_SWITCH_NOTIFY:
mlme_event_ch_switch(drv, mlme_event_ch_switch(drv,

View file

@ -3256,6 +3256,11 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
wpa_supplicant_event_assoc(wpa_s, data); wpa_supplicant_event_assoc(wpa_s, data);
if (data && data->assoc_info.authorized) if (data && data->assoc_info.authorized)
wpa_supplicant_event_assoc_auth(wpa_s, data); 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; break;
case EVENT_DISASSOC: case EVENT_DISASSOC:
wpas_event_disassoc(wpa_s, wpas_event_disassoc(wpa_s,