HS 2.0: Add support for configuring frame filters

When a station starts an association to a Hotspot 2.0 network, request
the driver to do the following, based on the BSS capabilities:

1. Enable gratuitous ARP filtering
2. Enable unsolicited Neighbor Advertisement filtering
3. Enable unicast IP packet encrypted with GTK filtering if
   DGAF disabled bit is zero

Clear the filter configuration when the station interface is
disassociated.

Signed-off-by: Matti Gottlieb <matti.gottlieb@intel.com>
This commit is contained in:
Matti Gottlieb 2016-04-06 17:14:41 +03:00 committed by Jouni Malinen
parent e42adb9a75
commit ece4ac5f4e
5 changed files with 61 additions and 1 deletions

View file

@ -281,6 +281,11 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
wpa_supplicant_ap_deinit(wpa_s); wpa_supplicant_ap_deinit(wpa_s);
#endif /* CONFIG_AP */ #endif /* CONFIG_AP */
#ifdef CONFIG_HS20
/* Clear possibly configured frame filters */
wpa_drv_configure_frame_filters(wpa_s, 0);
#endif /* CONFIG_HS20 */
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
return; return;

View file

@ -61,6 +61,46 @@ struct osu_provider {
}; };
void hs20_configure_frame_filters(struct wpa_supplicant *wpa_s)
{
struct wpa_bss *bss = wpa_s->current_bss;
u8 *bssid = wpa_s->bssid;
const u8 *ie;
const u8 *ext_capa;
u32 filter = 0;
if (!bss || !is_hs20_network(wpa_s, wpa_s->current_ssid, bss)) {
wpa_printf(MSG_DEBUG,
"Not configuring frame filtering - BSS " MACSTR
" is not a Hotspot 2.0 network", MAC2STR(bssid));
return;
}
ie = wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE);
/* Check if DGAF disabled bit is zero (5th byte in the IE) */
if (!ie || ie[1] < 5)
wpa_printf(MSG_DEBUG,
"Not configuring frame filtering - Can't extract DGAF bit");
else if (!(ie[6] & HS20_DGAF_DISABLED))
filter |= WPA_DATA_FRAME_FILTER_FLAG_GTK;
ext_capa = wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB);
if (!ext_capa || ext_capa[1] < 2) {
wpa_printf(MSG_DEBUG,
"Not configuring frame filtering - Can't extract Proxy ARP bit");
return;
}
/* Check if Proxy ARP is enabled (2nd byte in the IE) */
if (ext_capa[3] & BIT(4))
filter |= WPA_DATA_FRAME_FILTER_FLAG_ARP |
WPA_DATA_FRAME_FILTER_FLAG_NA;
wpa_drv_configure_frame_filters(wpa_s, filter);
}
void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id) void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id)
{ {
u8 conf; u8 conf;

View file

@ -8,6 +8,7 @@
#ifndef HS20_SUPPLICANT_H #ifndef HS20_SUPPLICANT_H
#define HS20_SUPPLICANT_H #define HS20_SUPPLICANT_H
void hs20_configure_frame_filters(struct wpa_supplicant *wpa_s);
void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id); void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id);
int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes, int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes,

View file

@ -556,6 +556,10 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
if (old_ssid != wpa_s->current_ssid) if (old_ssid != wpa_s->current_ssid)
wpas_notify_network_changed(wpa_s); wpas_notify_network_changed(wpa_s);
#ifdef CONFIG_HS20
hs20_configure_frame_filters(wpa_s);
#endif /* CONFIG_HS20 */
#ifdef CONFIG_P2P #ifdef CONFIG_P2P
/* /*
* If multi-channel concurrency is not supported, check for any * If multi-channel concurrency is not supported, check for any

View file

@ -552,6 +552,8 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
wpa_s->last_scan_res = NULL; wpa_s->last_scan_res = NULL;
#ifdef CONFIG_HS20 #ifdef CONFIG_HS20
if (wpa_s->drv_priv)
wpa_drv_configure_frame_filters(wpa_s, 0);
hs20_deinit(wpa_s); hs20_deinit(wpa_s);
#endif /* CONFIG_HS20 */ #endif /* CONFIG_HS20 */
@ -2319,6 +2321,8 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
wpa_ie_len += wpabuf_len(hs20); wpa_ie_len += wpabuf_len(hs20);
} }
wpabuf_free(hs20); wpabuf_free(hs20);
hs20_configure_frame_filters(wpa_s);
} }
} }
#endif /* CONFIG_HS20 */ #endif /* CONFIG_HS20 */
@ -2611,8 +2615,14 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
} }
old_ssid = wpa_s->current_ssid; old_ssid = wpa_s->current_ssid;
wpa_s->current_ssid = ssid; wpa_s->current_ssid = ssid;
if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set)
if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
wpa_s->current_bss = bss; wpa_s->current_bss = bss;
#ifdef CONFIG_HS20
hs20_configure_frame_filters(wpa_s);
#endif /* CONFIG_HS20 */
}
wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid); wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
wpa_supplicant_initiate_eapol(wpa_s); wpa_supplicant_initiate_eapol(wpa_s);
if (old_ssid != wpa_s->current_ssid) if (old_ssid != wpa_s->current_ssid)