OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [net/] [ieee80211/] [softmac/] [ieee80211softmac_auth.c] - Blame information for rev 67

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * This file contains the softmac's authentication logic.
3
 *
4
 * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
5
 *                          Joseph Jezak <josejx@gentoo.org>
6
 *                          Larry Finger <Larry.Finger@lwfinger.net>
7
 *                          Danny van Dyk <kugelfang@gentoo.org>
8
 *                          Michael Buesch <mbuesch@freenet.de>
9
 *
10
 * This program is free software; you can redistribute it and/or modify it
11
 * under the terms of version 2 of the GNU General Public License as
12
 * published by the Free Software Foundation.
13
 *
14
 * This program is distributed in the hope that it will be useful, but WITHOUT
15
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
17
 * more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
22
 *
23
 * The full GNU General Public License is included in this distribution in the
24
 * file called COPYING.
25
 */
26
 
27
#include "ieee80211softmac_priv.h"
28
 
29
static void ieee80211softmac_auth_queue(struct work_struct *work);
30
 
31
/* Queues an auth request to the desired AP */
32
int
33
ieee80211softmac_auth_req(struct ieee80211softmac_device *mac,
34
        struct ieee80211softmac_network *net)
35
{
36
        struct ieee80211softmac_auth_queue_item *auth;
37
        unsigned long flags;
38
        DECLARE_MAC_BUF(mac2);
39
 
40
        if (net->authenticating || net->authenticated)
41
                return 0;
42
        net->authenticating = 1;
43
 
44
        /* Add the network if it's not already added */
45
        ieee80211softmac_add_network(mac, net);
46
 
47
        dprintk(KERN_NOTICE PFX "Queueing Authentication Request to %s\n", print_mac(mac2, net->bssid));
48
        /* Queue the auth request */
49
        auth = (struct ieee80211softmac_auth_queue_item *)
50
                kmalloc(sizeof(struct ieee80211softmac_auth_queue_item), GFP_KERNEL);
51
        if(auth == NULL)
52
                return -ENOMEM;
53
 
54
        auth->net = net;
55
        auth->mac = mac;
56
        auth->retry = IEEE80211SOFTMAC_AUTH_RETRY_LIMIT;
57
        auth->state = IEEE80211SOFTMAC_AUTH_OPEN_REQUEST;
58
        INIT_DELAYED_WORK(&auth->work, ieee80211softmac_auth_queue);
59
 
60
        /* Lock (for list) */
61
        spin_lock_irqsave(&mac->lock, flags);
62
 
63
        /* add to list */
64
        list_add_tail(&auth->list, &mac->auth_queue);
65
        queue_delayed_work(mac->wq, &auth->work, 0);
66
        spin_unlock_irqrestore(&mac->lock, flags);
67
 
68
        return 0;
69
}
70
 
71
 
72
/* Sends an auth request to the desired AP and handles timeouts */
73
static void
74
ieee80211softmac_auth_queue(struct work_struct *work)
75
{
76
        struct ieee80211softmac_device *mac;
77
        struct ieee80211softmac_auth_queue_item *auth;
78
        struct ieee80211softmac_network *net;
79
        unsigned long flags;
80
        DECLARE_MAC_BUF(mac2);
81
 
82
        auth = container_of(work, struct ieee80211softmac_auth_queue_item,
83
                            work.work);
84
        net = auth->net;
85
        mac = auth->mac;
86
 
87
        if(auth->retry > 0) {
88
                /* Switch to correct channel for this network */
89
                mac->set_channel(mac->dev, net->channel);
90
 
91
                /* Lock and set flags */
92
                spin_lock_irqsave(&mac->lock, flags);
93
                if (unlikely(!mac->running)) {
94
                        /* Prevent reschedule on workqueue flush */
95
                        spin_unlock_irqrestore(&mac->lock, flags);
96
                        return;
97
                }
98
                net->authenticated = 0;
99
                /* add a timeout call so we eventually give up waiting for an auth reply */
100
                queue_delayed_work(mac->wq, &auth->work, IEEE80211SOFTMAC_AUTH_TIMEOUT);
101
                auth->retry--;
102
                spin_unlock_irqrestore(&mac->lock, flags);
103
                if (ieee80211softmac_send_mgt_frame(mac, auth->net, IEEE80211_STYPE_AUTH, auth->state))
104
                        dprintk(KERN_NOTICE PFX "Sending Authentication Request to %s failed (this shouldn't happen, wait for the timeout).\n",
105
                                print_mac(mac2, net->bssid));
106
                else
107
                        dprintk(KERN_NOTICE PFX "Sent Authentication Request to %s.\n", print_mac(mac2, net->bssid));
108
                return;
109
        }
110
 
111
        printkl(KERN_WARNING PFX "Authentication timed out with %s\n", print_mac(mac2, net->bssid));
112
        /* Remove this item from the queue */
113
        spin_lock_irqsave(&mac->lock, flags);
114
        net->authenticating = 0;
115
        ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT, net);
