+++ /dev/null
-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;