mac80211: add probe request filter flag
Johannes Berg [Wed, 13 Oct 2010 10:06:24 +0000 (12:06 +0200)]
Using the frame registration notification, we
can see when probe requests are requested and
notify the low-level driver via filtering. The
flag is also set in AP and IBSS modes.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

include/net/mac80211.h
net/mac80211/cfg.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/main.c

index 33aa2e3..9fdf982 100644 (file)
@@ -1478,12 +1478,14 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
  *     honour this flag if possible.
  *
  * @FIF_CONTROL: pass control frames (except for PS Poll), if PROMISC_IN_BSS
- *  is not set then only those addressed to this station.
+ *     is not set then only those addressed to this station.
  *
  * @FIF_OTHER_BSS: pass frames destined to other BSSes
  *
- * @FIF_PSPOLL: pass PS Poll frames, if PROMISC_IN_BSS  is not set then only
- *  those addressed to this station.
+ * @FIF_PSPOLL: pass PS Poll frames, if PROMISC_IN_BSS is not set then only
+ *     those addressed to this station.
+ *
+ * @FIF_PROBE_REQ: pass probe request frames
  */
 enum ieee80211_filter_flags {
        FIF_PROMISC_IN_BSS      = 1<<0,
@@ -1494,6 +1496,7 @@ enum ieee80211_filter_flags {
        FIF_CONTROL             = 1<<5,
        FIF_OTHER_BSS           = 1<<6,
        FIF_PSPOLL              = 1<<7,
+       FIF_PROBE_REQ           = 1<<8,
 };
 
 /**
index 25fb351..18bd0e5 100644 (file)
@@ -1604,6 +1604,23 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
        return 0;
 }
 
+static void ieee80211_mgmt_frame_register(struct wiphy *wiphy,
+                                         struct net_device *dev,
+                                         u16 frame_type, bool reg)
+{
+       struct ieee80211_local *local = wiphy_priv(wiphy);
+
+       if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
+               return;
+
+       if (reg)
+               local->probe_req_reg++;
+       else
+               local->probe_req_reg--;
+
+       ieee80211_queue_work(&local->hw, &local->reconfig_filter);
+}
+
 struct cfg80211_ops mac80211_config_ops = {
        .add_virtual_intf = ieee80211_add_iface,
        .del_virtual_intf = ieee80211_del_iface,
@@ -1655,4 +1672,5 @@ struct cfg80211_ops mac80211_config_ops = {
        .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel,
        .mgmt_tx = ieee80211_mgmt_tx,
        .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config,
+       .mgmt_frame_register = ieee80211_mgmt_frame_register,
 };
index f0610fa..b80c386 100644 (file)
@@ -707,7 +707,9 @@ struct ieee80211_local {
        int open_count;
        int monitors, cooked_mntrs;
        /* number of interfaces with corresponding FIF_ flags */
-       int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll;
+       int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll,
+           fif_probe_req;
+       int probe_req_reg;
        unsigned int filter_flags; /* FIF_* */
 
        bool wiphy_ciphers_allocated;
index e99d1b6..f9163b1 100644 (file)
@@ -280,8 +280,11 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
                        ieee80211_start_mesh(sdata);
                } else if (sdata->vif.type == NL80211_IFTYPE_AP) {
                        local->fif_pspoll++;
+                       local->fif_probe_req++;
 
                        ieee80211_configure_filter(local);
+               } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
+                       local->fif_probe_req++;
                }
 
                changed |= ieee80211_reset_erp_info(sdata);
@@ -428,8 +431,12 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
        if (sdata->flags & IEEE80211_SDATA_PROMISC)
                atomic_dec(&local->iff_promiscs);
 
-       if (sdata->vif.type == NL80211_IFTYPE_AP)
+       if (sdata->vif.type == NL80211_IFTYPE_AP) {
                local->fif_pspoll--;
+               local->fif_probe_req--;
+       } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
+               local->fif_probe_req--;
+       }
 
        netif_addr_lock_bh(sdata->dev);
        spin_lock_bh(&local->filter_lock);
index 915ecf8..5162303 100644 (file)
@@ -54,6 +54,9 @@ void ieee80211_configure_filter(struct ieee80211_local *local)
        if (local->monitors || local->scanning)
                new_flags |= FIF_BCN_PRBRESP_PROMISC;
 
+       if (local->fif_probe_req || local->probe_req_reg)
+               new_flags |= FIF_PROBE_REQ;
+
        if (local->fif_fcsfail)
                new_flags |= FIF_FCSFAIL;