aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/main.c
diff options
context:
space:
mode:
authorJuuso Oikarinen <juuso.oikarinen@nokia.com>2010-05-27 08:32:13 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-06-03 14:10:45 -0400
commit2b2c009ecf71f4c66ff8420b63dddbc9737e04e3 (patch)
tree62f93194843ecf92d871d34963450c03d165af08 /net/mac80211/main.c
parent095dfdb0c479661f437b24b85e31f0d0b841eab6 (diff)
mac80211: Add support for hardware ARP query filtering
Some hardware allow extended filtering of ARP frames not intended for the host. To perform such filtering, the hardware needs to know the current IP address(es) of the host, bound to its interface. Add support for ARP filtering to mac80211 by adding a new op to the driver interface, allowing to configure the current IP addresses. This op is called upon association with the currently configured address(es), and when associated whenever the IP address(es) change. This patch adds configuration of IPv4 addresses only, as IPv6 addresses don't need ARP filtering. Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com> Reviewed-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r--net/mac80211/main.c63
1 files changed, 62 insertions, 1 deletions
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