]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From: Ron Rindjunsky <ron.rindjunsky@intel.com> |
2 | Date: Sat, 9 Aug 2008 03:02:19 +0300 | |
3 | Subject: [PATCH] mac80211: add direct probe before association | |
4 | Patch-mainline: 2.6.28-rc1 | |
5 | References: bnc#461889 | |
6 | ||
7 | This patch adds a direct probe request as first step in the association | |
8 | flow if data we have is not up to date. Motivation of this step is to make | |
9 | sure that the bss information we have is correct, since last scan could | |
10 | have been done a while ago, and beacons do not fully answer this need as | |
11 | there are potential differences between them and probe responses (e.g. | |
12 | WMM parameter element) | |
13 | ||
14 | Signed-off-by: Ron Rindjunsky <ron.rindjunsky@intel.com> | |
15 | Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> | |
16 | Signed-off-by: John W. Linville <linville@tuxdriver.com> | |
17 | ||
18 | Modified not to break kABI: auth_tries is overriden to also mean | |
19 | direct_probe_tries, last_probe_resp is moved to the end of the | |
20 | ieee80211_sta_bss structure. | |
21 | ||
22 | Signed-off-by: Jiri Benc <jbenc@suse.cz> | |
23 | ||
24 | --- | |
25 | net/mac80211/ieee80211_i.h | 10 +++++ | |
26 | net/mac80211/mlme.c | 79 ++++++++++++++++++++++++++++++++++++++------- | |
27 | 2 files changed, 77 insertions(+), 12 deletions(-) | |
28 | ||
29 | --- linux-2.6.27.orig/net/mac80211/ieee80211_i.h | |
30 | +++ linux-2.6.27/net/mac80211/ieee80211_i.h | |
31 | @@ -117,6 +117,10 @@ struct ieee80211_sta_bss { | |
32 | * otherwise, you probably don't want to use them. */ | |
33 | int has_erp_value; | |
34 | u8 erp_value; | |
35 | + | |
36 | +#ifndef __GENKSYMS__ | |
37 | + unsigned long last_probe_resp; | |
38 | +#endif | |
39 | }; | |
40 | ||
41 | static inline u8 *bss_mesh_cfg(struct ieee80211_sta_bss *bss) | |
42 | @@ -310,6 +314,9 @@ struct ieee80211_if_sta { | |
43 | IEEE80211_ASSOCIATE, IEEE80211_ASSOCIATED, | |
44 | IEEE80211_IBSS_SEARCH, IEEE80211_IBSS_JOINED, | |
45 | IEEE80211_MESH_UP | |
46 | +#ifndef __GENKSYMS__ | |
47 | + , IEEE80211_DIRECT_PROBE | |
48 | +#endif | |
49 | } state; | |
50 | size_t ssid_len; | |
51 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; | |
52 | @@ -363,6 +370,7 @@ struct ieee80211_if_sta { | |
53 | #define IEEE80211_STA_REQ_SCAN 0 | |
54 | #define IEEE80211_STA_REQ_AUTH 1 | |
55 | #define IEEE80211_STA_REQ_RUN 2 | |
56 | +#define IEEE80211_STA_REQ_DIRECT_PROBE 3 | |
57 | ||
58 | #define IEEE80211_AUTH_ALG_OPEN BIT(0) | |
59 | #define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1) | |
60 | --- linux-2.6.27.orig/net/mac80211/mlme.c | |
61 | +++ linux-2.6.27/net/mac80211/mlme.c | |
62 | @@ -658,6 +658,36 @@ static void ieee80211_send_auth(struct n | |
63 | ieee80211_sta_tx(dev, skb, encrypt); | |
64 | } | |
65 | ||
66 | +static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, | |
67 | + struct ieee80211_if_sta *ifsta) | |
68 | +{ | |
69 | + DECLARE_MAC_BUF(mac); | |
70 | + | |
71 | + ifsta->auth_tries++; /* used as direct_probe_tries */ | |
72 | + if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) { | |
73 | + printk(KERN_DEBUG "%s: direct probe to AP %s timed out\n", | |
74 | + sdata->dev->name, print_mac(mac, ifsta->bssid)); | |
75 | + ifsta->state = IEEE80211_DISABLED; | |
76 | + return; | |
77 | + } | |
78 | + | |
79 | + printk(KERN_DEBUG "%s: direct probe to AP %s try %d\n", | |
80 | + sdata->dev->name, print_mac(mac, ifsta->bssid), | |
81 | + ifsta->auth_tries); | |
82 | + | |
83 | + ifsta->state = IEEE80211_DIRECT_PROBE; | |
84 | + | |
85 | + set_bit(IEEE80211_STA_REQ_DIRECT_PROBE, &ifsta->request); | |
86 | + | |
87 | + /* Direct probe is sent to broadcast address as some APs | |
88 | + * will not answer to direct packet in unassociated state. | |
89 | + */ | |
90 | + ieee80211_send_probe_req(sdata->dev, NULL, | |
91 | + ifsta->ssid, ifsta->ssid_len); | |
92 | + | |
93 | + mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); | |
94 | +} | |
95 | + | |
96 | ||
97 | static void ieee80211_authenticate(struct net_device *dev, | |
98 | struct ieee80211_if_sta *ifsta) | |
99 | @@ -1958,7 +1988,7 @@ static void ieee80211_rx_mgmt_deauth(str | |
100 | if (ifsta->state == IEEE80211_AUTHENTICATE || | |
101 | ifsta->state == IEEE80211_ASSOCIATE || | |
102 | ifsta->state == IEEE80211_ASSOCIATED) { | |
103 | - ifsta->state = IEEE80211_AUTHENTICATE; | |
104 | + ifsta->state = IEEE80211_DIRECT_PROBE; | |
105 | mod_timer(&ifsta->timer, jiffies + | |
106 | IEEE80211_RETRY_AUTH_INTERVAL); | |
107 | } | |
108 | @@ -2559,8 +2589,7 @@ static void ieee80211_rx_bss_info(struct | |
109 | struct ieee80211_mgmt *mgmt, | |
110 | size_t len, | |
111 | struct ieee80211_rx_status *rx_status, | |
112 | - struct ieee802_11_elems *elems, | |
113 | - int beacon) | |
114 | + struct ieee802_11_elems *elems) | |
115 | { | |
116 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | |
117 | int freq, clen; | |
118 | @@ -2569,6 +2598,7 @@ static void ieee80211_rx_bss_info(struct | |
119 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | |
120 | u64 beacon_timestamp, rx_timestamp; | |
121 | struct ieee80211_channel *channel; | |
122 | + bool beacon = ieee80211_is_beacon(mgmt->frame_control); | |
123 | DECLARE_MAC_BUF(mac); | |
124 | DECLARE_MAC_BUF(mac2); | |
125 | ||
126 | @@ -2728,15 +2758,14 @@ static void ieee80211_rx_bss_info(struct | |
127 | bss->signal = rx_status->signal; | |
128 | bss->noise = rx_status->noise; | |
129 | bss->qual = rx_status->qual; | |
130 | - if (!beacon && !bss->probe_resp) | |
131 | - bss->probe_resp = true; | |
132 | - | |
133 | + if (!beacon) | |
134 | + bss->last_probe_resp = jiffies; | |
135 | /* | |
136 | * In STA mode, the remaining parameters should not be overridden | |
137 | * by beacons because they're not necessarily accurate there. | |
138 | */ | |
139 | if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | |
140 | - bss->probe_resp && beacon) { | |
141 | + bss->last_probe_resp && beacon) { | |
142 | ieee80211_rx_bss_put(local, bss); | |
143 | return; | |
144 | } | |
145 | @@ -2891,6 +2920,8 @@ static void ieee80211_rx_mgmt_probe_resp | |
146 | { | |
147 | size_t baselen; | |
148 | struct ieee802_11_elems elems; | |
149 | + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | |
150 | + struct ieee80211_if_sta *ifsta = &sdata->u.sta; | |
151 | ||
152 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | |
153 | if (baselen > len) | |
154 | @@ -2899,7 +2930,17 @@ static void ieee80211_rx_mgmt_probe_resp | |
155 | ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, | |
156 | &elems); | |
157 | ||
158 | - ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems, 0); | |
159 | + ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems); | |
160 | + | |
161 | + /* direct probe may be part of the association flow */ | |
162 | + if (test_and_clear_bit(IEEE80211_STA_REQ_DIRECT_PROBE, | |
163 | + &ifsta->request)) { | |
164 | + printk(KERN_DEBUG "%s direct probe responded\n", | |
165 | + sdata->dev->name); | |
166 | + ifsta->auth_tries = 0; /* direct_probe_tries -> auth_tries */ | |
167 | + ieee80211_authenticate(dev, ifsta); | |
168 | + } | |
169 | + | |
170 | } | |
171 | ||
172 | ||
173 | @@ -2923,7 +2964,7 @@ static void ieee80211_rx_mgmt_beacon(str | |
174 | ||
175 | ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); | |
176 | ||
177 | - ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems, 1); | |
178 | + ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems); | |
179 | ||
180 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | |
181 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA) | |
182 | @@ -3361,7 +3402,8 @@ void ieee80211_sta_work(struct work_stru | |
183 | mesh_path_start_discovery(dev); | |
184 | #endif | |
185 | ||
186 | - if (ifsta->state != IEEE80211_AUTHENTICATE && | |
187 | + if (ifsta->state != IEEE80211_DIRECT_PROBE && | |
188 | + ifsta->state != IEEE80211_AUTHENTICATE && | |
189 | ifsta->state != IEEE80211_ASSOCIATE && | |
190 | test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) { | |
191 | if (ifsta->scan_ssid_len) | |
192 | @@ -3381,6 +3423,10 @@ void ieee80211_sta_work(struct work_stru | |
193 | switch (ifsta->state) { | |
194 | case IEEE80211_DISABLED: | |
195 | break; | |
196 | + case IEEE80211_DIRECT_PROBE: | |
197 | + ieee80211_direct_probe(sdata, ifsta); | |
198 | + break; | |
199 | + | |
200 | case IEEE80211_AUTHENTICATE: | |
201 | ieee80211_authenticate(dev, ifsta); | |
202 | break; | |
203 | @@ -3541,8 +3587,18 @@ static int ieee80211_sta_config_auth(str | |
204 | selected->ssid_len); | |
205 | ieee80211_sta_set_bssid(dev, selected->bssid); | |
206 | ieee80211_sta_def_wmm_params(dev, selected, 0); | |
207 | + | |
208 | + /* Send out direct probe if no probe resp was received or | |
209 | + * the one we have is outdated | |
210 | + */ | |
211 | + if (!selected->last_probe_resp || | |
212 | + time_after(jiffies, selected->last_probe_resp | |
213 | + + IEEE80211_SCAN_RESULT_EXPIRE)) | |
214 | + ifsta->state = IEEE80211_DIRECT_PROBE; | |
215 | + else | |
216 | + ifsta->state = IEEE80211_AUTHENTICATE; | |
217 | + | |
218 | ieee80211_rx_bss_put(local, selected); | |
219 | - ifsta->state = IEEE80211_AUTHENTICATE; | |
220 | ieee80211_sta_reset_auth(dev, ifsta); | |
221 | return 0; | |
222 | } else { | |
223 | @@ -3553,6 +3609,7 @@ static int ieee80211_sta_config_auth(str | |
224 | ieee80211_sta_start_scan(dev, ifsta->ssid, | |
225 | ifsta->ssid_len); | |
226 | ifsta->state = IEEE80211_AUTHENTICATE; | |
227 | + ifsta->auth_tries = 0; /* direct_probe_tries -> auth_tries */ | |
228 | set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); | |
229 | } else | |
230 | ifsta->state = IEEE80211_DISABLED; |