diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/driver-ops.h | 17 | ||||
-rw-r--r-- | net/mac80211/driver-trace.h | 25 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 2 | ||||
-rw-r--r-- | net/mac80211/main.c | 63 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 11 |
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 | ||
86 | struct in_ifaddr; | ||
87 | static 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 | |||
86 | static inline u64 drv_prepare_multicast(struct ieee80211_local *local, | 103 | static 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 | ||
222 | TRACE_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 | |||
222 | TRACE_EVENT(drv_prepare_multicast, | 247 | TRACE_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, | |||
997 | void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency); | 998 | void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency); |
998 | int ieee80211_max_network_latency(struct notifier_block *nb, | 999 | int ieee80211_max_network_latency(struct notifier_block *nb, |
999 | unsigned long data, void *dummy); | 1000 | unsigned long data, void *dummy); |
1001 | int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata); | ||
1000 | void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | 1002 | void 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 | ||
332 | int 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 | |||
349 | static 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 | |||
332 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | 384 | struct 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); |