aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/driver-ops.h17
-rw-r--r--net/mac80211/driver-trace.h22
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/iface.c3
-rw-r--r--net/mac80211/main.c54
-rw-r--r--net/mac80211/mlme.c34
6 files changed, 58 insertions, 74 deletions
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 965d64f68567..c33317320eee 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -89,23 +89,6 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local,
89 trace_drv_return_void(local); 89 trace_drv_return_void(local);
90} 90}
91 91
92struct in_ifaddr;
93static inline int drv_configure_arp_filter(struct ieee80211_local *local,
94 struct ieee80211_vif *vif,
95 struct in_ifaddr *ifa_list)
96{
97 int ret = 0;
98
99 might_sleep();
100
101 trace_drv_configure_arp_filter(local, vif_to_sdata(vif));
102 if (local->ops->configure_arp_filter)
103 ret = local->ops->configure_arp_filter(&local->hw, vif,
104 ifa_list);
105 trace_drv_return_int(local, ret);
106 return ret;
107}
108
109static inline u64 drv_prepare_multicast(struct ieee80211_local *local, 92static inline u64 drv_prepare_multicast(struct ieee80211_local *local,
110 struct netdev_hw_addr_list *mc_list) 93 struct netdev_hw_addr_list *mc_list)
111{ 94{
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 06444ea67bc4..8da31caff931 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -251,28 +251,6 @@ TRACE_EVENT(drv_bss_info_changed,
251 ) 251 )
252); 252);
253 253
254TRACE_EVENT(drv_configure_arp_filter,
255 TP_PROTO(struct ieee80211_local *local,
256 struct ieee80211_sub_if_data *sdata),
257
258 TP_ARGS(local, sdata),
259
260 TP_STRUCT__entry(
261 LOCAL_ENTRY
262 VIF_ENTRY
263 ),
264
265 TP_fast_assign(
266 LOCAL_ASSIGN;
267 VIF_ASSIGN;
268 ),
269
270 TP_printk(
271 VIF_PR_FMT LOCAL_PR_FMT,
272 VIF_PR_ARG, LOCAL_PR_ARG
273 )
274);
275
276TRACE_EVENT(drv_prepare_multicast, 254TRACE_EVENT(drv_prepare_multicast,
277 TP_PROTO(struct ieee80211_local *local, int mc_count), 255 TP_PROTO(struct ieee80211_local *local, int mc_count),
278 256
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index c3c2be3f8a2c..9b3c3f971d28 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -514,6 +514,8 @@ struct ieee80211_sub_if_data {
514 struct work_struct work; 514 struct work_struct work;
515 struct sk_buff_head skb_queue; 515 struct sk_buff_head skb_queue;
516 516
517 bool arp_filter_state;
518
517 /* 519 /*
518 * AP this belongs to: self in AP mode and 520 * AP this belongs to: self in AP mode and
519 * corresponding AP in VLAN mode, NULL for 521 * corresponding AP in VLAN mode, NULL for
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 490be2f3af27..910729fc18cd 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1076,6 +1076,9 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
1076 sdata->wdev.wiphy = local->hw.wiphy; 1076 sdata->wdev.wiphy = local->hw.wiphy;
1077 sdata->local = local; 1077 sdata->local = local;
1078 sdata->dev = ndev; 1078 sdata->dev = ndev;
1079#ifdef CONFIG_INET
1080 sdata->arp_filter_state = true;
1081#endif
1079 1082
1080 for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) 1083 for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
1081 skb_queue_head_init(&sdata->fragments[i].skb_list); 1084 skb_queue_head_init(&sdata->fragments[i].skb_list);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index c2e46e88f3c9..a1bf46c64b93 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -20,6 +20,7 @@
20#include <linux/rtnetlink.h> 20#include <linux/rtnetlink.h>
21#include <linux/bitmap.h> 21#include <linux/bitmap.h>
22#include <linux/pm_qos_params.h> 22#include <linux/pm_qos_params.h>
23#include <linux/inetdevice.h>
23#include <net/net_namespace.h> 24#include <net/net_namespace.h>
24#include <net/cfg80211.h> 25#include <net/cfg80211.h>
25 26
@@ -317,23 +318,6 @@ static void ieee80211_recalc_smps_work(struct work_struct *work)
317} 318}
318 319
319#ifdef CONFIG_INET 320#ifdef CONFIG_INET
320int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata)
321{
322 struct in_device *idev;
323 int ret = 0;
324
325 BUG_ON(!sdata);
326 ASSERT_RTNL();
327
328 idev = sdata->dev->ip_ptr;
329 if (!idev)
330 return 0;
331
332 ret = drv_configure_arp_filter(sdata->local, &sdata->vif,
333 idev->ifa_list);
334 return ret;
335}
336
337static int ieee80211_ifa_changed(struct notifier_block *nb, 321static int ieee80211_ifa_changed(struct notifier_block *nb,
338 unsigned long data, void *arg) 322 unsigned long data, void *arg)
339{ 323{
@@ -343,8 +327,11 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
343 ifa_notifier); 327 ifa_notifier);
344 struct net_device *ndev = ifa->ifa_dev->dev; 328 struct net_device *ndev = ifa->ifa_dev->dev;
345 struct wireless_dev *wdev = ndev->ieee80211_ptr; 329 struct wireless_dev *wdev = ndev->ieee80211_ptr;
330 struct in_device *idev;
346 struct ieee80211_sub_if_data *sdata; 331 struct ieee80211_sub_if_data *sdata;
332 struct ieee80211_bss_conf *bss_conf;
347 struct ieee80211_if_managed *ifmgd; 333 struct ieee80211_if_managed *ifmgd;
334 int c = 0;
348 335
349 if (!netif_running(ndev)) 336 if (!netif_running(ndev))
350 return NOTIFY_DONE; 337 return NOTIFY_DONE;
@@ -356,17 +343,44 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
356 if (wdev->wiphy != local->hw.wiphy) 343 if (wdev->wiphy != local->hw.wiphy)
357 return NOTIFY_DONE; 344 return NOTIFY_DONE;
358 345
359 /* We are concerned about IP addresses only when associated */
360 sdata = IEEE80211_DEV_TO_SUB_IF(ndev); 346 sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
347 bss_conf = &sdata->vif.bss_conf;
361 348
362 /* ARP filtering is only supported in managed mode */ 349 /* ARP filtering is only supported in managed mode */
363 if (sdata->vif.type != NL80211_IFTYPE_STATION) 350 if (sdata->vif.type != NL80211_IFTYPE_STATION)
364 return NOTIFY_DONE; 351 return NOTIFY_DONE;
365 352
353 idev = sdata->dev->ip_ptr;
354 if (!idev)
355 return NOTIFY_DONE;
356
366 ifmgd = &sdata->u.mgd; 357 ifmgd = &sdata->u.mgd;
367 mutex_lock(&ifmgd->mtx); 358 mutex_lock(&ifmgd->mtx);
368 if (ifmgd->associated) 359
369 ieee80211_set_arp_filter(sdata); 360 /* Copy the addresses to the bss_conf list */
361 ifa = idev->ifa_list;
362 while (c < IEEE80211_BSS_ARP_ADDR_LIST_LEN && ifa) {
363 bss_conf->arp_addr_list[c] = ifa->ifa_address;
364 ifa = ifa->ifa_next;
365 c++;
366 }
367
368 /* If not all addresses fit the list, disable filtering */
369 if (ifa) {
370 sdata->arp_filter_state = false;
371 c = 0;
372 } else {
373 sdata->arp_filter_state = true;
374 }
375 bss_conf->arp_addr_cnt = c;
376
377 /* Configure driver only if associated */
378 if (ifmgd->associated) {
379 bss_conf->arp_filter_enabled = sdata->arp_filter_state;
380 ieee80211_bss_info_change_notify(sdata,
381 BSS_CHANGED_ARP_FILTER);
382 }
383
370 mutex_unlock(&ifmgd->mtx); 384 mutex_unlock(&ifmgd->mtx);
371 385
372 return NOTIFY_DONE; 386 return NOTIFY_DONE;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 583b34686a26..74479c2d12d4 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -806,11 +806,12 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
806{ 806{
807 struct ieee80211_bss *bss = (void *)cbss->priv; 807 struct ieee80211_bss *bss = (void *)cbss->priv;
808 struct ieee80211_local *local = sdata->local; 808 struct ieee80211_local *local = sdata->local;
809 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
809 810
810 bss_info_changed |= BSS_CHANGED_ASSOC; 811 bss_info_changed |= BSS_CHANGED_ASSOC;
811 /* set timing information */ 812 /* set timing information */
812 sdata->vif.bss_conf.beacon_int = cbss->beacon_interval; 813 bss_conf->beacon_int = cbss->beacon_interval;
813 sdata->vif.bss_conf.timestamp = cbss->tsf; 814 bss_conf->timestamp = cbss->tsf;
814 815
815 bss_info_changed |= BSS_CHANGED_BEACON_INT; 816 bss_info_changed |= BSS_CHANGED_BEACON_INT;
816 bss_info_changed |= ieee80211_handle_bss_capability(sdata, 817 bss_info_changed |= ieee80211_handle_bss_capability(sdata,
@@ -835,7 +836,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
835 836
836 ieee80211_led_assoc(local, 1); 837 ieee80211_led_assoc(local, 1);
837 838
838 sdata->vif.bss_conf.assoc = 1; 839 bss_conf->assoc = 1;
839 /* 840 /*
840 * For now just always ask the driver to update the basic rateset 841 * For now just always ask the driver to update the basic rateset
841 * when we have associated, we aren't checking whether it actually 842 * when we have associated, we aren't checking whether it actually
@@ -848,9 +849,15 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
848 849
849 /* Tell the driver to monitor connection quality (if supported) */ 850 /* Tell the driver to monitor connection quality (if supported) */
850 if ((local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI) && 851 if ((local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI) &&
851 sdata->vif.bss_conf.cqm_rssi_thold) 852 bss_conf->cqm_rssi_thold)
852 bss_info_changed |= BSS_CHANGED_CQM; 853 bss_info_changed |= BSS_CHANGED_CQM;
853 854
855 /* Enable ARP filtering */
856 if (bss_conf->arp_filter_enabled != sdata->arp_filter_state) {
857 bss_conf->arp_filter_enabled = sdata->arp_filter_state;
858 bss_info_changed |= BSS_CHANGED_ARP_FILTER;
859 }
860
854 ieee80211_bss_info_change_notify(sdata, bss_info_changed); 861 ieee80211_bss_info_change_notify(sdata, bss_info_changed);
855 862
856 mutex_lock(&local->iflist_mtx); 863 mutex_lock(&local->iflist_mtx);
@@ -932,6 +939,12 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
932 939
933 ieee80211_hw_config(local, config_changed); 940 ieee80211_hw_config(local, config_changed);
934 941
942 /* Disable ARP filtering */
943 if (sdata->vif.bss_conf.arp_filter_enabled) {
944 sdata->vif.bss_conf.arp_filter_enabled = false;
945 changed |= BSS_CHANGED_ARP_FILTER;
946 }
947
935 /* The BSSID (not really interesting) and HT changed */ 948 /* The BSSID (not really interesting) and HT changed */
936 changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT; 949 changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT;
937 ieee80211_bss_info_change_notify(sdata, changed); 950 ieee80211_bss_info_change_notify(sdata, changed);
@@ -2018,18 +2031,9 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
2018 cfg80211_send_assoc_timeout(wk->sdata->dev, 2031 cfg80211_send_assoc_timeout(wk->sdata->dev,
2019 wk->filter_ta); 2032 wk->filter_ta);
2020 return WORK_DONE_DESTROY; 2033 return WORK_DONE_DESTROY;
2021 } else {
2022 mutex_unlock(&wk->sdata->u.mgd.mtx);
2023#ifdef CONFIG_INET
2024 /*
2025 * configure ARP filter IP addresses to the driver,
2026 * intentionally outside the mgd mutex.
2027 */
2028 rtnl_lock();
2029 ieee80211_set_arp_filter(wk->sdata);
2030 rtnl_unlock();
2031#endif
2032 } 2034 }
2035
2036 mutex_unlock(&wk->sdata->u.mgd.mtx);
2033 } 2037 }
2034 2038
2035 cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len); 2039 cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len);