[PATCH] softmac: convert to use global workqueue
[deliverable/linux.git] / net / ieee80211 / softmac / ieee80211softmac_auth.c
CommitLineData
370121e5
JB
1#include "ieee80211softmac_priv.h"
2
3static void ieee80211softmac_auth_queue(void *data);
4
5/* Queues an auth request to the desired AP */
6int
7ieee80211softmac_auth_req(struct ieee80211softmac_device *mac,
8 struct ieee80211softmac_network *net)
9{
10 struct ieee80211softmac_auth_queue_item *auth;
11 unsigned long flags;
12
13 function_enter();
14
15 if (net->authenticating)
16 return 0;
17
18 /* Add the network if it's not already added */
19 ieee80211softmac_add_network(mac, net);
20
21 dprintk(KERN_NOTICE PFX "Queueing Authentication Request to "MAC_FMT"\n", MAC_ARG(net->bssid));
22 /* Queue the auth request */
23 auth = (struct ieee80211softmac_auth_queue_item *)
24 kmalloc(sizeof(struct ieee80211softmac_auth_queue_item), GFP_KERNEL);
25 if(auth == NULL)
26 return -ENOMEM;
27
28 auth->net = net;
29 auth->mac = mac;
30 auth->retry = IEEE80211SOFTMAC_AUTH_RETRY_LIMIT;
31 auth->state = IEEE80211SOFTMAC_AUTH_OPEN_REQUEST;
32 INIT_WORK(&auth->work, &ieee80211softmac_auth_queue, (void *)auth);
33
34 /* Lock (for list) */
35 spin_lock_irqsave(&mac->lock, flags);
36
37 /* add to list */
38 list_add_tail(&auth->list, &mac->auth_queue);
5c4df6da 39 schedule_work(&auth->work);
370121e5
JB
40 spin_unlock_irqrestore(&mac->lock, flags);
41
42 return 0;
43}
44
45
46/* Sends an auth request to the desired AP and handles timeouts */
47static void
48ieee80211softmac_auth_queue(void *data)
49{
50 struct ieee80211softmac_device *mac;
51 struct ieee80211softmac_auth_queue_item *auth;
52 struct ieee80211softmac_network *net;
53 unsigned long flags;
54
55 function_enter();
56
57 auth = (struct ieee80211softmac_auth_queue_item *)data;
58 net = auth->net;
59 mac = auth->mac;
60
61 if(auth->retry > 0) {
62 /* Switch to correct channel for this network */
63 mac->set_channel(mac->dev, net->channel);
64
65 /* Lock and set flags */
66 spin_lock_irqsave(&mac->lock, flags);
67 net->authenticated = 0;
68 net->authenticating = 1;
69 /* add a timeout call so we eventually give up waiting for an auth reply */
5c4df6da 70 schedule_delayed_work(&auth->work, IEEE80211SOFTMAC_AUTH_TIMEOUT);
370121e5
JB
71 auth->retry--;
72 spin_unlock_irqrestore(&mac->lock, flags);
73 if (ieee80211softmac_send_mgt_frame(mac, auth->net, IEEE80211_STYPE_AUTH, auth->state))
74 dprintk(KERN_NOTICE PFX "Sending Authentication Request to "MAC_FMT" failed (this shouldn't happen, wait for the timeout).\n", MAC_ARG(net->bssid));
75 else
76 dprintk(KERN_NOTICE PFX "Sent Authentication Request to "MAC_FMT".\n", MAC_ARG(net->bssid));
77 return;
78 }
79
80 printkl(KERN_WARNING PFX "Authentication timed out with "MAC_FMT"\n", MAC_ARG(net->bssid));
81 /* Remove this item from the queue */
82 spin_lock_irqsave(&mac->lock, flags);
83 ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT, net);
84 cancel_delayed_work(&auth->work); /* just to make sure... */
85 list_del(&auth->list);
86 spin_unlock_irqrestore(&mac->lock, flags);
87 /* Free it */
88 kfree(auth);
89}
90
91/* Handle the auth response from the AP
92 * This should be registered with ieee80211 as handle_auth
93 */
94int
95ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
96{
97
98 struct list_head *list_ptr;
99 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
100 struct ieee80211softmac_auth_queue_item *aq = NULL;
101 struct ieee80211softmac_network *net = NULL;
102 unsigned long flags;
103 u8 * data;
104
105 function_enter();
106
107 /* Find correct auth queue item */
108 spin_lock_irqsave(&mac->lock, flags);
109 list_for_each(list_ptr, &mac->auth_queue) {
110 aq = list_entry(list_ptr, struct ieee80211softmac_auth_queue_item, list);
111 net = aq->net;
112 if (!memcmp(net->bssid, auth->header.addr2, ETH_ALEN))
113 break;
114 else
115 aq = NULL;
116 }
117 spin_unlock_irqrestore(&mac->lock, flags);
118
119 /* Make sure that we've got an auth queue item for this request */
120 if(aq == NULL)
121 {
122 printkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but no queue item exists.\n", MAC_ARG(auth->header.addr2));
123 /* Error #? */
124 return -1;
125 }
126
127 /* Check for out of order authentication */
128 if(!net->authenticating)
129 {
130 printkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but did not request authentication.\n",MAC_ARG(auth->header.addr2));
131 return -1;
132 }
133
134 /* Parse the auth packet */
135 switch(auth->algorithm) {
136 case WLAN_AUTH_OPEN:
137 /* Check the status code of the response */
138
139 switch(auth->status) {
140 case WLAN_STATUS_SUCCESS:
141 /* Update the status to Authenticated */
142 spin_lock_irqsave(&mac->lock, flags);
143 net->authenticating = 0;
144 net->authenticated = 1;
145 spin_unlock_irqrestore(&mac->lock, flags);
146
147 /* Send event */
148 printkl(KERN_NOTICE PFX "Open Authentication completed with "MAC_FMT"\n", MAC_ARG(net->bssid));
149 ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net);
150 break;
151 default:
152 /* Lock and reset flags */
153 spin_lock_irqsave(&mac->lock, flags);
154 net->authenticated = 0;
155 net->authenticating = 0;
156 spin_unlock_irqrestore(&mac->lock, flags);
157
158 printkl(KERN_NOTICE PFX "Open Authentication with "MAC_FMT" failed, error code: %i\n",
159 MAC_ARG(net->bssid), le16_to_cpup(&auth->status));
160 /* Count the error? */
161 break;
162 }
163 goto free_aq;
164 break;
165 case WLAN_AUTH_SHARED_KEY:
166 /* Figure out where we are in the process */
167 switch(auth->transaction) {
168 case IEEE80211SOFTMAC_AUTH_SHARED_CHALLENGE:
169 /* Check to make sure we have a challenge IE */
170 data = (u8 *)auth->info_element;
171 if(*data++ != MFIE_TYPE_CHALLENGE){
172 printkl(KERN_NOTICE PFX "Shared Key Authentication failed due to a missing challenge.\n");
173 break;
174 }
175 /* Save the challenge */
176 spin_lock_irqsave(&mac->lock, flags);
177 net->challenge_len = *data++;
178 if(net->challenge_len > WLAN_AUTH_CHALLENGE_LEN)
179 net->challenge_len = WLAN_AUTH_CHALLENGE_LEN;
180 if(net->challenge != NULL)
181 kfree(net->challenge);
182 net->challenge = kmalloc(net->challenge_len, GFP_ATOMIC);
183 memcpy(net->challenge, data, net->challenge_len);
184 aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE;
185 spin_unlock_irqrestore(&mac->lock, flags);
186
187 /* Switch to correct channel for this network */
188 mac->set_channel(mac->dev, net->channel);
189
190 /* Send our response (How to encrypt?) */
191 ieee80211softmac_send_mgt_frame(mac, aq->net, IEEE80211_STYPE_AUTH, aq->state);
192 break;
193 case IEEE80211SOFTMAC_AUTH_SHARED_PASS:
194 /* Check the status code of the response */
195 switch(auth->status) {
196 case WLAN_STATUS_SUCCESS:
197 /* Update the status to Authenticated */
198 spin_lock_irqsave(&mac->lock, flags);
199 net->authenticating = 0;
200 net->authenticated = 1;
201 spin_unlock_irqrestore(&mac->lock, flags);
202 printkl(KERN_NOTICE PFX "Shared Key Authentication completed with "MAC_FMT"\n",
203 MAC_ARG(net->bssid));
204 break;
205 default:
206 printkl(KERN_NOTICE PFX "Shared Key Authentication with "MAC_FMT" failed, error code: %i\n",
207 MAC_ARG(net->bssid), le16_to_cpup(&auth->status));
208 /* Lock and reset flags */
209 spin_lock_irqsave(&mac->lock, flags);
210 net->authenticating = 0;
211 net->authenticated = 0;
212 spin_unlock_irqrestore(&mac->lock, flags);
213 /* Count the error? */
214 break;
215 }
216 goto free_aq;
217 break;
218 default:
219 printkl(KERN_WARNING PFX "Unhandled Authentication Step: %i\n", auth->transaction);
220 break;
221 }
222 goto free_aq;
223 break;
224 default:
225 /* ERROR */
226 goto free_aq;
227 break;
228 }
229 return 0;
230free_aq:
231 /* Cancel the timeout */
232 spin_lock_irqsave(&mac->lock, flags);
233 cancel_delayed_work(&aq->work);
234 /* Remove this item from the queue */
235 list_del(&aq->list);
236 spin_unlock_irqrestore(&mac->lock, flags);
237
238 /* Free it */
239 kfree(aq);
240 return 0;
241}
242
243/*
244 * Handle deauthorization
245 */
714e1a51 246static void
370121e5
JB
247ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac,
248 struct ieee80211softmac_network *net)
249{
250 struct ieee80211softmac_auth_queue_item *aq = NULL;
251 struct list_head *list_ptr;
252 unsigned long flags;
253
254 function_enter();
255
256 /* Lock and reset status flags */
257 spin_lock_irqsave(&mac->lock, flags);
258 net->authenticating = 0;
259 net->authenticated = 0;
260
261 /* Find correct auth queue item, if it exists */
262 list_for_each(list_ptr, &mac->auth_queue) {
263 aq = list_entry(list_ptr, struct ieee80211softmac_auth_queue_item, list);
264 if (!memcmp(net->bssid, aq->net->bssid, ETH_ALEN))
265 break;
266 else
267 aq = NULL;
268 }
269
270 /* Cancel pending work */
271 if(aq != NULL)
272 /* Not entirely safe? What about running work? */
273 cancel_delayed_work(&aq->work);
274
275 /* Free our network ref */
276 ieee80211softmac_del_network_locked(mac, net);
277 if(net->challenge != NULL)
278 kfree(net->challenge);
279 kfree(net);
280
281 /* let's try to re-associate */
5c4df6da 282 schedule_work(&mac->associnfo.work);
370121e5
JB
283 spin_unlock_irqrestore(&mac->lock, flags);
284}
285
286/*
287 * Sends a deauth request to the desired AP
288 */
289int
290ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac,
291 struct ieee80211softmac_network *net, int reason)
292{
293 int ret;
294
295 function_enter();
296
297 /* Make sure the network is authenticated */
298 if (!net->authenticated)
299 {
300 printkl(KERN_DEBUG PFX "Can't send deauthentication packet, network is not authenticated.\n");
301 /* Error okay? */
302 return -EPERM;
303 }
304
305 /* Send the de-auth packet */
306 if((ret = ieee80211softmac_send_mgt_frame(mac, net, IEEE80211_STYPE_DEAUTH, reason)))
307 return ret;
308
309 ieee80211softmac_deauth_from_net(mac, net);
310 return 0;
311}
312
313/*
314 * This should be registered with ieee80211 as handle_deauth
315 */
316int
317ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_auth *auth)
318{
319
320 struct ieee80211softmac_network *net = NULL;
321 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
322
323 function_enter();
324
325 if (!auth) {
326 dprintk("deauth without deauth packet. eek!\n");
327 return 0;
328 }
329
330 net = ieee80211softmac_get_network_by_bssid(mac, auth->header.addr2);
331
332 if (net == NULL) {
333 printkl(KERN_DEBUG PFX "Recieved deauthentication packet from "MAC_FMT", but that network is unknown.\n",
334 MAC_ARG(auth->header.addr2));
335 return 0;
336 }
337
338 /* Make sure the network is authenticated */
339 if(!net->authenticated)
340 {
341 printkl(KERN_DEBUG PFX "Can't perform deauthentication, network is not authenticated.\n");
342 /* Error okay? */
343 return -EPERM;
344 }
345
346 ieee80211softmac_deauth_from_net(mac, net);
347 return 0;
348}
This page took 0.056246 seconds and 5 git commands to generate.