Merge branch 'upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6 into upstream
This commit is contained in:
@ -555,7 +555,8 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
/* Incoming 802.11 strucure is converted to a TXB
|
||||
* a block of 802.11 fragment packets (stored as skbs) */
|
||||
int ieee80211_tx_frame(struct ieee80211_device *ieee,
|
||||
struct ieee80211_hdr *frame, int len)
|
||||
struct ieee80211_hdr *frame, int hdr_len, int total_len,
|
||||
int encrypt_mpdu)
|
||||
{
|
||||
struct ieee80211_txb *txb = NULL;
|
||||
unsigned long flags;
|
||||
@ -565,6 +566,9 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee,
|
||||
|
||||
spin_lock_irqsave(&ieee->lock, flags);
|
||||
|
||||
if (encrypt_mpdu && !ieee->sec.encrypt)
|
||||
encrypt_mpdu = 0;
|
||||
|
||||
/* If there is no driver handler to take the TXB, dont' bother
|
||||
* creating it... */
|
||||
if (!ieee->hard_start_xmit) {
|
||||
@ -572,32 +576,41 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee,
|
||||
goto success;
|
||||
}
|
||||
|
||||
if (unlikely(len < 24)) {
|
||||
if (unlikely(total_len < 24)) {
|
||||
printk(KERN_WARNING "%s: skb too small (%d).\n",
|
||||
ieee->dev->name, len);
|
||||
ieee->dev->name, total_len);
|
||||
goto success;
|
||||
}
|
||||
|
||||
if (encrypt_mpdu)
|
||||
frame->frame_ctl |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
|
||||
|
||||
/* When we allocate the TXB we allocate enough space for the reserve
|
||||
* and full fragment bytes (bytes_per_frag doesn't include prefix,
|
||||
* postfix, header, FCS, etc.) */
|
||||
txb = ieee80211_alloc_txb(1, len, ieee->tx_headroom, GFP_ATOMIC);
|
||||
txb = ieee80211_alloc_txb(1, total_len, ieee->tx_headroom, GFP_ATOMIC);
|
||||
if (unlikely(!txb)) {
|
||||
printk(KERN_WARNING "%s: Could not allocate TXB\n",
|
||||
ieee->dev->name);
|
||||
goto failed;
|
||||
}
|
||||
txb->encrypted = 0;
|
||||
txb->payload_size = len;
|
||||
txb->payload_size = total_len;
|
||||
|
||||
skb_frag = txb->fragments[0];
|
||||
|
||||
memcpy(skb_put(skb_frag, len), frame, len);
|
||||
memcpy(skb_put(skb_frag, total_len), frame, total_len);
|
||||
|
||||
if (ieee->config &
|
||||
(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
|
||||
skb_put(skb_frag, 4);
|
||||
|
||||
/* To avoid overcomplicating things, we do the corner-case frame
|
||||
* encryption in software. The only real situation where encryption is
|
||||
* needed here is during software-based shared key authentication. */
|
||||
if (encrypt_mpdu)
|
||||
ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
|
||||
|
||||
success:
|
||||
spin_unlock_irqrestore(&ieee->lock, flags);
|
||||
|
||||
|
@ -2,6 +2,7 @@ config IEEE80211_SOFTMAC
|
||||
tristate "Software MAC add-on to the IEEE 802.11 networking stack"
|
||||
depends on IEEE80211 && EXPERIMENTAL
|
||||
select WIRELESS_EXT
|
||||
select IEEE80211_CRYPT_WEP
|
||||
---help---
|
||||
This option enables the hardware independent software MAC addon
|
||||
for the IEEE 802.11 networking stack.
|
||||
|
@ -164,12 +164,28 @@ network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_ne
|
||||
}
|
||||
|
||||
static void
|
||||
ieee80211softmac_assoc_notify(struct net_device *dev, void *context)
|
||||
ieee80211softmac_assoc_notify_scan(struct net_device *dev, int event_type, void *context)
|
||||
{
|
||||
struct ieee80211softmac_device *mac = ieee80211_priv(dev);
|
||||
ieee80211softmac_assoc_work((void*)mac);
|
||||
}
|
||||
|
||||
static void
|
||||
ieee80211softmac_assoc_notify_auth(struct net_device *dev, int event_type, void *context)
|
||||
{
|
||||
struct ieee80211softmac_device *mac = ieee80211_priv(dev);
|
||||
|
||||
switch (event_type) {
|
||||
case IEEE80211SOFTMAC_EVENT_AUTHENTICATED:
|
||||
ieee80211softmac_assoc_work((void*)mac);
|
||||
break;
|
||||
case IEEE80211SOFTMAC_EVENT_AUTH_FAILED:
|
||||
case IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT:
|
||||
ieee80211softmac_disassoc(mac);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is called to handle userspace requests (asynchronously) */
|
||||
void
|
||||
ieee80211softmac_assoc_work(void *d)
|
||||
@ -249,7 +265,7 @@ ieee80211softmac_assoc_work(void *d)
|
||||
* Maybe we can hope to have more memory after scanning finishes ;)
|
||||
*/
|
||||
dprintk(KERN_INFO PFX "Associate: Scanning for networks first.\n");
|
||||
ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify, NULL);
|
||||
ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL);
|
||||
if (ieee80211softmac_start_scan(mac))
|
||||
dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
|
||||
return;
|
||||
@ -284,7 +300,7 @@ ieee80211softmac_assoc_work(void *d)
|
||||
* otherwise adding the notification would be racy. */
|
||||
if (!ieee80211softmac_auth_req(mac, found)) {
|
||||
dprintk(KERN_INFO PFX "cannot associate without being authenticated, requested authentication\n");
|
||||
ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify, NULL, GFP_KERNEL);
|
||||
ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL);
|
||||
} else {
|
||||
printkl(KERN_WARNING PFX "Not authenticated, but requesting authentication failed. Giving up to associate\n");
|
||||
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found);
|
||||
|
@ -107,6 +107,7 @@ ieee80211softmac_auth_queue(void *data)
|
||||
printkl(KERN_WARNING PFX "Authentication timed out with "MAC_FMT"\n", MAC_ARG(net->bssid));
|
||||
/* Remove this item from the queue */
|
||||
spin_lock_irqsave(&mac->lock, flags);
|
||||
net->authenticating = 0;
|
||||
ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT, net);
|
||||
cancel_delayed_work(&auth->work); /* just to make sure... */
|
||||
list_del(&auth->list);
|
||||
@ -212,13 +213,13 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
|
||||
aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE;
|
||||
spin_unlock_irqrestore(&mac->lock, flags);
|
||||
|
||||
/* Switch to correct channel for this network */
|
||||
mac->set_channel(mac->dev, net->channel);
|
||||
|
||||
/* Send our response (How to encrypt?) */
|
||||
/* Send our response */
|
||||
ieee80211softmac_send_mgt_frame(mac, aq->net, IEEE80211_STYPE_AUTH, aq->state);
|
||||
break;
|
||||
return 0;
|
||||
case IEEE80211SOFTMAC_AUTH_SHARED_PASS:
|
||||
kfree(net->challenge);
|
||||
net->challenge = NULL;
|
||||
net->challenge_len = 0;
|
||||
/* Check the status code of the response */
|
||||
switch(auth->status) {
|
||||
case WLAN_STATUS_SUCCESS:
|
||||
@ -229,6 +230,7 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
|
||||
spin_unlock_irqrestore(&mac->lock, flags);
|
||||
printkl(KERN_NOTICE PFX "Shared Key Authentication completed with "MAC_FMT"\n",
|
||||
MAC_ARG(net->bssid));
|
||||
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net);
|
||||
break;
|
||||
default:
|
||||
printkl(KERN_NOTICE PFX "Shared Key Authentication with "MAC_FMT" failed, error code: %i\n",
|
||||
|
@ -78,7 +78,7 @@ ieee80211softmac_notify_callback(void *d)
|
||||
struct ieee80211softmac_event event = *(struct ieee80211softmac_event*) d;
|
||||
kfree(d);
|
||||
|
||||
event.fun(event.mac->dev, event.context);
|
||||
event.fun(event.mac->dev, event.event_type, event.context);
|
||||
}
|
||||
|
||||
int
|
||||
@ -167,6 +167,9 @@ ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int eve
|
||||
if ((eventptr->event_type == event || eventptr->event_type == -1)
|
||||
&& (eventptr->event_context == NULL || eventptr->event_context == event_ctx)) {
|
||||
list_del(&eventptr->list);
|
||||
/* User may have subscribed to ANY event, so
|
||||
* we tell them which event triggered it. */
|
||||
eventptr->event_type = event;
|
||||
schedule_work(&eventptr->work);
|
||||
}
|
||||
}
|
||||
|
@ -149,6 +149,56 @@ ieee80211softmac_hdr_3addr(struct ieee80211softmac_device *mac,
|
||||
* shouldn't the sequence number be in ieee80211? */
|
||||
}
|
||||
|
||||
static u16
|
||||
ieee80211softmac_capabilities(struct ieee80211softmac_device *mac,
|
||||
struct ieee80211softmac_network *net)
|
||||
{
|
||||
u16 capability = 0;
|
||||
|
||||
/* ESS and IBSS bits are set according to the current mode */
|
||||
switch (mac->ieee->iw_mode) {
|
||||
case IW_MODE_INFRA:
|
||||
capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
|
||||
break;
|
||||
case IW_MODE_ADHOC:
|
||||
capability = cpu_to_le16(WLAN_CAPABILITY_IBSS);
|
||||
break;
|
||||
case IW_MODE_AUTO:
|
||||
capability = net->capabilities &
|
||||
(WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS);
|
||||
break;
|
||||
default:
|
||||
/* bleh. we don't ever go to these modes */
|
||||
printk(KERN_ERR PFX "invalid iw_mode!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* CF Pollable / CF Poll Request */
|
||||
/* Needs to be implemented, for now, the 0's == not supported */
|
||||
|
||||
/* Privacy Bit */
|
||||
capability |= mac->ieee->sec.level ?
|
||||
cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0;
|
||||
|
||||
/* Short Preamble */
|
||||
/* Always supported: we probably won't ever be powering devices which
|
||||
* dont support this... */
|
||||
capability |= WLAN_CAPABILITY_SHORT_PREAMBLE;
|
||||
|
||||
/* PBCC */
|
||||
/* Not widely used */
|
||||
|
||||
/* Channel Agility */
|
||||
/* Not widely used */
|
||||
|
||||
/* Short Slot */
|
||||
/* Will be implemented later */
|
||||
|
||||
/* DSSS-OFDM */
|
||||
/* Not widely used */
|
||||
|
||||
return capability;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Create Management packets
|
||||
@ -179,27 +229,6 @@ ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt,
|
||||
return 0;
|
||||
ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid);
|
||||
|
||||
/* Fill in capability Info */
|
||||
switch (mac->ieee->iw_mode) {
|
||||
case IW_MODE_INFRA:
|
||||
(*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
|
||||
break;
|
||||
case IW_MODE_ADHOC:
|
||||
(*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_IBSS);
|
||||
break;
|
||||
case IW_MODE_AUTO:
|
||||
(*pkt)->capability = net->capabilities & (WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS);
|
||||
break;
|
||||
default:
|
||||
/* bleh. we don't ever go to these modes */
|
||||
printk(KERN_ERR PFX "invalid iw_mode!\n");
|
||||
break;
|
||||
}
|
||||
/* Need to add this
|
||||
(*pkt)->capability |= mac->ieee->short_slot ?
|
||||
cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0;
|
||||
*/
|
||||
(*pkt)->capability |= mac->ieee->sec.level ? cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0;
|
||||
/* Fill in Listen Interval (?) */
|
||||
(*pkt)->listen_interval = cpu_to_le16(10);
|
||||
|
||||
@ -239,17 +268,9 @@ ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt,
|
||||
return 0;
|
||||
ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_REASSOC_REQ, net->bssid, net->bssid);
|
||||
|
||||
/* Fill in capability Info */
|
||||
(*pkt)->capability = mac->ieee->iw_mode == IW_MODE_MASTER ?
|
||||
cpu_to_le16(WLAN_CAPABILITY_ESS) :
|
||||
cpu_to_le16(WLAN_CAPABILITY_IBSS);
|
||||
/*
|
||||
(*pkt)->capability |= mac->ieee->short_slot ?
|
||||
cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0;
|
||||
*/
|
||||
(*pkt)->capability |= mac->ieee->sec.level ?
|
||||
cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0;
|
||||
|
||||
/* Fill in the capabilities */
|
||||
(*pkt)->capability = ieee80211softmac_capabilities(mac, net);
|
||||
|
||||
/* Fill in Listen Interval (?) */
|
||||
(*pkt)->listen_interval = cpu_to_le16(10);
|
||||
/* Fill in the current AP MAC */
|
||||
@ -268,26 +289,27 @@ ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt,
|
||||
static u32
|
||||
ieee80211softmac_auth(struct ieee80211_auth **pkt,
|
||||
struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net,
|
||||
u16 transaction, u16 status)
|
||||
u16 transaction, u16 status, int *encrypt_mpdu)
|
||||
{
|
||||
u8 *data;
|
||||
int auth_mode = mac->ieee->sec.auth_mode;
|
||||
int is_shared_response = (auth_mode == WLAN_AUTH_SHARED_KEY
|
||||
&& transaction == IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE);
|
||||
|
||||
/* Allocate Packet */
|
||||
(*pkt) = (struct ieee80211_auth *)ieee80211softmac_alloc_mgt(
|
||||
2 + /* Auth Algorithm */
|
||||
2 + /* Auth Transaction Seq */
|
||||
2 + /* Status Code */
|
||||
/* Challenge Text IE */
|
||||
mac->ieee->open_wep ? 0 :
|
||||
1 + 1 + WLAN_AUTH_CHALLENGE_LEN
|
||||
);
|
||||
is_shared_response ? 0 : 1 + 1 + net->challenge_len
|
||||
);
|
||||
if (unlikely((*pkt) == NULL))
|
||||
return 0;
|
||||
ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_AUTH, net->bssid, net->bssid);
|
||||
|
||||
/* Algorithm */
|
||||
(*pkt)->algorithm = mac->ieee->open_wep ?
|
||||
cpu_to_le16(WLAN_AUTH_OPEN) :
|
||||
cpu_to_le16(WLAN_AUTH_SHARED_KEY);
|
||||
(*pkt)->algorithm = cpu_to_le16(auth_mode);
|
||||
/* Transaction */
|
||||
(*pkt)->transaction = cpu_to_le16(transaction);
|
||||
/* Status */
|
||||
@ -295,18 +317,20 @@ ieee80211softmac_auth(struct ieee80211_auth **pkt,
|
||||
|
||||
data = (u8 *)(*pkt)->info_element;
|
||||
/* Challenge Text */
|
||||
if(!mac->ieee->open_wep){
|
||||
if (is_shared_response) {
|
||||
*data = MFIE_TYPE_CHALLENGE;
|
||||
data++;
|
||||
|
||||
/* Copy the challenge in */
|
||||
// *data = challenge length
|
||||
// data += sizeof(u16);
|
||||
// memcpy(data, challenge, challenge length);
|
||||
// data += challenge length;
|
||||
|
||||
/* Add the full size to the packet length */
|
||||
}
|
||||
*data = net->challenge_len;
|
||||
data++;
|
||||
memcpy(data, net->challenge, net->challenge_len);
|
||||
data += net->challenge_len;
|
||||
|
||||
/* Make sure this frame gets encrypted with the shared key */
|
||||
*encrypt_mpdu = 1;
|
||||
} else
|
||||
*encrypt_mpdu = 0;
|
||||
|
||||
/* Return the packet size */
|
||||
return (data - (u8 *)(*pkt));
|
||||
@ -396,6 +420,7 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
|
||||
{
|
||||
void *pkt = NULL;
|
||||
u32 pkt_size = 0;
|
||||
int encrypt_mpdu = 0;
|
||||
|
||||
switch(type) {
|
||||
case IEEE80211_STYPE_ASSOC_REQ:
|
||||
@ -405,7 +430,7 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
|
||||
pkt_size = ieee80211softmac_reassoc_req((struct ieee80211_reassoc_request **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg);
|
||||
break;
|
||||
case IEEE80211_STYPE_AUTH:
|
||||
pkt_size = ieee80211softmac_auth((struct ieee80211_auth **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, (u16)(arg & 0xFFFF), (u16) (arg >> 16));
|
||||
pkt_size = ieee80211softmac_auth((struct ieee80211_auth **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, (u16)(arg & 0xFFFF), (u16) (arg >> 16), &encrypt_mpdu);
|
||||
break;
|
||||
case IEEE80211_STYPE_DISASSOC:
|
||||
case IEEE80211_STYPE_DEAUTH:
|
||||
@ -434,52 +459,8 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
|
||||
* or get rid of it alltogether?
|
||||
* Does this work for you now?
|
||||
*/
|
||||
ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *)pkt, pkt_size);
|
||||
|
||||
kfree(pkt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Create an rts/cts frame */
|
||||
static u32
|
||||
ieee80211softmac_rts_cts(struct ieee80211_hdr_2addr **pkt,
|
||||
struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net,
|
||||
u32 type)
|
||||
{
|
||||
/* Allocate Packet */
|
||||
(*pkt) = kmalloc(IEEE80211_2ADDR_LEN, GFP_ATOMIC);
|
||||
memset(*pkt, 0, IEEE80211_2ADDR_LEN);
|
||||
if((*pkt) == NULL)
|
||||
return 0;
|
||||
ieee80211softmac_hdr_2addr(mac, (*pkt), type, net->bssid);
|
||||
return IEEE80211_2ADDR_LEN;
|
||||
}
|
||||
|
||||
|
||||
/* Sends a control packet */
|
||||
static int
|
||||
ieee80211softmac_send_ctl_frame(struct ieee80211softmac_device *mac,
|
||||
struct ieee80211softmac_network *net, u32 type, u32 arg)
|
||||
{
|
||||
void *pkt = NULL;
|
||||
u32 pkt_size = 0;
|
||||
|
||||
switch(type) {
|
||||
case IEEE80211_STYPE_RTS:
|
||||
case IEEE80211_STYPE_CTS:
|
||||
pkt_size = ieee80211softmac_rts_cts((struct ieee80211_hdr_2addr **)(&pkt), mac, net, type);
|
||||
break;
|
||||
default:
|
||||
printkl(KERN_DEBUG PFX "Unsupported Control Frame type: %i\n", type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if(pkt_size == 0)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Send the packet to the ieee80211 layer for tx */
|
||||
ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *) pkt, pkt_size);
|
||||
ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *)pkt,
|
||||
IEEE80211_3ADDR_LEN, pkt_size, encrypt_mpdu);
|
||||
|
||||
kfree(pkt);
|
||||
return 0;
|
||||
|
Reference in New Issue
Block a user