116
        cancel_delayed_work(&auth->work); /* just to make sure... */
117
        list_del(&auth->list);
118
        spin_unlock_irqrestore(&mac->lock, flags);
119
        /* Free it */
120
        kfree(auth);
121
}
122
 
123
/* Sends a response to an auth challenge (for shared key auth). */
124
static void
125
ieee80211softmac_auth_challenge_response(struct work_struct *work)
126
{
127
        struct ieee80211softmac_auth_queue_item *aq =
128
                container_of(work, struct ieee80211softmac_auth_queue_item,
129
                             work.work);
130
 
131
        /* Send our response */
132
        ieee80211softmac_send_mgt_frame(aq->mac, aq->net, IEEE80211_STYPE_AUTH, aq->state);
133
}
134
 
135
/* Handle the auth response from the AP
136
 * This should be registered with ieee80211 as handle_auth
137
 */
138
int
139
ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
140
{
141
 
142
        struct list_head *list_ptr;
143
        struct ieee80211softmac_device *mac = ieee80211_priv(dev);
144
        struct ieee80211softmac_auth_queue_item *aq = NULL;
145
        struct ieee80211softmac_network *net = NULL;
146
        unsigned long flags;
147
        u8 * data;
148
        DECLARE_MAC_BUF(mac2);
149
 
150
        if (unlikely(!mac->running))
151
                return -ENODEV;
152
 
153
        /* Find correct auth queue item */
154
        spin_lock_irqsave(&mac->lock, flags);
155
        list_for_each(list_ptr, &mac->auth_queue) {
156
                aq = list_entry(list_ptr, struct ieee80211softmac_auth_queue_item, list);
157
                net = aq->net;
158
                if (!memcmp(net->bssid, auth->header.addr2, ETH_ALEN))
159
                        break;
160
                else
161
                        aq = NULL;
162
        }
163
        spin_unlock_irqrestore(&mac->lock, flags);
164
 
165
        /* Make sure that we've got an auth queue item for this request */
166
        if(aq == NULL)
167
        {
168
                dprintkl(KERN_DEBUG PFX "Authentication response received from %s but no queue item exists.\n", print_mac(mac2, auth->header.addr2));
169
                /* Error #? */
170
                return -1;
171
        }
172
 
173
        /* Check for out of order authentication */
174
        if(!net->authenticating)
175
        {
176
                dprintkl(KERN_DEBUG PFX "Authentication response received from %s but did not request authentication.\n",print_mac(mac2, auth->header.addr2));
177
                return -1;
178
        }
179
 
180
        /* Parse the auth packet */
181
        switch(auth->algorithm) {
182
        case WLAN_AUTH_OPEN:
183
                /* Check the status code of the response */
184
 
185
                switch(auth->status) {
186
                case WLAN_STATUS_SUCCESS:
187
                        /* Update the status to Authenticated */
188
                        spin_lock_irqsave(&mac->lock, flags);
189
                        net->authenticating = 0;
190
                        net->authenticated = 1;
191
                        spin_unlock_irqrestore(&mac->lock, flags);
192
 
193
                        /* Send event */
194
                        printkl(KERN_NOTICE PFX "Open Authentication completed with %s\n", print_mac(mac2, net->bssid));
195
                        ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net);
196
                        break;
197
                default:
198
                        /* Lock and reset flags */
199
                        spin_lock_irqsave(&mac->lock, flags);
200
                        net->authenticated = 0;
201
                        net->authenticating = 0;
202
                        spin_unlock_irqrestore(&mac->lock, flags);
203
 
204
                        printkl(KERN_NOTICE PFX "Open Authentication with %s failed, error code: %i\n",
205
                                print_mac(mac2, net->bssid), le16_to_cpup(&auth->status));
206
                        /* Count the error? */
207
                        break;
208
                }
209
                goto free_aq;
210
                break;
211
        case WLAN_AUTH_SHARED_KEY:
212
                /* Figure out where we are in the process */
213
                switch(auth->transaction) {
214
                case IEEE80211SOFTMAC_AUTH_SHARED_CHALLENGE:
215
                        /* Check to make sure we have a challenge IE */
216
                        data = (u8 *)auth->info_element;
217
                        if (*data++ != MFIE_TYPE_CHALLENGE) {
218
                                printkl(KERN_NOTICE PFX "Shared Key Authentication failed due to a missing challenge.\n");
219
                                break;
220
                        }
221
                        /* Save the challenge */
222
                        spin_lock_irqsave(&mac->lock, flags);
223
                        net->challenge_len = *data++;
224
                        if (net->challenge_len > WLAN_AUTH_CHALLENGE_LEN)
225
                                net->challenge_len = WLAN_AUTH_CHALLENGE_LEN;
226
                        kfree(net->challenge);
227
                        net->challenge = kmemdup(data, net->challenge_len,
228
                                                 GFP_ATOMIC);
229
                        if (net->challenge == NULL) {
230
                                printkl(KERN_NOTICE PFX "Shared Key "
231
                                        "Authentication failed due to "
232
                                        "memory shortage.\n");
233
                                spin_unlock_irqrestore(&mac->lock, flags);
234
                                break;
235
                        }
236
                        aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE;
237
 
238
                        /* We reuse the work struct from the auth request here.
239
                         * It is safe to do so as each one is per-request, and
240
                         * at this point (dealing with authentication response)
241
                         * we have obviously already sent the initial auth
242
                         * request. */
243
                        cancel_delayed_work(&aq->work);
244
                        INIT_DELAYED_WORK(&aq->work, &ieee80211softmac_auth_challenge_response);
245
                        queue_delayed_work(mac->wq, &aq->work, 0);
246
                        spin_unlock_irqrestore(&mac->lock, flags);
247
                        return 0;
248
                case IEEE80211SOFTMAC_AUTH_SHARED_PASS:
249
                        kfree(net->challenge);
250
                        net->challenge = NULL;
251
                        net->challenge_len = 0;
252
                        /* Check the status code of the response */
253
                        switch(auth->status) {
254
                        case WLAN_STATUS_SUCCESS:
255
                                /* Update the status to Authenticated */
256
                                spin_lock_irqsave(&mac->lock, flags);
257
                                net->authenticating = 0;
258
                                net->authenticated = 1;
259
                                spin_unlock_irqrestore(&mac->lock, flags);
260
                                printkl(KERN_NOTICE PFX "Shared Key Authentication completed with %s\n",
261
                                        print_mac(mac2, net->bssid));
262
                                ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net);
263
                                break;
264
                        default:
265
                                printkl(KERN_NOTICE PFX "Shared Key Authentication with %s failed, error code: %i\n",
266
                                        print_mac(mac2, net->bssid), le16_to_cpup(&auth->status));
267
                                /* Lock and reset flags */
268
                                spin_lock_irqsave(&mac->lock, flags);
269
                                net->authenticating = 0;
270
                                net->authenticated = 0;
271
                                spin_unlock_irqrestore(&mac->lock, flags);
272
                                /* Count the error? */
273
                                break;
274
                        }
275
                        goto free_aq;
276
                        break;
277
                default:
278
                        printkl(KERN_WARNING PFX "Unhandled Authentication Step: %i\n", auth->transaction);
279
                        break;
280
                }
