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.h25
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/main.c63
-rw-r--r--net/mac80211/mlme.c11
5 files changed, 116 insertions, 2 deletions
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 4f2271316650..978850ee3a5f 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -83,6 +83,23 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local,
83 trace_drv_bss_info_changed(local, sdata, info, changed); 83 trace_drv_bss_info_changed(local, sdata, info, changed);
84} 84}
85 85
86struct in_ifaddr;
87static inline int drv_configure_arp_filter(struct ieee80211_local *local,
88 struct ieee80211_vif *vif,
89 struct in_ifaddr *ifa_list)
90{
91 int ret = 0;
92
93 might_sleep();
94
95 if (local->ops->configure_arp_filter)
96 ret = local->ops->configure_arp_filter(&local->hw, vif,
97 ifa_list);
98
99 trace_drv_configure_arp_filter(local, vif_to_sdata(vif), ifa_list, ret);
100 return ret;
101}
102
86static inline u64 drv_prepare_multicast(struct ieee80211_local *local, 103static inline u64 drv_prepare_multicast(struct ieee80211_local *local,
87 struct netdev_hw_addr_list *mc_list) 104 struct netdev_hw_addr_list *mc_list)
88{ 105{
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 6a9b2342a9c2..577460da2ea1 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -219,6 +219,31 @@ TRACE_EVENT(drv_bss_info_changed,
219 ) 219 )
220); 220);
221 221
222TRACE_EVENT(drv_configure_arp_filter,
223 TP_PROTO(struct ieee80211_local *local,
224 struct ieee80211_sub_if_data *sdata,
225 struct in_ifaddr *ifa_list, int ret),
226
227 TP_ARGS(local, sdata, ifa_list, ret),
228
229 TP_STRUCT__entry(
230 LOCAL_ENTRY
231 VIF_ENTRY
232 __field(int, ret)
233 ),
234
235 TP_fast_assign(
236 LOCAL_ASSIGN;
237 VIF_ASSIGN;
238 __entry->ret = ret;
239 ),
240
241 TP_printk(
242 VIF_PR_FMT LOCAL_PR_FMT " ret:%d",
243 VIF_PR_ARG, LOCAL_PR_ARG, __entry->ret
244 )
245);
246
222TRACE_EVENT(drv_prepare_multicast, 247TRACE_EVENT(drv_prepare_multicast,
223 TP_PROTO(struct ieee80211_local *local, int mc_count, u64 ret), 248 TP_PROTO(struct ieee80211_local *local, int mc_count, u64 ret),
224 249
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index d4677efd3a36..47d67537f170 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -851,6 +851,7 @@ struct ieee80211_local {
851 struct work_struct dynamic_ps_disable_work; 851 struct work_struct dynamic_ps_disable_work;
852 struct timer_list dynamic_ps_timer; 852 struct timer_list dynamic_ps_timer;
853 struct notifier_block network_latency_notifier; 853 struct notifier_block network_latency_notifier;
854 struct notifier_block ifa_notifier;
854 855
855 int user_power_level; /* in dBm */ 856 int user_power_level; /* in dBm */
856 int power_constr_level; /* in dBm */ 857 int power_constr_level; /* in dBm */
@@ -997,6 +998,7 @@ void ieee80211_send_pspoll(struct ieee80211_local *local,
997void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency); 998void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency);
998int ieee80211_max_network_latency(struct notifier_block *nb, 999int ieee80211_max_network_latency(struct notifier_block *nb,
999 unsigned long data, void *dummy); 1000 unsigned long data, void *dummy);
1001int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata);
1000void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, 1002void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1001 struct ieee80211_channel_sw_ie *sw_elem, 1003 struct ieee80211_channel_sw_ie *sw_elem,
1002 struct ieee80211_bss *bss, 1004 struct ieee80211_bss *bss,
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index c8548e61f860..4051b232c6e6 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -329,6 +329,58 @@ static void ieee80211_recalc_smps_work(struct work_struct *work)
329 mutex_unlock(&local->iflist_mtx); 329 mutex_unlock(&local->iflist_mtx);
330} 330}
331 331
332int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata)
333{
334 struct in_device *idev;
335 int ret = 0;
336
337 BUG_ON(!sdata);
338 ASSERT_RTNL();
339
340 idev = sdata->dev->ip_ptr;
341 if (!idev)
342 return 0;
343
344 ret = drv_configure_arp_filter(sdata->local, &sdata->vif,
345 idev->ifa_list);
346 return ret;
347}
348
349static int ieee80211_ifa_changed(struct notifier_block *nb,
350 unsigned long data, void *arg)
351{
352 struct in_ifaddr *ifa = arg;
353 struct ieee80211_local *local =
354 container_of(nb, struct ieee80211_local,
355 ifa_notifier);
356 struct net_device *ndev = ifa->ifa_dev->dev;
357 struct wireless_dev *wdev = ndev->ieee80211_ptr;
358 struct ieee80211_sub_if_data *sdata;
359 struct ieee80211_if_managed *ifmgd;
360
361 /* Make sure it's our interface that got changed */
362 if (!wdev)
363 return NOTIFY_DONE;
364
365 if (wdev->wiphy != local->hw.wiphy)
366 return NOTIFY_DONE;
367
368 /* We are concerned about IP addresses only when associated */
369 sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
370
371 /* ARP filtering is only supported in managed mode */
372 if (sdata->vif.type != NL80211_IFTYPE_STATION)
373 return NOTIFY_DONE;
374
375 ifmgd = &sdata->u.mgd;
376 mutex_lock(&ifmgd->mtx);
377 if (ifmgd->associated)
378 ieee80211_set_arp_filter(sdata);
379 mutex_unlock(&ifmgd->mtx);
380
381 return NOTIFY_DONE;
382}
383
332struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, 384struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
333 const struct ieee80211_ops *ops) 385 const struct ieee80211_ops *ops)
334{ 386{
@@ -612,14 +664,22 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
612 ieee80211_max_network_latency; 664 ieee80211_max_network_latency;
613 result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY, 665 result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY,
614 &local->network_latency_notifier); 666 &local->network_latency_notifier);
615
616 if (result) { 667 if (result) {
617 rtnl_lock(); 668 rtnl_lock();
618 goto fail_pm_qos; 669 goto fail_pm_qos;
619 } 670 }
620 671
672 local->ifa_notifier.notifier_call = ieee80211_ifa_changed;
673 result = register_inetaddr_notifier(&local->ifa_notifier);
674 if (result)
675 goto fail_ifa;
676
621 return 0; 677 return 0;
622 678
679 fail_ifa:
680 pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
681 &local->network_latency_notifier);
682 rtnl_lock();
623 fail_pm_qos: 683 fail_pm_qos:
624 ieee80211_led_exit(local); 684 ieee80211_led_exit(local);
625 ieee80211_remove_interfaces(local); 685 ieee80211_remove_interfaces(local);
@@ -647,6 +707,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
647 707
648 pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, 708 pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
649 &local->network_latency_notifier); 709 &local->network_latency_notifier);
710 unregister_inetaddr_notifier(&local->ifa_notifier);
650 711
651 rtnl_lock(); 712 rtnl_lock();
652 713
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 29c3a75a7ad0..7e720133358c 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2078,8 +2078,17 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
2078 cfg80211_send_assoc_timeout(wk->sdata->dev, 2078 cfg80211_send_assoc_timeout(wk->sdata->dev,
2079 wk->filter_ta); 2079 wk->filter_ta);
2080 return WORK_DONE_DESTROY; 2080 return WORK_DONE_DESTROY;
2081 } else {
2082 mutex_unlock(&wk->sdata->u.mgd.mtx);
2083
2084 /*
2085 * configure ARP filter IP addresses to the driver,
2086 * intentionally outside the mgd mutex.
2087 */
2088 rtnl_lock();
2089 ieee80211_set_arp_filter(wk->sdata);
2090 rtnl_unlock();
2081 } 2091 }
2082 mutex_unlock(&wk->sdata->u.mgd.mtx);
2083 } 2092 }
2084 2093
2085 cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len); 2094 cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len);