]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blobdiff - src/patches/suse-2.6.27.31/patches.fixes/mac80211-add-direct-probe.patch
Reenabled linux-xen, added patches for Xen Kernel Version 2.6.27.31,
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.fixes / mac80211-add-direct-probe.patch
diff --git a/src/patches/suse-2.6.27.31/patches.fixes/mac80211-add-direct-probe.patch b/src/patches/suse-2.6.27.31/patches.fixes/mac80211-add-direct-probe.patch
new file mode 100644 (file)
index 0000000..71dcdcb
--- /dev/null
@@ -0,0 +1,230 @@
+From: Ron Rindjunsky <ron.rindjunsky@intel.com>
+Date: Sat, 9 Aug 2008 03:02:19 +0300
+Subject: [PATCH] mac80211: add direct probe before association
+Patch-mainline: 2.6.28-rc1
+References: bnc#461889
+
+This patch adds a direct probe request as first step in the association
+flow if data we have is not up to date. Motivation of this step is to make
+sure that the bss information we have is correct, since last scan could
+have been done a while ago, and beacons do not fully answer this need as
+there are potential differences between them and probe responses (e.g.
+WMM parameter element)
+
+Signed-off-by: Ron Rindjunsky <ron.rindjunsky@intel.com>
+Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+
+Modified not to break kABI: auth_tries is overriden to also mean
+direct_probe_tries, last_probe_resp is moved to the end of the
+ieee80211_sta_bss structure.
+
+Signed-off-by: Jiri Benc <jbenc@suse.cz>
+
+---
+ net/mac80211/ieee80211_i.h |   10 +++++
+ net/mac80211/mlme.c        |   79 ++++++++++++++++++++++++++++++++++++++-------
+ 2 files changed, 77 insertions(+), 12 deletions(-)
+
+--- linux-2.6.27.orig/net/mac80211/ieee80211_i.h
++++ linux-2.6.27/net/mac80211/ieee80211_i.h
+@@ -117,6 +117,10 @@ struct ieee80211_sta_bss {
+        * otherwise, you probably don't want to use them. */
+       int has_erp_value;
+       u8 erp_value;
++
++#ifndef __GENKSYMS__
++      unsigned long last_probe_resp;
++#endif
+ };
+ static inline u8 *bss_mesh_cfg(struct ieee80211_sta_bss *bss)
+@@ -310,6 +314,9 @@ struct ieee80211_if_sta {
+               IEEE80211_ASSOCIATE, IEEE80211_ASSOCIATED,
+               IEEE80211_IBSS_SEARCH, IEEE80211_IBSS_JOINED,
+               IEEE80211_MESH_UP
++#ifndef __GENKSYMS__
++              , IEEE80211_DIRECT_PROBE
++#endif
+       } state;
+       size_t ssid_len;
+       u8 scan_ssid[IEEE80211_MAX_SSID_LEN];
+@@ -363,6 +370,7 @@ struct ieee80211_if_sta {
+ #define IEEE80211_STA_REQ_SCAN 0
+ #define IEEE80211_STA_REQ_AUTH 1
+ #define IEEE80211_STA_REQ_RUN  2
++#define IEEE80211_STA_REQ_DIRECT_PROBE 3
+ #define IEEE80211_AUTH_ALG_OPEN BIT(0)
+ #define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1)
+--- linux-2.6.27.orig/net/mac80211/mlme.c
++++ linux-2.6.27/net/mac80211/mlme.c
+@@ -658,6 +658,36 @@ static void ieee80211_send_auth(struct n
+       ieee80211_sta_tx(dev, skb, encrypt);
+ }
++static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata,
++                                 struct ieee80211_if_sta *ifsta)
++{
++      DECLARE_MAC_BUF(mac);
++
++      ifsta->auth_tries++;    /* used as direct_probe_tries */
++      if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) {
++              printk(KERN_DEBUG "%s: direct probe to AP %s timed out\n",
++                     sdata->dev->name, print_mac(mac, ifsta->bssid));
++              ifsta->state = IEEE80211_DISABLED;
++              return;
++      }
++
++      printk(KERN_DEBUG "%s: direct probe to AP %s try %d\n",
++                      sdata->dev->name, print_mac(mac, ifsta->bssid),
++                      ifsta->auth_tries);
++
++      ifsta->state = IEEE80211_DIRECT_PROBE;
++
++      set_bit(IEEE80211_STA_REQ_DIRECT_PROBE, &ifsta->request);
++
++      /* Direct probe is sent to broadcast address as some APs
++       * will not answer to direct packet in unassociated state.
++       */
++      ieee80211_send_probe_req(sdata->dev, NULL,
++                               ifsta->ssid, ifsta->ssid_len);
++
++      mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
++}
++
+ static void ieee80211_authenticate(struct net_device *dev,
+                                  struct ieee80211_if_sta *ifsta)
+@@ -1958,7 +1988,7 @@ static void ieee80211_rx_mgmt_deauth(str
+       if (ifsta->state == IEEE80211_AUTHENTICATE ||
+           ifsta->state == IEEE80211_ASSOCIATE ||
+           ifsta->state == IEEE80211_ASSOCIATED) {
+-              ifsta->state = IEEE80211_AUTHENTICATE;
++              ifsta->state = IEEE80211_DIRECT_PROBE;
+               mod_timer(&ifsta->timer, jiffies +
+                                     IEEE80211_RETRY_AUTH_INTERVAL);
+       }
+@@ -2559,8 +2589,7 @@ static void ieee80211_rx_bss_info(struct
+                                 struct ieee80211_mgmt *mgmt,
+                                 size_t len,
+                                 struct ieee80211_rx_status *rx_status,
+-                                struct ieee802_11_elems *elems,
+-                                int beacon)
++                                struct ieee802_11_elems *elems)
+ {
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       int freq, clen;
+@@ -2569,6 +2598,7 @@ static void ieee80211_rx_bss_info(struct
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       u64 beacon_timestamp, rx_timestamp;
+       struct ieee80211_channel *channel;
++      bool beacon = ieee80211_is_beacon(mgmt->frame_control);
+       DECLARE_MAC_BUF(mac);
+       DECLARE_MAC_BUF(mac2);
+@@ -2728,15 +2758,14 @@ static void ieee80211_rx_bss_info(struct
+       bss->signal = rx_status->signal;
+       bss->noise = rx_status->noise;
+       bss->qual = rx_status->qual;
+-      if (!beacon && !bss->probe_resp)
+-              bss->probe_resp = true;
+-
++      if (!beacon)
++              bss->last_probe_resp = jiffies;
+       /*
+        * In STA mode, the remaining parameters should not be overridden
+        * by beacons because they're not necessarily accurate there.
+        */
+       if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
+-          bss->probe_resp && beacon) {
++          bss->last_probe_resp && beacon) {
+               ieee80211_rx_bss_put(local, bss);
+               return;
+       }
+@@ -2891,6 +2920,8 @@ static void ieee80211_rx_mgmt_probe_resp
+ {
+       size_t baselen;
+       struct ieee802_11_elems elems;
++      struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++      struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+       baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
+       if (baselen > len)
+@@ -2899,7 +2930,17 @@ static void ieee80211_rx_mgmt_probe_resp
+       ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
+                               &elems);
+-      ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems, 0);
++      ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems);
++
++      /* direct probe may be part of the association flow */
++      if (test_and_clear_bit(IEEE80211_STA_REQ_DIRECT_PROBE,
++                                                      &ifsta->request)) {
++              printk(KERN_DEBUG "%s direct probe responded\n",
++                     sdata->dev->name);
++              ifsta->auth_tries = 0;  /* direct_probe_tries -> auth_tries */
++              ieee80211_authenticate(dev, ifsta);
++      }
++
+ }
+@@ -2923,7 +2964,7 @@ static void ieee80211_rx_mgmt_beacon(str
+       ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
+-      ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems, 1);
++      ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems);
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
+@@ -3361,7 +3402,8 @@ void ieee80211_sta_work(struct work_stru
+               mesh_path_start_discovery(dev);
+ #endif
+-      if (ifsta->state != IEEE80211_AUTHENTICATE &&
++      if (ifsta->state != IEEE80211_DIRECT_PROBE &&
++          ifsta->state != IEEE80211_AUTHENTICATE &&
+           ifsta->state != IEEE80211_ASSOCIATE &&
+           test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) {
+               if (ifsta->scan_ssid_len)
+@@ -3381,6 +3423,10 @@ void ieee80211_sta_work(struct work_stru
+       switch (ifsta->state) {
+       case IEEE80211_DISABLED:
+               break;
++      case IEEE80211_DIRECT_PROBE:
++              ieee80211_direct_probe(sdata, ifsta);
++              break;
++
+       case IEEE80211_AUTHENTICATE:
+               ieee80211_authenticate(dev, ifsta);
+               break;
+@@ -3541,8 +3587,18 @@ static int ieee80211_sta_config_auth(str
+                                              selected->ssid_len);
+               ieee80211_sta_set_bssid(dev, selected->bssid);
+               ieee80211_sta_def_wmm_params(dev, selected, 0);
++
++              /* Send out direct probe if no probe resp was received or
++               * the one we have is outdated
++               */
++              if (!selected->last_probe_resp ||
++                  time_after(jiffies, selected->last_probe_resp
++                                      + IEEE80211_SCAN_RESULT_EXPIRE))
++                      ifsta->state = IEEE80211_DIRECT_PROBE;
++              else
++                      ifsta->state = IEEE80211_AUTHENTICATE;
++
+               ieee80211_rx_bss_put(local, selected);
+-              ifsta->state = IEEE80211_AUTHENTICATE;
+               ieee80211_sta_reset_auth(dev, ifsta);
+               return 0;
+       } else {
+@@ -3553,6 +3609,7 @@ static int ieee80211_sta_config_auth(str
+                               ieee80211_sta_start_scan(dev, ifsta->ssid,
+                                                        ifsta->ssid_len);
+                       ifsta->state = IEEE80211_AUTHENTICATE;
++                      ifsta->auth_tries = 0; /* direct_probe_tries -> auth_tries */
+                       set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
+               } else
+                       ifsta->state = IEEE80211_DISABLED;