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
);