281
                goto free_aq;
282
                break;
283
        default:
284
                /* ERROR */
285
                goto free_aq;
286
                break;
287
        }
288
        return 0;
289
free_aq:
290
        /* Cancel the timeout */
291
        spin_lock_irqsave(&mac->lock, flags);
292
        cancel_delayed_work(&aq->work);
293
        /* Remove this item from the queue */
294
        list_del(&aq->list);
295
        spin_unlock_irqrestore(&mac->lock, flags);
296
 
297
        /* Free it */
298
        kfree(aq);
299
        return 0;
300
}
301
 
302
/*
303
 * Handle deauthorization
304
 */
305
static void
306
ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac,
307
        struct ieee80211softmac_network *net)
308
{
309
        struct ieee80211softmac_auth_queue_item *aq = NULL;
310
        struct list_head *list_ptr;
311
        unsigned long flags;
312
 
313
        /* deauthentication implies disassociation */
314
        ieee80211softmac_disassoc(mac);
315
 
316
        /* Lock and reset status flags */
317
        spin_lock_irqsave(&mac->lock, flags);
318
        net->authenticating = 0;
319
        net->authenticated = 0;
320
 
321
        /* Find correct auth queue item, if it exists */
322
        list_for_each(list_ptr, &mac->auth_queue) {
323
                aq = list_entry(list_ptr, struct ieee80211softmac_auth_queue_item, list);
324
                if (!memcmp(net->bssid, aq->net->bssid, ETH_ALEN))
325
                        break;
326
                else
327
                        aq = NULL;
328
        }
329
 
330
        /* Cancel pending work */
331
        if(aq != NULL)
332
                /* Not entirely safe?  What about running work? */
333
                cancel_delayed_work(&aq->work);
334
 
335
        /* Free our network ref */
336
        ieee80211softmac_del_network_locked(mac, net);
337
        if(net->challenge != NULL)
338
                kfree(net->challenge);
339
        kfree(net);
340
 
341
        /* can't transmit data right now... */
342
        netif_carrier_off(mac->dev);
343
        spin_unlock_irqrestore(&mac->lock, flags);
344
 
345
        ieee80211softmac_try_reassoc(mac);
346
}
347
 
