diff options
Diffstat (limited to 'net/ieee80211/softmac/ieee80211softmac_io.c')
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_io.c | 169 |
1 files changed, 75 insertions, 94 deletions
diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c index cc6cd56c85b1..09541611e48c 100644 --- a/net/ieee80211/softmac/ieee80211softmac_io.c +++ b/net/ieee80211/softmac/ieee80211softmac_io.c | |||
@@ -149,6 +149,56 @@ ieee80211softmac_hdr_3addr(struct ieee80211softmac_device *mac, | |||
149 | * shouldn't the sequence number be in ieee80211? */ | 149 | * shouldn't the sequence number be in ieee80211? */ |
150 | } | 150 | } |
151 | 151 | ||
152 | static u16 | ||
153 | ieee80211softmac_capabilities(struct ieee80211softmac_device *mac, | ||
154 | struct ieee80211softmac_network *net) | ||
155 | { | ||
156 | u16 capability = 0; | ||
157 | |||
158 | /* ESS and IBSS bits are set according to the current mode */ | ||
159 | switch (mac->ieee->iw_mode) { | ||
160 | case IW_MODE_INFRA: | ||
161 | capability = cpu_to_le16(WLAN_CAPABILITY_ESS); | ||
162 | break; | ||
163 | case IW_MODE_ADHOC: | ||
164 | capability = cpu_to_le16(WLAN_CAPABILITY_IBSS); | ||
165 | break; | ||
166 | case IW_MODE_AUTO: | ||
167 | capability = net->capabilities & | ||
168 | (WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS); | ||
169 | break; | ||
170 | default: | ||
171 | /* bleh. we don't ever go to these modes */ | ||
172 | printk(KERN_ERR PFX "invalid iw_mode!\n"); | ||
173 | break; | ||
174 | } | ||
175 | |||
176 | /* CF Pollable / CF Poll Request */ | ||
177 | /* Needs to be implemented, for now, the 0's == not supported */ | ||
178 | |||
179 | /* Privacy Bit */ | ||
180 | capability |= mac->ieee->sec.level ? | ||
181 | cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0; | ||
182 | |||
183 | /* Short Preamble */ | ||
184 | /* Always supported: we probably won't ever be powering devices which | ||
185 | * dont support this... */ | ||
186 | capability |= WLAN_CAPABILITY_SHORT_PREAMBLE; | ||
187 | |||
188 | /* PBCC */ | ||
189 | /* Not widely used */ | ||
190 | |||
191 | /* Channel Agility */ | ||
192 | /* Not widely used */ | ||
193 | |||
194 | /* Short Slot */ | ||
195 | /* Will be implemented later */ | ||
196 | |||
197 | /* DSSS-OFDM */ | ||
198 | /* Not widely used */ | ||
199 | |||
200 | return capability; | ||
201 | } | ||
152 | 202 | ||
153 | /***************************************************************************** | 203 | /***************************************************************************** |
154 | * Create Management packets | 204 | * Create Management packets |
@@ -179,27 +229,6 @@ ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt, | |||
179 | return 0; | 229 | return 0; |
180 | ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid); | 230 | ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid); |
181 | 231 | ||
182 | /* Fill in capability Info */ | ||
183 | switch (mac->ieee->iw_mode) { | ||
184 | case IW_MODE_INFRA: | ||
185 | (*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_ESS); | ||
186 | break; | ||
187 | case IW_MODE_ADHOC: | ||
188 | (*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_IBSS); | ||
189 | break; | ||
190 | case IW_MODE_AUTO: | ||
191 | (*pkt)->capability = net->capabilities & (WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS); | ||
192 | break; | ||
193 | default: | ||
194 | /* bleh. we don't ever go to these modes */ | ||
195 | printk(KERN_ERR PFX "invalid iw_mode!\n"); | ||
196 | break; | ||
197 | } | ||
198 | /* Need to add this | ||
199 | (*pkt)->capability |= mac->ieee->short_slot ? | ||
200 | cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0; | ||
201 | */ | ||
202 | (*pkt)->capability |= mac->ieee->sec.level ? cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0; | ||
203 | /* Fill in Listen Interval (?) */ | 232 | /* Fill in Listen Interval (?) */ |
204 | (*pkt)->listen_interval = cpu_to_le16(10); | 233 | (*pkt)->listen_interval = cpu_to_le16(10); |
205 | 234 | ||
@@ -239,17 +268,9 @@ ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt, | |||
239 | return 0; | 268 | return 0; |
240 | ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_REASSOC_REQ, net->bssid, net->bssid); | 269 | ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_REASSOC_REQ, net->bssid, net->bssid); |
241 | 270 | ||
242 | /* Fill in capability Info */ | 271 | /* Fill in the capabilities */ |
243 | (*pkt)->capability = mac->ieee->iw_mode == IW_MODE_MASTER ? | 272 | (*pkt)->capability = ieee80211softmac_capabilities(mac, net); |
244 | cpu_to_le16(WLAN_CAPABILITY_ESS) : | 273 | |
245 | cpu_to_le16(WLAN_CAPABILITY_IBSS); | ||
246 | /* | ||
247 | (*pkt)->capability |= mac->ieee->short_slot ? | ||
248 | cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0; | ||
249 | */ | ||
250 | (*pkt)->capability |= mac->ieee->sec.level ? | ||
251 | cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0; | ||
252 | |||
253 | /* Fill in Listen Interval (?) */ | 274 | /* Fill in Listen Interval (?) */ |
254 | (*pkt)->listen_interval = cpu_to_le16(10); | 275 | (*pkt)->listen_interval = cpu_to_le16(10); |
255 | /* Fill in the current AP MAC */ | 276 | /* Fill in the current AP MAC */ |
@@ -268,26 +289,27 @@ ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt, | |||
268 | static u32 | 289 | static u32 |
269 | ieee80211softmac_auth(struct ieee80211_auth **pkt, | 290 | ieee80211softmac_auth(struct ieee80211_auth **pkt, |
270 | struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net, | 291 | struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net, |
271 | u16 transaction, u16 status) | 292 | u16 transaction, u16 status, int *encrypt_mpdu) |
272 | { | 293 | { |
273 | u8 *data; | 294 | u8 *data; |
295 | int auth_mode = mac->ieee->sec.auth_mode; | ||
296 | int is_shared_response = (auth_mode == WLAN_AUTH_SHARED_KEY | ||
297 | && transaction == IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE); | ||
298 | |||
274 | /* Allocate Packet */ | 299 | /* Allocate Packet */ |
275 | (*pkt) = (struct ieee80211_auth *)ieee80211softmac_alloc_mgt( | 300 | (*pkt) = (struct ieee80211_auth *)ieee80211softmac_alloc_mgt( |
276 | 2 + /* Auth Algorithm */ | 301 | 2 + /* Auth Algorithm */ |
277 | 2 + /* Auth Transaction Seq */ | 302 | 2 + /* Auth Transaction Seq */ |
278 | 2 + /* Status Code */ | 303 | 2 + /* Status Code */ |
279 | /* Challenge Text IE */ | 304 | /* Challenge Text IE */ |
280 | mac->ieee->open_wep ? 0 : | 305 | is_shared_response ? 0 : 1 + 1 + net->challenge_len |
281 | 1 + 1 + WLAN_AUTH_CHALLENGE_LEN | 306 | ); |
282 | ); | ||
283 | if (unlikely((*pkt) == NULL)) | 307 | if (unlikely((*pkt) == NULL)) |
284 | return 0; | 308 | return 0; |
285 | ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_AUTH, net->bssid, net->bssid); | 309 | ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_AUTH, net->bssid, net->bssid); |
286 | 310 | ||
287 | /* Algorithm */ | 311 | /* Algorithm */ |
288 | (*pkt)->algorithm = mac->ieee->open_wep ? | 312 | (*pkt)->algorithm = cpu_to_le16(auth_mode); |
289 | cpu_to_le16(WLAN_AUTH_OPEN) : | ||
290 | cpu_to_le16(WLAN_AUTH_SHARED_KEY); | ||
291 | /* Transaction */ | 313 | /* Transaction */ |
292 | (*pkt)->transaction = cpu_to_le16(transaction); | 314 | (*pkt)->transaction = cpu_to_le16(transaction); |
293 | /* Status */ | 315 | /* Status */ |
@@ -295,18 +317,20 @@ ieee80211softmac_auth(struct ieee80211_auth **pkt, | |||
295 | 317 | ||
296 | data = (u8 *)(*pkt)->info_element; | 318 | data = (u8 *)(*pkt)->info_element; |
297 | /* Challenge Text */ | 319 | /* Challenge Text */ |
298 | if(!mac->ieee->open_wep){ | 320 | if (is_shared_response) { |
299 | *data = MFIE_TYPE_CHALLENGE; | 321 | *data = MFIE_TYPE_CHALLENGE; |
300 | data++; | 322 | data++; |
301 | 323 | ||
302 | /* Copy the challenge in */ | 324 | /* Copy the challenge in */ |
303 | // *data = challenge length | 325 | *data = net->challenge_len; |
304 | // data += sizeof(u16); | 326 | data++; |
305 | // memcpy(data, challenge, challenge length); | 327 | memcpy(data, net->challenge, net->challenge_len); |
306 | // data += challenge length; | 328 | data += net->challenge_len; |
307 | 329 | ||
308 | /* Add the full size to the packet length */ | 330 | /* Make sure this frame gets encrypted with the shared key */ |
309 | } | 331 | *encrypt_mpdu = 1; |
332 | } else | ||
333 | *encrypt_mpdu = 0; | ||
310 | 334 | ||
311 | /* Return the packet size */ | 335 | /* Return the packet size */ |
312 | return (data - (u8 *)(*pkt)); | 336 | return (data - (u8 *)(*pkt)); |
@@ -396,6 +420,7 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac, | |||
396 | { | 420 | { |
397 | void *pkt = NULL; | 421 | void *pkt = NULL; |
398 | u32 pkt_size = 0; | 422 | u32 pkt_size = 0; |
423 | int encrypt_mpdu = 0; | ||
399 | 424 | ||
400 | switch(type) { | 425 | switch(type) { |
401 | case IEEE80211_STYPE_ASSOC_REQ: | 426 | case IEEE80211_STYPE_ASSOC_REQ: |
@@ -405,7 +430,7 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac, | |||
405 | pkt_size = ieee80211softmac_reassoc_req((struct ieee80211_reassoc_request **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg); | 430 | pkt_size = ieee80211softmac_reassoc_req((struct ieee80211_reassoc_request **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg); |
406 | break; | 431 | break; |
407 | case IEEE80211_STYPE_AUTH: | 432 | case IEEE80211_STYPE_AUTH: |
408 | pkt_size = ieee80211softmac_auth((struct ieee80211_auth **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, (u16)(arg & 0xFFFF), (u16) (arg >> 16)); | 433 | pkt_size = ieee80211softmac_auth((struct ieee80211_auth **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, (u16)(arg & 0xFFFF), (u16) (arg >> 16), &encrypt_mpdu); |
409 | break; | 434 | break; |
410 | case IEEE80211_STYPE_DISASSOC: | 435 | case IEEE80211_STYPE_DISASSOC: |
411 | case IEEE80211_STYPE_DEAUTH: | 436 | case IEEE80211_STYPE_DEAUTH: |
@@ -434,52 +459,8 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac, | |||
434 | * or get rid of it alltogether? | 459 | * or get rid of it alltogether? |
435 | * Does this work for you now? | 460 | * Does this work for you now? |
436 | */ | 461 | */ |
437 | ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *)pkt, pkt_size); | 462 | ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *)pkt, |
438 | 463 | IEEE80211_3ADDR_LEN, pkt_size, encrypt_mpdu); | |
439 | kfree(pkt); | ||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | |||
444 | /* Create an rts/cts frame */ | ||
445 | static u32 | ||
446 | ieee80211softmac_rts_cts(struct ieee80211_hdr_2addr **pkt, | ||
447 | struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net, | ||
448 | u32 type) | ||
449 | { | ||
450 | /* Allocate Packet */ | ||
451 | (*pkt) = kmalloc(IEEE80211_2ADDR_LEN, GFP_ATOMIC); | ||
452 | memset(*pkt, 0, IEEE80211_2ADDR_LEN); | ||
453 | if((*pkt) == NULL) | ||
454 | return 0; | ||
455 | ieee80211softmac_hdr_2addr(mac, (*pkt), type, net->bssid); | ||
456 | return IEEE80211_2ADDR_LEN; | ||
457 | } | ||
458 | |||
459 | |||
460 | /* Sends a control packet */ | ||
461 | static int | ||
462 | ieee80211softmac_send_ctl_frame(struct ieee80211softmac_device *mac, | ||
463 | struct ieee80211softmac_network *net, u32 type, u32 arg) | ||
464 | { | ||
465 | void *pkt = NULL; | ||
466 | u32 pkt_size = 0; | ||
467 | |||
468 | switch(type) { | ||
469 | case IEEE80211_STYPE_RTS: | ||
470 | case IEEE80211_STYPE_CTS: | ||
471 | pkt_size = ieee80211softmac_rts_cts((struct ieee80211_hdr_2addr **)(&pkt), mac, net, type); | ||
472 | break; | ||
473 | default: | ||
474 | printkl(KERN_DEBUG PFX "Unsupported Control Frame type: %i\n", type); | ||
475 | return -EINVAL; | ||
476 | } | ||
477 | |||
478 | if(pkt_size == 0) | ||
479 | return -ENOMEM; | ||
480 | |||
481 | /* Send the packet to the ieee80211 layer for tx */ | ||
482 | ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *) pkt, pkt_size); | ||
483 | 464 | ||
484 | kfree(pkt); | 465 | kfree(pkt); |
485 | return 0; | 466 | return 0; |