aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2006-06-08 15:48:25 -0400
committerJeff Garzik <jeff@garzik.org>2006-06-08 15:48:25 -0400
commitba9b28d19a3251bb1dfe6a6f8cc89b96fb85f683 (patch)
treed770bd8c536771cb3804abb51ed029d7dd9d30d2 /net
parent862fc81b62c2d41a7e0b97b90844c80e59c7b0f1 (diff)
parent5c601d0c942f5aaf7f3cff7e08f61047d70a964e (diff)
Merge branch 'upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6 into upstream
Diffstat (limited to 'net')
-rw-r--r--net/ieee80211/ieee80211_tx.c25
-rw-r--r--net/ieee80211/softmac/Kconfig1
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_assoc.c22
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_auth.c12
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_event.c5
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_io.c169
6 files changed, 125 insertions, 109 deletions
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index 233d527c695..6a5de1b8445 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -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);
diff --git a/net/ieee80211/softmac/Kconfig b/net/ieee80211/softmac/Kconfig
index f2a27cc6ecb..2811651cb13 100644
--- a/net/ieee80211/softmac/Kconfig
+++ b/net/ieee80211/softmac/Kconfig
@@ -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.
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
index 5d90b9a6ee5..5e9a90651d0 100644
--- a/net/ieee80211/softmac/ieee80211softmac_assoc.c
+++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c
@@ -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);
diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c
index 084b6211f29..90b8484e509 100644
--- a/net/ieee80211/softmac/ieee80211softmac_auth.c
+++ b/net/ieee80211/softmac/ieee80211softmac_auth.c
@@ -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",
diff --git a/net/ieee80211/softmac/ieee80211softmac_event.c b/net/ieee80211/softmac/ieee80211softmac_event.c
index 4b153f7cc96..f34fa2ef666 100644
--- a/net/ieee80211/softmac/ieee80211softmac_event.c
+++ b/net/ieee80211/softmac/ieee80211softmac_event.c
@@ -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);
}
}
diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c
index cc6cd56c85b..09541611e48 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,
* 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;