@@ -917,4 +917,12 @@ static inline int wpa_drv_abort_scan(struct wpa_supplicant *wpa_s)
return wpa_s->driver->abort_scan(wpa_s->drv_priv);
}
+static inline int wpa_drv_configure_frame_filters(struct wpa_supplicant *wpa_s,
+ u32 filters)
+{
+ if (!wpa_s->driver->configure_data_frame_filters)
+ return -1;
+ return wpa_s->driver->configure_data_frame_filters(wpa_s->drv_priv,
+ filters);
+}
#endif /* DRIVER_I_H */
@@ -60,6 +60,46 @@ struct osu_provider {
size_t icon_count;
};
+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 (!is_hs20_network(wpa_s, wpa_s->current_ssid, bss)) {
+ wpa_printf(MSG_DEBUG,
+ "Not configuring frame filtering - bss "
+ MACSTR " is not a HS network\n", 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\n");
+ 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 - Cant extract proxy ARP bit\n");
+ 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;
+
+ if (filter)
+ wpa_drv_configure_frame_filters(wpa_s, filter);
+}
+
void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id)
{
@@ -8,6 +8,7 @@
#ifndef 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);
int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes,
@@ -751,6 +751,9 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
wpas_connect_work_done(wpa_s);
/* Reinitialize normal_scan counter */
wpa_s->normal_scans = 0;
+#ifdef CONFIG_HS20
+ hs20_configure_frame_filters(wpa_s);
+#endif /* CONFIG_HS20 */
}
#ifdef CONFIG_P2P
@@ -816,8 +819,15 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_BGSCAN
if (state == WPA_COMPLETED)
wpa_supplicant_start_bgscan(wpa_s);
- else if (state < WPA_ASSOCIATED)
+ else if (state < WPA_ASSOCIATED) {
wpa_supplicant_stop_bgscan(wpa_s);
+
+#ifdef CONFIG_HS20
+ /* clear possibly configured frame filters */
+ if (old_state == WPA_COMPLETED)
+ wpa_drv_configure_frame_filters(wpa_s, 0);
+#endif /* CONFIG_HS20 */
+ }
#endif /* CONFIG_BGSCAN */
if (state == WPA_AUTHENTICATING)