348
/*
349
 * Sends a deauth request to the desired AP
350
 */
351
int
352
ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac,
353
        struct ieee80211softmac_network *net, int reason)
354
{
355
        int ret;
356
 
357
        /* Make sure the network is authenticated */
358
        if (!net->authenticated)
359
        {
360
                dprintkl(KERN_DEBUG PFX "Can't send deauthentication packet, network is not authenticated.\n");
361
                /* Error okay? */
362
                return -EPERM;
363
        }
364
 
365
        /* Send the de-auth packet */
366
        if((ret = ieee80211softmac_send_mgt_frame(mac, net, IEEE80211_STYPE_DEAUTH, reason)))
367
                return ret;
368
 
369
        ieee80211softmac_deauth_from_net(mac, net);
370
        return 0;
371
}
372
 
373
/*
374
 * This should be registered with ieee80211 as handle_deauth
375
 */
376
int
377
ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *deauth)
378
{
379
 
380
        struct ieee80211softmac_network *net = NULL;
381
        struct ieee80211softmac_device *mac = ieee80211_priv(dev);
382
        DECLARE_MAC_BUF(mac2);
383
 
384
        if (unlikely(!mac->running))
385
                return -ENODEV;
386
 
387
        if (!deauth) {
388
                dprintk("deauth without deauth packet. eek!\n");
389
                return 0;
390
        }
391
 
392
        net = ieee80211softmac_get_network_by_bssid(mac, deauth->header.addr2);
393
 
394
        if (net == NULL) {
395
                dprintkl(KERN_DEBUG PFX "Received deauthentication packet from %s, but that network is unknown.\n",
396
                        print_mac(mac2, deauth->header.addr2));
397
                return 0;
398
        }
399
 
400
        /* Make sure the network is authenticated */
401
        if(!net->authenticated)
402
        {
403
                dprintkl(KERN_DEBUG PFX "Can't perform deauthentication, network is not authenticated.\n");
404
                /* Error okay? */
405
                return -EPERM;
406
        }
407
 
408
        ieee80211softmac_deauth_from_net(mac, net);
409
 
410
        /* let's try to re-associate */
411
        queue_delayed_work(mac->wq, &mac->associnfo.work, 0);
412
        return 0;
413
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.