From efa53ebe0d2f50bf342eb1976824f59bba9941eb Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 13 Nov 2006 11:32:50 +0800 Subject: [PATCH] ieee80211: Fix kernel panic when QoS is enabled The 802.11 header length is affected by the wireless mode (WDS or not) and type (QoS or not). We should use the variable hdr_len instead of the hard coded IEEE80211_3ADDR_LEN, otherwise we may touch invalid memory. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- net/ieee80211/ieee80211_tx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/ieee80211') diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c index ae254497ba3..854fc13cd78 100644 --- a/net/ieee80211/ieee80211_tx.c +++ b/net/ieee80211/ieee80211_tx.c @@ -390,7 +390,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) * this stack is providing the full 802.11 header, one will * eventually be affixed to this fragment -- so we must account * for it when determining the amount of payload space. */ - bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN; + bytes_per_frag = frag_size - hdr_len; if (ieee->config & (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) bytes_per_frag -= IEEE80211_FCS_LEN; @@ -412,7 +412,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) } else { nr_frags = 1; bytes_per_frag = bytes_last_frag = bytes; - frag_size = bytes + IEEE80211_3ADDR_LEN; + frag_size = bytes + hdr_len; } rts_required = (frag_size > ieee->rts -- cgit v1.2.3 From a3df3b6f2e37474cdb8b56d55d31be41c22f9b18 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 27 Nov 2006 14:37:21 -0600 Subject: [PATCH] softmac: remove netif_tx_disable when scanning In the scan section of ieee80211softmac, network transmits are disabled. When SoftMAC re-enables transmits, it may override the wishes of a driver that may have very good reasons for disabling transmits. At least one failure in bcm43xx can be traced to this problem. In addition, several unexplained problems may arise from the unexpected enabling of transmits. Note that making this change introduces a new bug that would allow transmits for the current session to be transmitted on the wrong channel; however, the new bug is much less severe than the one being fixed, as the new one only leads to a few retransmits, whereas the old one can bring the interface down. A fix that will not introduce new bugs is being investigated; however, the current, more serious one should be fixed now. Signed-off-by: Michael Buesch Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- net/ieee80211/softmac/ieee80211softmac_scan.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'net/ieee80211') diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c index d31cf77498c..ad67368b58e 100644 --- a/net/ieee80211/softmac/ieee80211softmac_scan.c +++ b/net/ieee80211/softmac/ieee80211softmac_scan.c @@ -47,7 +47,6 @@ ieee80211softmac_start_scan(struct ieee80211softmac_device *sm) sm->scanning = 1; spin_unlock_irqrestore(&sm->lock, flags); - netif_tx_disable(sm->ieee->dev); ret = sm->start_scan(sm->dev); if (ret) { spin_lock_irqsave(&sm->lock, flags); @@ -248,7 +247,6 @@ void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm) if (net) sm->set_channel(sm->dev, net->channel); } - netif_wake_queue(sm->ieee->dev); ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL); } EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished); -- cgit v1.2.3 From c9308b06c049a107edfbd4e5271771564eb6024d Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Wed, 27 Sep 2006 03:50:31 +0100 Subject: [PATCH] ieee80211: Move IV/ICV stripping into ieee80211_rx This patch adds a host_strip_iv_icv flag to ieee80211 which indicates that ieee80211_rx should strip the IV/ICV/other security features from the payload. This saves on some memmove() calls in the driver and seems like something that belongs in the stack as it can be used by bcm43xx, ipw2200, and zd1211rw I will submit the ipw2200 patch separately as it needs testing. This patch also adds some sensible variable reuse (idx vs keyidx) in ieee80211_rx Signed-off-by: Daniel Drake Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/ieee80211/ieee80211_rx.c | 56 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 6 deletions(-) (limited to 'net/ieee80211') diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index 2759312a420..d9265195656 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c @@ -415,17 +415,16 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, ieee->host_mc_decrypt : ieee->host_decrypt; if (can_be_decrypted) { - int idx = 0; if (skb->len >= hdrlen + 3) { /* Top two-bits of byte 3 are the key index */ - idx = skb->data[hdrlen + 3] >> 6; + keyidx = skb->data[hdrlen + 3] >> 6; } - /* ieee->crypt[] is WEP_KEY (4) in length. Given that idx - * is only allowed 2-bits of storage, no value of idx can - * be provided via above code that would result in idx + /* ieee->crypt[] is WEP_KEY (4) in length. Given that keyidx + * is only allowed 2-bits of storage, no value of keyidx can + * be provided via above code that would result in keyidx * being out of range */ - crypt = ieee->crypt[idx]; + crypt = ieee->crypt[keyidx]; #ifdef NOT_YET sta = NULL; @@ -655,6 +654,51 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, goto rx_dropped; } + /* If the frame was decrypted in hardware, we may need to strip off + * any security data (IV, ICV, etc) that was left behind */ + if (!can_be_decrypted && (fc & IEEE80211_FCTL_PROTECTED) && + ieee->host_strip_iv_icv) { + int trimlen = 0; + + /* Top two-bits of byte 3 are the key index */ + if (skb->len >= hdrlen + 3) + keyidx = skb->data[hdrlen + 3] >> 6; + + /* To strip off any security data which appears before the + * payload, we simply increase hdrlen (as the header gets + * chopped off immediately below). For the security data which + * appears after the payload, we use skb_trim. */ + + switch (ieee->sec.encode_alg[keyidx]) { + case SEC_ALG_WEP: + /* 4 byte IV */ + hdrlen += 4; + /* 4 byte ICV */ + trimlen = 4; + break; + case SEC_ALG_TKIP: + /* 4 byte IV, 4 byte ExtIV */ + hdrlen += 8; + /* 8 byte MIC, 4 byte ICV */ + trimlen = 12; + break; + case SEC_ALG_CCMP: + /* 8 byte CCMP header */ + hdrlen += 8; + /* 8 byte MIC */ + trimlen = 8; + break; + } + + if (skb->len < trimlen) + goto rx_dropped; + + __skb_trim(skb, skb->len - trimlen); + + if (skb->len < hdrlen) + goto rx_dropped; + } + /* skb: hdr + (possible reassembled) full plaintext payload */ payload = skb->data + hdrlen; -- cgit v1.2.3 From 42a4cf9576f036db69e15fa6b4e72986e17f0359 Mon Sep 17 00:00:00 2001 From: matthieu castet Date: Thu, 28 Sep 2006 19:57:25 +0200 Subject: [PATCH] ieee80211: allow mtu bigger than 1500 Hi this patch allow to set the mtu between 1500 and 2304 (max octets in an MSDU) for devices using ieee80211 linux stack. Signed-off-by: Matthieu CASTET Signed-off-by: John W. Linville --- net/ieee80211/ieee80211_module.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'net/ieee80211') diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c index 13b1e5fff7e..2b14c2f3e21 100644 --- a/net/ieee80211/ieee80211_module.c +++ b/net/ieee80211/ieee80211_module.c @@ -118,6 +118,14 @@ static void ieee80211_networks_initialize(struct ieee80211_device *ieee) &ieee->network_free_list); } +static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) +{ + if ((new_mtu < 68) || (new_mtu > IEEE80211_DATA_LEN)) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + struct net_device *alloc_ieee80211(int sizeof_priv) { struct ieee80211_device *ieee; @@ -133,6 +141,7 @@ struct net_device *alloc_ieee80211(int sizeof_priv) } ieee = netdev_priv(dev); dev->hard_start_xmit = ieee80211_xmit; + dev->change_mtu = ieee80211_change_mtu; ieee->dev = dev; -- cgit v1.2.3 From 837925df022a667c302b24aad9d6a58f94efd959 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 3 Oct 2006 18:49:32 -0500 Subject: [PATCH] ieee80211: Drop and count duplicate data frames to remove 'replay detected' log messages In the SoftMAC version of the IEEE 802.11 stack, not all duplicate messages are detected. For the most part, there is no difficulty; however for TKIP and CCMP encryption, the duplicates result in a "replay detected" log message where the received and previous values of the TSC are identical. This change adds a new variable to the ieee80211_device structure that holds the 'seq_ctl' value for the previous frame. When a new frame repeats the value, the frame is dropped and the appropriate counter is incremented. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- net/ieee80211/ieee80211_rx.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'net/ieee80211') diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index d9265195656..ce28d571afa 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c @@ -478,6 +478,11 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, goto rx_exit; } #endif + /* drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.29) */ + if (sc == ieee->prev_seq_ctl) + goto rx_dropped; + else + ieee->prev_seq_ctl = sc; /* Data frame - extract src/dst addresses */ if (skb->len < IEEE80211_3ADDR_LEN) -- cgit v1.2.3 From 5398d5901dcb677d24d839d3feac7209e250b161 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sat, 4 Nov 2006 13:29:50 -0600 Subject: [PATCH] ieee80211softmac: fix verbosity when debug disabled SoftMAC contains a number of debug-type messages that continue to print even when debugging is turned off. This patch substitutes dprintkl for printkl for those lines. Signed-off-by: Larry Finger Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/ieee80211/softmac/ieee80211softmac_auth.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'net/ieee80211') diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c index 4cef39e171d..95e5287e12b 100644 --- a/net/ieee80211/softmac/ieee80211softmac_auth.c +++ b/net/ieee80211/softmac/ieee80211softmac_auth.c @@ -158,7 +158,7 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth) /* Make sure that we've got an auth queue item for this request */ if(aq == NULL) { - printkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but no queue item exists.\n", MAC_ARG(auth->header.addr2)); + dprintkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but no queue item exists.\n", MAC_ARG(auth->header.addr2)); /* Error #? */ return -1; } @@ -166,7 +166,7 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth) /* Check for out of order authentication */ if(!net->authenticating) { - printkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but did not request authentication.\n",MAC_ARG(auth->header.addr2)); + dprintkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but did not request authentication.\n",MAC_ARG(auth->header.addr2)); return -1; } @@ -342,7 +342,7 @@ ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac, /* Make sure the network is authenticated */ if (!net->authenticated) { - printkl(KERN_DEBUG PFX "Can't send deauthentication packet, network is not authenticated.\n"); + dprintkl(KERN_DEBUG PFX "Can't send deauthentication packet, network is not authenticated.\n"); /* Error okay? */ return -EPERM; } @@ -376,7 +376,7 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de net = ieee80211softmac_get_network_by_bssid(mac, deauth->header.addr2); if (net == NULL) { - printkl(KERN_DEBUG PFX "Received deauthentication packet from "MAC_FMT", but that network is unknown.\n", + dprintkl(KERN_DEBUG PFX "Received deauthentication packet from "MAC_FMT", but that network is unknown.\n", MAC_ARG(deauth->header.addr2)); return 0; } @@ -384,7 +384,7 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de /* Make sure the network is authenticated */ if(!net->authenticated) { - printkl(KERN_DEBUG PFX "Can't perform deauthentication, network is not authenticated.\n"); + dprintkl(KERN_DEBUG PFX "Can't perform deauthentication, network is not authenticated.\n"); /* Error okay? */ return -EPERM; } -- cgit v1.2.3 From 571d6eee9b5bce28fcbeb7588890ad5ca3f8c718 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 21 Nov 2006 01:26:49 -0200 Subject: [PATCH] Check ieee80211softmac_auth_resp kmalloc result And use kmemdup and kzalloc where applicable Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: John W. Linville --- net/ieee80211/ieee80211_module.c | 5 +---- net/ieee80211/ieee80211_rx.c | 7 +++---- net/ieee80211/softmac/ieee80211softmac_auth.c | 14 ++++++++++---- 3 files changed, 14 insertions(+), 12 deletions(-) (limited to 'net/ieee80211') diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c index 2b14c2f3e21..f16e60ee9ce 100644 --- a/net/ieee80211/ieee80211_module.c +++ b/net/ieee80211/ieee80211_module.c @@ -67,7 +67,7 @@ static int ieee80211_networks_allocate(struct ieee80211_device *ieee) return 0; ieee->networks = - kmalloc(MAX_NETWORK_COUNT * sizeof(struct ieee80211_network), + kzalloc(MAX_NETWORK_COUNT * sizeof(struct ieee80211_network), GFP_KERNEL); if (!ieee->networks) { printk(KERN_WARNING "%s: Out of memory allocating beacons\n", @@ -75,9 +75,6 @@ static int ieee80211_networks_allocate(struct ieee80211_device *ieee) return -ENOMEM; } - memset(ieee->networks, 0, - MAX_NETWORK_COUNT * sizeof(struct ieee80211_network)); - return 0; } diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index ce28d571afa..d97e5412e31 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c @@ -1304,12 +1304,11 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element case MFIE_TYPE_IBSS_DFS: if (network->ibss_dfs) break; - network->ibss_dfs = - kmalloc(info_element->len, GFP_ATOMIC); + network->ibss_dfs = kmemdup(info_element->data, + info_element->len, + GFP_ATOMIC); if (!network->ibss_dfs) return 1; - memcpy(network->ibss_dfs, info_element->data, - info_element->len); network->flags |= NETWORK_HAS_IBSS_DFS; break; diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c index 95e5287e12b..0612015f1c7 100644 --- a/net/ieee80211/softmac/ieee80211softmac_auth.c +++ b/net/ieee80211/softmac/ieee80211softmac_auth.c @@ -216,10 +216,16 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth) net->challenge_len = *data++; if (net->challenge_len > WLAN_AUTH_CHALLENGE_LEN) net->challenge_len = WLAN_AUTH_CHALLENGE_LEN; - if (net->challenge != NULL) - kfree(net->challenge); - net->challenge = kmalloc(net->challenge_len, GFP_ATOMIC); - memcpy(net->challenge, data, net->challenge_len); + kfree(net->challenge); + net->challenge = kmemdup(data, net->challenge_len, + GFP_ATOMIC); + if (net->challenge == NULL) { + printkl(KERN_NOTICE PFX "Shared Key " + "Authentication failed due to " + "memory shortage.\n"); + spin_unlock_irqrestore(&mac->lock, flags); + break; + } aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE; /* We reuse the work struct from the auth request here. -- cgit v1.2.3 From 718cc4ca2bfb3263c7ea3ceba9c194f9cd7292e2 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Wed, 22 Nov 2006 03:15:46 +0000 Subject: [PATCH] ieee80211: Provide generic get_stats implementation bcm43xx and ipw2100 currently duplicate the same simplistic get_stats handler. Additionally, zd1211rw requires the same handler to fix a bug where all stats are reported as 0. This patch adds a generic implementation to the ieee80211 layer, which drivers are free to override. Signed-off-by: Daniel Drake Signed-off-by: John W. Linville --- net/ieee80211/ieee80211_module.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'net/ieee80211') diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c index f16e60ee9ce..b1c6d1f717d 100644 --- a/net/ieee80211/ieee80211_module.c +++ b/net/ieee80211/ieee80211_module.c @@ -123,6 +123,13 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) return 0; } +static struct net_device_stats *ieee80211_generic_get_stats( + struct net_device *dev) +{ + struct ieee80211_device *ieee = netdev_priv(dev); + return &ieee->stats; +} + struct net_device *alloc_ieee80211(int sizeof_priv) { struct ieee80211_device *ieee; @@ -140,6 +147,10 @@ struct net_device *alloc_ieee80211(int sizeof_priv) dev->hard_start_xmit = ieee80211_xmit; dev->change_mtu = ieee80211_change_mtu; + /* Drivers are free to override this if the generic implementation + * does not meet their needs. */ + dev->get_stats = ieee80211_generic_get_stats; + ieee->dev = dev; err = ieee80211_networks_allocate(ieee); -- cgit v1.2.3 From 38e3a6466f369944a2a1ec9aee9a9e472689d0a9 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sat, 25 Nov 2006 18:30:03 -0600 Subject: [PATCH] softmac: reduce scan debug output When scanning in debug mode, softmac is very chatty in that it puts 3 lines in the logs for each time it scans. This patch has only one line containing all the information previously reported. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- net/ieee80211/softmac/ieee80211softmac_scan.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'net/ieee80211') diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c index ad67368b58e..5507feab32d 100644 --- a/net/ieee80211/softmac/ieee80211softmac_scan.c +++ b/net/ieee80211/softmac/ieee80211softmac_scan.c @@ -134,7 +134,8 @@ void ieee80211softmac_scan(void *d) si->started = 0; spin_unlock_irqrestore(&sm->lock, flags); - dprintk(PFX "Scanning finished\n"); + dprintk(PFX "Scanning finished: scanned %d channels starting with channel %d\n", + sm->scaninfo->number_channels, sm->scaninfo->channels[0].channel); ieee80211softmac_scan_finished(sm); complete_all(&sm->scaninfo->finished); } @@ -182,8 +183,6 @@ int ieee80211softmac_start_scan_implementation(struct net_device *dev) sm->scaninfo->channels = sm->ieee->geo.bg; sm->scaninfo->number_channels = sm->ieee->geo.bg_channels; } - dprintk(PFX "Start scanning with channel: %d\n", sm->scaninfo->channels[0].channel); - dprintk(PFX "Scanning %d channels\n", sm->scaninfo->number_channels); sm->scaninfo->current_channel_idx = 0; sm->scaninfo->started = 1; sm->scaninfo->stop = 0; -- cgit v1.2.3