X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=src%2Fpatches%2Fsuse-2.6.27.31%2Fpatches.fixes%2Fmac80211-add-direct-probe.patch;fp=src%2Fpatches%2Fsuse-2.6.27.31%2Fpatches.fixes%2Fmac80211-add-direct-probe.patch;h=71dcdcb1cd8e3494192aad669faf7da6293b7bbd;hb=2cb7cef9f877c88c82c959e2944ff02a12d068fa;hp=0000000000000000000000000000000000000000;hpb=836f873377e58243cc856caa0586954efff79185;p=ipfire-2.x.git 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 index 0000000000..71dcdcb1cd --- /dev/null +++ b/src/patches/suse-2.6.27.31/patches.fixes/mac80211-add-direct-probe.patch @@ -0,0 +1,230 @@ +From: Ron Rindjunsky +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 +Signed-off-by: Tomas Winkler +Signed-off-by: John W. Linville + +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 + +--- + 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;