1 #include "ieee80211softmac_priv.h"
3 static void ieee80211softmac_auth_queue(void *data);
5 /* Queues an auth request to the desired AP */
7 ieee80211softmac_auth_req(struct ieee80211softmac_device *mac,
8 struct ieee80211softmac_network *net)
10 struct ieee80211softmac_auth_queue_item *auth;
15 if (net->authenticating)
18 /* Add the network if it's not already added */
19 ieee80211softmac_add_network(mac, net);
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);
30 auth->retry = IEEE80211SOFTMAC_AUTH_RETRY_LIMIT;
31 auth->state = IEEE80211SOFTMAC_AUTH_OPEN_REQUEST;
32 INIT_WORK(&auth->work, &ieee80211softmac_auth_queue, (void *)auth);
35 spin_lock_irqsave(&mac->lock, flags);
38 list_add_tail(&auth->list, &mac->auth_queue);
39 queue_work(mac->workqueue, &auth->work);
40 spin_unlock_irqrestore(&mac->lock, flags);
46 /* Sends an auth request to the desired AP and handles timeouts */
48 ieee80211softmac_auth_queue(void *data)
50 struct ieee80211softmac_device *mac;
51 struct ieee80211softmac_auth_queue_item *auth;
52 struct ieee80211softmac_network *net;
57 auth = (struct ieee80211softmac_auth_queue_item *)data;
62 /* Switch to correct channel for this network */
63 mac->set_channel(mac->dev, net->channel);
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 */
70 queue_delayed_work(mac->workqueue, &auth->work, IEEE80211SOFTMAC_AUTH_TIMEOUT);
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));
76 dprintk(KERN_NOTICE PFX "Sent Authentication Request to "MAC_FMT".\n", MAC_ARG(net->bssid));
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);
91 /* Handle the auth response from the AP
92 * This should be registered with ieee80211 as handle_auth
95 ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
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;
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);
112 if (!memcmp(net->bssid, auth->header.addr2, ETH_ALEN))
117 spin_unlock_irqrestore(&mac->lock, flags);
119 /* Make sure that we've got an auth queue item for this request */
122 printkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but no queue item exists.\n", MAC_ARG(auth->header.addr2));
127 /* Check for out of order authentication */
128 if(!net->authenticating)
130 printkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but did not request authentication.\n",MAC_ARG(auth->header.addr2));
134 /* Parse the auth packet */
135 switch(auth->algorithm) {
137 /* Check the status code of the response */
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);
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);
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);
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? */
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");
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);
187 /* Switch to correct channel for this network */
188 mac->set_channel(mac->dev, net->channel);
190 /* Send our response (How to encrypt?) */
191 ieee80211softmac_send_mgt_frame(mac, aq->net, IEEE80211_STYPE_AUTH, aq->state);
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));
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? */
219 printkl(KERN_WARNING PFX "Unhandled Authentication Step: %i\n", auth->transaction);
231 /* Cancel the timeout */
232 spin_lock_irqsave(&mac->lock, flags);
233 cancel_delayed_work(&aq->work);
234 /* Remove this item from the queue */
236 spin_unlock_irqrestore(&mac->lock, flags);
244 * Handle deauthorization
247 ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac,
248 struct ieee80211softmac_network *net)
250 struct ieee80211softmac_auth_queue_item *aq = NULL;
251 struct list_head *list_ptr;
256 /* Lock and reset status flags */
257 spin_lock_irqsave(&mac->lock, flags);
258 net->authenticating = 0;
259 net->authenticated = 0;
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))
270 /* Cancel pending work */
272 /* Not entirely safe? What about running work? */
273 cancel_delayed_work(&aq->work);
275 /* Free our network ref */
276 ieee80211softmac_del_network_locked(mac, net);
277 if(net->challenge != NULL)
278 kfree(net->challenge);
281 /* let's try to re-associate */
282 queue_work(mac->workqueue, &mac->associnfo.work);
283 spin_unlock_irqrestore(&mac->lock, flags);
287 * Sends a deauth request to the desired AP
290 ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac,
291 struct ieee80211softmac_network *net, int reason)
297 /* Make sure the network is authenticated */
298 if (!net->authenticated)
300 printkl(KERN_DEBUG PFX "Can't send deauthentication packet, network is not authenticated.\n");
305 /* Send the de-auth packet */
306 if((ret = ieee80211softmac_send_mgt_frame(mac, net, IEEE80211_STYPE_DEAUTH, reason)))
309 ieee80211softmac_deauth_from_net(mac, net);
314 * This should be registered with ieee80211 as handle_deauth
317 ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_auth *auth)
320 struct ieee80211softmac_network *net = NULL;
321 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
326 dprintk("deauth without deauth packet. eek!\n");
330 net = ieee80211softmac_get_network_by_bssid(mac, auth->header.addr2);
333 printkl(KERN_DEBUG PFX "Recieved deauthentication packet from "MAC_FMT", but that network is unknown.\n",
334 MAC_ARG(auth->header.addr2));
338 /* Make sure the network is authenticated */
339 if(!net->authenticated)
341 printkl(KERN_DEBUG PFX "Can't perform deauthentication, network is not authenticated.\n");
346 ieee80211softmac_deauth_from_net(mac, net);