* [PATCH] zd1211rw, fix oops when ejecting install media
@ 2007-10-15 6:51 Marc Pignat
2007-10-15 11:05 ` Daniel Drake
0 siblings, 1 reply; 5+ messages in thread
From: Marc Pignat @ 2007-10-15 6:51 UTC (permalink / raw)
To: linux-wireless; +Cc: dsd, kune, linux-kernel
The disconnect function can dereference the net_device structure before it is
allocated. This is the case when ejecting the device installer.
Signed-off-by: Marc Pignat <marc.pignat@hevs.ch>
---
Hello!
Patch against 2.6.23.
This patch fixes the bug I've submitted to linux-wireless friday in the
"zd1211rw on 2.6.23 oops ejecting device" thread.
Regards
Marc
--- drivers/net/wireless/zd1211rw/zd_usb.c.orig 2007-10-15 08:29:16.000000000 +0200
+++ drivers/net/wireless/zd1211rw/zd_usb.c 2007-10-15 08:29:32.000000000 +0200
@@ -1041,14 +1041,17 @@ error:
static void disconnect(struct usb_interface *intf)
{
struct net_device *netdev = zd_intf_to_netdev(intf);
- struct zd_mac *mac = zd_netdev_mac(netdev);
- struct zd_usb *usb = &mac->chip.usb;
+ struct zd_mac *mac;
+ struct zd_usb *usb;
/* Either something really bad happened, or we're just dealing with
* a DEVICE_INSTALLER. */
if (netdev == NULL)
return;
+ mac = zd_netdev_mac(netdev);
+ usb = &mac->chip.usb;
+
dev_dbg_f(zd_usb_dev(usb), "\n");
zd_netdev_disconnect(netdev);
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] zd1211rw, fix oops when ejecting install media 2007-10-15 6:51 [PATCH] zd1211rw, fix oops when ejecting install media Marc Pignat @ 2007-10-15 11:05 ` Daniel Drake 2007-10-16 6:33 ` Marc Pignat 0 siblings, 1 reply; 5+ messages in thread From: Daniel Drake @ 2007-10-15 11:05 UTC (permalink / raw) To: John Linville; +Cc: Marc Pignat, linux-wireless, kune, linux-kernel Marc Pignat wrote: > The disconnect function can dereference the net_device structure before it is > allocated. This is the case when ejecting the device installer. > > Signed-off-by: Marc Pignat <marc.pignat@hevs.ch> s/before it is allocated/when it is never allocated/ Acked-by: Daniel Drake <dsd@gentoo.org> > --- > > Hello! > > Patch against 2.6.23. > This patch fixes the bug I've submitted to linux-wireless friday in the > "zd1211rw on 2.6.23 oops ejecting device" thread. > > Regards > > Marc > > --- drivers/net/wireless/zd1211rw/zd_usb.c.orig 2007-10-15 08:29:16.000000000 +0200 > +++ drivers/net/wireless/zd1211rw/zd_usb.c 2007-10-15 08:29:32.000000000 +0200 > @@ -1041,14 +1041,17 @@ error: > static void disconnect(struct usb_interface *intf) > { > struct net_device *netdev = zd_intf_to_netdev(intf); > - struct zd_mac *mac = zd_netdev_mac(netdev); > - struct zd_usb *usb = &mac->chip.usb; > + struct zd_mac *mac; > + struct zd_usb *usb; > > /* Either something really bad happened, or we're just dealing with > * a DEVICE_INSTALLER. */ > if (netdev == NULL) > return; > > + mac = zd_netdev_mac(netdev); > + usb = &mac->chip.usb; > + > dev_dbg_f(zd_usb_dev(usb), "\n"); > > zd_netdev_disconnect(netdev); > > ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] zd1211rw, fix oops when ejecting install media 2007-10-15 11:05 ` Daniel Drake @ 2007-10-16 6:33 ` Marc Pignat 2007-10-16 13:02 ` Daniel Drake 0 siblings, 1 reply; 5+ messages in thread From: Marc Pignat @ 2007-10-16 6:33 UTC (permalink / raw) To: Daniel Drake; +Cc: John Linville, linux-wireless, kune, linux-kernel Hi all! On Monday 15 October 2007, Daniel Drake wrote: ... > Acked-by: Daniel Drake <dsd@gentoo.org> Is there any hope to apply this to 2.6.23.2, as this is a regression fix? Regards Marc ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] zd1211rw, fix oops when ejecting install media 2007-10-16 6:33 ` Marc Pignat @ 2007-10-16 13:02 ` Daniel Drake 0 siblings, 0 replies; 5+ messages in thread From: Daniel Drake @ 2007-10-16 13:02 UTC (permalink / raw) To: Marc Pignat; +Cc: John Linville, linux-wireless, kune, linux-kernel Marc Pignat wrote: > Hi all! > > On Monday 15 October 2007, Daniel Drake wrote: > ... >> Acked-by: Daniel Drake <dsd@gentoo.org> > > Is there any hope to apply this to 2.6.23.2, as this is a regression fix? Yes, already planned, it just has to go upstream first. Thanks, Daniel ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH] Add get_unaligned to ieee80211_get_radiotap_len @ 2007-10-26 21:04 John W. Linville 2007-10-26 21:04 ` [PATCH] Improve sanity checks on injected packets John W. Linville 0 siblings, 1 reply; 5+ messages in thread From: John W. Linville @ 2007-10-26 21:04 UTC (permalink / raw) To: stable; +Cc: linux-wireless, warmcat, John W. Linville From: warmcat <andy@warmcat.com> ieee80211_get_radiotap_len() tries to dereference radiotap length without taking care that it is completely unaligned and get_unaligned() is required. Signed-off-by: Andy Green <andy@warmcat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- net/mac80211/ieee80211.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index ff2172f..9b9d716 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c @@ -350,7 +350,7 @@ static int ieee80211_get_radiotap_len(struct sk_buff *skb) struct ieee80211_radiotap_header *hdr = (struct ieee80211_radiotap_header *) skb->data; - return le16_to_cpu(hdr->it_len); + return le16_to_cpu(get_unaligned(&hdr->it_len)); } #ifdef CONFIG_MAC80211_LOWTX_FRAME_DUMP -- 1.5.2.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH] Improve sanity checks on injected packets 2007-10-26 21:04 [PATCH] Add get_unaligned to ieee80211_get_radiotap_len John W. Linville @ 2007-10-26 21:04 ` John W. Linville 2007-10-26 21:04 ` [PATCH] mac80211: filter locally-originated multicast frames John W. Linville 0 siblings, 1 reply; 5+ messages in thread From: John W. Linville @ 2007-10-26 21:04 UTC (permalink / raw) To: stable; +Cc: linux-wireless, warmcat, John W. Linville From: warmcat <andy@warmcat.com> Michael Wu noticed that the skb length checking is not taken care of enough when a packet is presented on the Monitor interface for injection. This patch improves the sanity checking and removes fake offsets placed into the skb network and transport header. Signed-off-by: Andy Green <andy@warmcat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- net/mac80211/ieee80211.c | 48 ++++++++++++++++++++++++++------------------- 1 files changed, 28 insertions(+), 20 deletions(-) diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index 9b9d716..ad73a40 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c @@ -1680,46 +1680,54 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct ieee80211_tx_packet_data *pkt_data; struct ieee80211_radiotap_header *prthdr = (struct ieee80211_radiotap_header *)skb->data; - u16 len; + u16 len_rthdr; - /* - * there must be a radiotap header at the - * start in this case - */ - if (unlikely(prthdr->it_version)) { - /* only version 0 is supported */ - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } + /* check for not even having the fixed radiotap header part */ + if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header))) + goto fail; /* too short to be possibly valid */ + + /* is it a header version we can trust to find length from? */ + if (unlikely(prthdr->it_version)) + goto fail; /* only version 0 is supported */ + + /* then there must be a radiotap header with a length we can use */ + len_rthdr = ieee80211_get_radiotap_len(skb); + + /* does the skb contain enough to deliver on the alleged length? */ + if (unlikely(skb->len < len_rthdr)) + goto fail; /* skb too short for claimed rt header extent */ skb->dev = local->mdev; pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; memset(pkt_data, 0, sizeof(*pkt_data)); + /* needed because we set skb device to master */ pkt_data->ifindex = dev->ifindex; + pkt_data->mgmt_iface = 0; pkt_data->do_not_encrypt = 1; - /* above needed because we set skb device to master */ - /* * fix up the pointers accounting for the radiotap * header still being in there. We are being given * a precooked IEEE80211 header so no need for * normal processing */ - len = le16_to_cpu(get_unaligned(&prthdr->it_len)); - skb_set_mac_header(skb, len); - skb_set_network_header(skb, len + sizeof(struct ieee80211_hdr)); - skb_set_transport_header(skb, len + sizeof(struct ieee80211_hdr)); - + skb_set_mac_header(skb, len_rthdr); /* - * pass the radiotap header up to - * the next stage intact + * these are just fixed to the end of the rt area since we + * don't have any better information and at this point, nobody cares */ - dev_queue_xmit(skb); + skb_set_network_header(skb, len_rthdr); + skb_set_transport_header(skb, len_rthdr); + /* pass the radiotap header up to the next stage intact */ + dev_queue_xmit(skb); return NETDEV_TX_OK; + +fail: + dev_kfree_skb(skb); + return NETDEV_TX_OK; /* meaning, we dealt with the skb */ } -- 1.5.2.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH] mac80211: filter locally-originated multicast frames 2007-10-26 21:04 ` [PATCH] Improve sanity checks on injected packets John W. Linville @ 2007-10-26 21:04 ` John W. Linville 2007-10-26 21:04 ` [PATCH] libertas: fix endianness breakage John W. Linville 0 siblings, 1 reply; 5+ messages in thread From: John W. Linville @ 2007-10-26 21:04 UTC (permalink / raw) To: stable; +Cc: linux-wireless, John W. Linville From: John W. Linville <linville@tuxdriver.com> In STA mode, the AP will echo our traffic. This includes multicast traffic. Receiving these frames confuses some protocols and applications, notably IPv6 Duplicate Address Detection. Signed-off-by: John W. Linville <linville@tuxdriver.com> --- net/mac80211/ieee80211.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index ad73a40..9e0da6e 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c @@ -2844,9 +2844,10 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx) memcpy(dst, hdr->addr1, ETH_ALEN); memcpy(src, hdr->addr3, ETH_ALEN); - if (sdata->type != IEEE80211_IF_TYPE_STA) { + if (sdata->type != IEEE80211_IF_TYPE_STA || + (is_multicast_ether_addr(dst) && + !compare_ether_addr(src, dev->dev_addr))) return TXRX_DROP; - } break; case 0: /* DA SA BSSID */ -- 1.5.2.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH] libertas: fix endianness breakage 2007-10-26 21:04 ` [PATCH] mac80211: filter locally-originated multicast frames John W. Linville @ 2007-10-26 21:04 ` John W. Linville 2007-10-26 21:04 ` [PATCH] libertas: more " John W. Linville 0 siblings, 1 reply; 5+ messages in thread From: John W. Linville @ 2007-10-26 21:04 UTC (permalink / raw) To: stable; +Cc: linux-wireless, Al Viro, Al Viro, John W. Linville From: Al Viro <viro@ftp.linux.org.uk> wep->keytype[] is u8 Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- drivers/net/wireless/libertas/cmd.c | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 4a8f5dc..86fff8d 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -185,14 +185,12 @@ static int wlan_cmd_802_11_set_wep(wlan_private * priv, switch (pkey->len) { case KEY_LEN_WEP_40: - wep->keytype[i] = - cpu_to_le16(cmd_type_wep_40_bit); + wep->keytype[i] = cmd_type_wep_40_bit; memmove(&wep->keymaterial[i], pkey->key, pkey->len); break; case KEY_LEN_WEP_104: - wep->keytype[i] = - cpu_to_le16(cmd_type_wep_104_bit); + wep->keytype[i] = cmd_type_wep_104_bit; memmove(&wep->keymaterial[i], pkey->key, pkey->len); break; -- 1.5.2.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH] libertas: more endianness breakage 2007-10-26 21:04 ` [PATCH] libertas: fix endianness breakage John W. Linville @ 2007-10-26 21:04 ` John W. Linville 2007-10-26 21:04 ` [PATCH] ieee80211: fix TKIP QoS bug John W. Linville 0 siblings, 1 reply; 5+ messages in thread From: John W. Linville @ 2007-10-26 21:04 UTC (permalink / raw) To: stable; +Cc: linux-wireless, Al Viro, Al Viro, John W. Linville From: Al Viro <viro@ftp.linux.org.uk> domain->header.len is le16 and has just been assigned cpu_to_le16(arithmetical expression). And all fields of adapter->logmsg are __le32; not a single 16-bit among them... That's incremental to the previous one Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- drivers/net/wireless/libertas/11d.c | 2 +- drivers/net/wireless/libertas/wext.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/libertas/11d.c b/drivers/net/wireless/libertas/11d.c index 4cf0ff7..0560270 100644 --- a/drivers/net/wireless/libertas/11d.c +++ b/drivers/net/wireless/libertas/11d.c @@ -562,7 +562,7 @@ int libertas_cmd_802_11d_domain_info(wlan_private * priv, nr_subband * sizeof(struct ieeetypes_subbandset)); cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) + - domain->header.len + + le16_to_cpu(domain->header.len) + sizeof(struct mrvlietypesheader) + S_DS_GEN); } else { diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index 2fcc3bf..873c405 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -973,7 +973,7 @@ static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev) /* Quality by TX errors */ priv->wstats.discard.retries = priv->stats.tx_errors; - tx_retries = le16_to_cpu(adapter->logmsg.retry); + tx_retries = le32_to_cpu(adapter->logmsg.retry); if (tx_retries > 75) tx_qual = (90 - tx_retries) * POOR / 15; @@ -989,10 +989,10 @@ static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev) (PERFECT - VERY_GOOD) / 50 + VERY_GOOD; quality = min(quality, tx_qual); - priv->wstats.discard.code = le16_to_cpu(adapter->logmsg.wepundecryptable); - priv->wstats.discard.fragment = le16_to_cpu(adapter->logmsg.rxfrag); + priv->wstats.discard.code = le32_to_cpu(adapter->logmsg.wepundecryptable); + priv->wstats.discard.fragment = le32_to_cpu(adapter->logmsg.rxfrag); priv->wstats.discard.retries = tx_retries; - priv->wstats.discard.misc = le16_to_cpu(adapter->logmsg.ackfailure); + priv->wstats.discard.misc = le32_to_cpu(adapter->logmsg.ackfailure); /* Calculate quality */ priv->wstats.qual.qual = max(quality, (u32)100); -- 1.5.2.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH] ieee80211: fix TKIP QoS bug 2007-10-26 21:04 ` [PATCH] libertas: more " John W. Linville @ 2007-10-26 21:04 ` John W. Linville 2007-10-26 21:04 ` [PATCH] mac80211: reorder association debug output John W. Linville 0 siblings, 1 reply; 5+ messages in thread From: John W. Linville @ 2007-10-26 21:04 UTC (permalink / raw) To: stable; +Cc: linux-wireless, Johannes Berg, John W. Linville From: Johannes Berg <johannes@sipsolutions.net> The commit 65b6a277 titled "ieee80211: Fix header->qos_ctl endian issue" *introduced* an endianness bug. Partially revert it. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- net/ieee80211/ieee80211_crypt_tkip.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c index 5a48d8e..7f11dd9 100644 --- a/net/ieee80211/ieee80211_crypt_tkip.c +++ b/net/ieee80211/ieee80211_crypt_tkip.c @@ -584,7 +584,7 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr) if (stype & IEEE80211_STYPE_QOS_DATA) { const struct ieee80211_hdr_3addrqos *qoshdr = (struct ieee80211_hdr_3addrqos *)skb->data; - hdr[12] = qoshdr->qos_ctl & cpu_to_le16(IEEE80211_QCTL_TID); + hdr[12] = le16_to_cpu(qoshdr->qos_ctl) & IEEE80211_QCTL_TID; } else hdr[12] = 0; /* priority */ -- 1.5.2.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH] mac80211: reorder association debug output 2007-10-26 21:04 ` [PATCH] ieee80211: fix TKIP QoS bug John W. Linville @ 2007-10-26 21:04 ` John W. Linville 2007-10-26 21:04 ` [PATCH] mac80211: store channel info in sta_bss_list John W. Linville 0 siblings, 1 reply; 5+ messages in thread From: John W. Linville @ 2007-10-26 21:04 UTC (permalink / raw) To: stable; +Cc: linux-wireless, Johannes Berg, John W. Linville From: Johannes Berg <johannes@sipsolutions.net> There's no reason to warn about an invalid AID field when the association was denied. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Acked-by: Michael Wu <flamingice@sourmilk.net> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- net/mac80211/ieee80211_sta.c | 11 ++++++----- 1 files changed, 6 insertions(+), 5 deletions(-) diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index 0d99b68..ae74c79 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c @@ -1174,15 +1174,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); aid = le16_to_cpu(mgmt->u.assoc_resp.aid); - if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) - printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " - "set\n", dev->name, aid); - aid &= ~(BIT(15) | BIT(14)); printk(KERN_DEBUG "%s: RX %sssocResp from " MAC_FMT " (capab=0x%x " "status=%d aid=%d)\n", dev->name, reassoc ? "Rea" : "A", MAC_ARG(mgmt->sa), - capab_info, status_code, aid); + capab_info, status_code, aid & ~(BIT(15) | BIT(14))); if (status_code != WLAN_STATUS_SUCCESS) { printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", @@ -1192,6 +1188,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, return; } + if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) + printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " + "set\n", dev->name, aid); + aid &= ~(BIT(15) | BIT(14)); + pos = mgmt->u.assoc_resp.variable; if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems) == ParseFailed) { -- 1.5.2.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH] mac80211: store channel info in sta_bss_list 2007-10-26 21:04 ` [PATCH] mac80211: reorder association debug output John W. Linville @ 2007-10-26 21:04 ` John W. Linville 2007-10-26 21:04 ` [PATCH] mac80211: store SSID " John W. Linville 0 siblings, 1 reply; 5+ messages in thread From: John W. Linville @ 2007-10-26 21:04 UTC (permalink / raw) To: stable; +Cc: linux-wireless, John W. Linville From: John W. Linville <linville@tuxdriver.com> Some AP equipment "in the wild" uses the same BSSID on multiple channels (particularly "a" vs. "b/g"). This patch changes the key of sta_bss_list to include both the BSSID and the channel so as to prevent a BSSID on one channel from eclipsing the same BSSID on another channel. Signed-off-by: John W. Linville <linville@tuxdriver.com> --- net/mac80211/ieee80211_sta.c | 35 ++++++++++++++++++++--------------- 1 files changed, 20 insertions(+), 15 deletions(-) diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index ae74c79..1991daa 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c @@ -61,7 +61,7 @@ static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, u8 *ssid, size_t ssid_len); static struct ieee80211_sta_bss * -ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid); +ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel); static void ieee80211_rx_bss_put(struct net_device *dev, struct ieee80211_sta_bss *bss); static int ieee80211_sta_find_ibss(struct net_device *dev, @@ -387,6 +387,7 @@ static void ieee80211_set_associated(struct net_device *dev, struct ieee80211_if_sta *ifsta, int assoc) { union iwreq_data wrqu; + struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (ifsta->associated == assoc) @@ -401,7 +402,8 @@ static void ieee80211_set_associated(struct net_device *dev, if (sdata->type != IEEE80211_IF_TYPE_STA) return; - bss = ieee80211_rx_bss_get(dev, ifsta->bssid); + bss = ieee80211_rx_bss_get(dev, ifsta->bssid, + local->hw.conf.channel); if (bss) { if (bss->has_erp_value) ieee80211_handle_erp_ie(dev, bss->erp_value); @@ -543,7 +545,7 @@ static void ieee80211_send_assoc(struct net_device *dev, capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME | WLAN_CAPABILITY_SHORT_PREAMBLE; } - bss = ieee80211_rx_bss_get(dev, ifsta->bssid); + bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel); if (bss) { if (bss->capability & WLAN_CAPABILITY_PRIVACY) capab |= WLAN_CAPABILITY_PRIVACY; @@ -695,6 +697,7 @@ static void ieee80211_send_disassoc(struct net_device *dev, static int ieee80211_privacy_mismatch(struct net_device *dev, struct ieee80211_if_sta *ifsta) { + struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; int res = 0; @@ -702,7 +705,7 @@ static int ieee80211_privacy_mismatch(struct net_device *dev, ifsta->key_mgmt != IEEE80211_KEY_MGMT_NONE) return 0; - bss = ieee80211_rx_bss_get(dev, ifsta->bssid); + bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel); if (!bss) return 0; @@ -1211,7 +1214,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, * update our stored copy */ if (elems.erp_info && elems.erp_info_len >= 1) { struct ieee80211_sta_bss *bss - = ieee80211_rx_bss_get(dev, ifsta->bssid); + = ieee80211_rx_bss_get(dev, ifsta->bssid, + local->hw.conf.channel); if (bss) { bss->erp_value = elems.erp_info[0]; bss->has_erp_value = 1; @@ -1241,7 +1245,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, " AP\n", dev->name); return; } - bss = ieee80211_rx_bss_get(dev, ifsta->bssid); + bss = ieee80211_rx_bss_get(dev, ifsta->bssid, + local->hw.conf.channel); if (bss) { sta->last_rssi = bss->rssi; sta->last_signal = bss->signal; @@ -1322,7 +1327,7 @@ static void __ieee80211_rx_bss_hash_del(struct net_device *dev, static struct ieee80211_sta_bss * -ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid) +ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; @@ -1333,6 +1338,7 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid) atomic_inc(&bss->users); atomic_inc(&bss->users); memcpy(bss->bssid, bssid, ETH_ALEN); + bss->channel = channel; spin_lock_bh(&local->sta_bss_lock); /* TODO: order by RSSI? */ @@ -1344,7 +1350,7 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid) static struct ieee80211_sta_bss * -ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid) +ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; @@ -1352,7 +1358,8 @@ ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid) spin_lock_bh(&local->sta_bss_lock); bss = local->sta_bss_hash[STA_HASH(bssid)]; while (bss) { - if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0) { + if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0 && + bss->channel == channel) { atomic_inc(&bss->users); break; } @@ -1520,9 +1527,9 @@ static void ieee80211_rx_bss_info(struct net_device *dev, else channel = rx_status->channel; - bss = ieee80211_rx_bss_get(dev, mgmt->bssid); + bss = ieee80211_rx_bss_get(dev, mgmt->bssid, channel); if (!bss) { - bss = ieee80211_rx_bss_add(dev, mgmt->bssid); + bss = ieee80211_rx_bss_add(dev, mgmt->bssid, channel); if (!bss) return; } else { @@ -1622,7 +1629,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev, bss->hw_mode = rx_status->phymode; - bss->channel = channel; bss->freq = rx_status->freq; if (channel != rx_status->channel && (bss->hw_mode == MODE_IEEE80211G || @@ -2355,7 +2361,7 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID " MAC_FMT "\n", dev->name, MAC_ARG(bssid)); - bss = ieee80211_rx_bss_add(dev, bssid); + bss = ieee80211_rx_bss_add(dev, bssid, local->hw.conf.channel); if (!bss) return -ENOMEM; @@ -2366,7 +2372,6 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, local->hw.conf.beacon_int = 100; bss->beacon_int = local->hw.conf.beacon_int; bss->hw_mode = local->hw.conf.phymode; - bss->channel = local->hw.conf.channel; bss->freq = local->hw.conf.freq; bss->last_update = jiffies; bss->capability = WLAN_CAPABILITY_IBSS; @@ -2426,7 +2431,7 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, MAC_FMT "\n", MAC_ARG(bssid), MAC_ARG(ifsta->bssid)); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 && - (bss = ieee80211_rx_bss_get(dev, bssid))) { + (bss = ieee80211_rx_bss_get(dev, bssid, local->hw.conf.channel))) { printk(KERN_DEBUG "%s: Selected IBSS BSSID " MAC_FMT " based on configured SSID\n", dev->name, MAC_ARG(bssid)); -- 1.5.2.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH] mac80211: store SSID in sta_bss_list 2007-10-26 21:04 ` [PATCH] mac80211: store channel info in sta_bss_list John W. Linville @ 2007-10-26 21:04 ` John W. Linville 2007-10-26 21:04 ` [PATCH] mac80211: honor IW_SCAN_THIS_ESSID in siwscan ioctl John W. Linville 0 siblings, 1 reply; 5+ messages in thread From: John W. Linville @ 2007-10-26 21:04 UTC (permalink / raw) To: stable; +Cc: linux-wireless, John W. Linville From: John W. Linville <linville@tuxdriver.com> Some AP equipment "in the wild" services multiple SSIDs using the same BSSID. This patch changes the key of sta_bss_list to include the SSID as well as the BSSID and the channel so as to prevent one SSID from eclipsing another SSID with the same BSSID. Signed-off-by: John W. Linville <linville@tuxdriver.com> --- net/mac80211/ieee80211_sta.c | 54 +++++++++++++++++++++++++---------------- 1 files changed, 33 insertions(+), 21 deletions(-) diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index 1991daa..e78b51e 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c @@ -12,7 +12,6 @@ */ /* TODO: - * BSS table: use <BSSID,SSID> as the key to support multi-SSID APs * order BSS list by RSSI(?) ("quality of AP") * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE, * SSID) @@ -61,7 +60,8 @@ static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, u8 *ssid, size_t ssid_len); static struct ieee80211_sta_bss * -ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel); +ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel, + u8 *ssid, u8 ssid_len); static void ieee80211_rx_bss_put(struct net_device *dev, struct ieee80211_sta_bss *bss); static int ieee80211_sta_find_ibss(struct net_device *dev, @@ -403,7 +403,8 @@ static void ieee80211_set_associated(struct net_device *dev, return; bss = ieee80211_rx_bss_get(dev, ifsta->bssid, - local->hw.conf.channel); + local->hw.conf.channel, + ifsta->ssid, ifsta->ssid_len); if (bss) { if (bss->has_erp_value) ieee80211_handle_erp_ie(dev, bss->erp_value); @@ -545,7 +546,8 @@ static void ieee80211_send_assoc(struct net_device *dev, capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME | WLAN_CAPABILITY_SHORT_PREAMBLE; } - bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel); + bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel, + ifsta->ssid, ifsta->ssid_len); if (bss) { if (bss->capability & WLAN_CAPABILITY_PRIVACY) capab |= WLAN_CAPABILITY_PRIVACY; @@ -705,7 +707,8 @@ static int ieee80211_privacy_mismatch(struct net_device *dev, ifsta->key_mgmt != IEEE80211_KEY_MGMT_NONE) return 0; - bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel); + bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel, + ifsta->ssid, ifsta->ssid_len); if (!bss) return 0; @@ -1215,7 +1218,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, if (elems.erp_info && elems.erp_info_len >= 1) { struct ieee80211_sta_bss *bss = ieee80211_rx_bss_get(dev, ifsta->bssid, - local->hw.conf.channel); + local->hw.conf.channel, + ifsta->ssid, ifsta->ssid_len); if (bss) { bss->erp_value = elems.erp_info[0]; bss->has_erp_value = 1; @@ -1246,7 +1250,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, return; } bss = ieee80211_rx_bss_get(dev, ifsta->bssid, - local->hw.conf.channel); + local->hw.conf.channel, + ifsta->ssid, ifsta->ssid_len); if (bss) { sta->last_rssi = bss->rssi; sta->last_signal = bss->signal; @@ -1327,7 +1332,8 @@ static void __ieee80211_rx_bss_hash_del(struct net_device *dev, static struct ieee80211_sta_bss * -ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel) +ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel, + u8 *ssid, u8 ssid_len) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; @@ -1339,6 +1345,10 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel) atomic_inc(&bss->users); memcpy(bss->bssid, bssid, ETH_ALEN); bss->channel = channel; + if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) { + memcpy(bss->ssid, ssid, ssid_len); + bss->ssid_len = ssid_len; + } spin_lock_bh(&local->sta_bss_lock); /* TODO: order by RSSI? */ @@ -1350,7 +1360,8 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel) static struct ieee80211_sta_bss * -ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel) +ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel, + u8 *ssid, u8 ssid_len) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; @@ -1358,8 +1369,10 @@ ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel) spin_lock_bh(&local->sta_bss_lock); bss = local->sta_bss_hash[STA_HASH(bssid)]; while (bss) { - if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0 && - bss->channel == channel) { + if (!memcmp(bss->bssid, bssid, ETH_ALEN) && + bss->channel == channel && + bss->ssid_len == ssid_len && + (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) { atomic_inc(&bss->users); break; } @@ -1527,9 +1540,11 @@ static void ieee80211_rx_bss_info(struct net_device *dev, else channel = rx_status->channel; - bss = ieee80211_rx_bss_get(dev, mgmt->bssid, channel); + bss = ieee80211_rx_bss_get(dev, mgmt->bssid, channel, + elems.ssid, elems.ssid_len); if (!bss) { - bss = ieee80211_rx_bss_add(dev, mgmt->bssid, channel); + bss = ieee80211_rx_bss_add(dev, mgmt->bssid, channel, + elems.ssid, elems.ssid_len); if (!bss) return; } else { @@ -1555,10 +1570,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev, bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); - if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) { - memcpy(bss->ssid, elems.ssid, elems.ssid_len); - bss->ssid_len = elems.ssid_len; - } bss->supp_rates_len = 0; if (elems.supp_rates) { @@ -2339,7 +2350,7 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_hw_mode *mode; u8 bssid[ETH_ALEN], *pos; int i; @@ -2361,11 +2372,11 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID " MAC_FMT "\n", dev->name, MAC_ARG(bssid)); - bss = ieee80211_rx_bss_add(dev, bssid, local->hw.conf.channel); + bss = ieee80211_rx_bss_add(dev, bssid, local->hw.conf.channel, + sdata->u.sta.ssid, sdata->u.sta.ssid_len); if (!bss) return -ENOMEM; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); mode = local->oper_hw_mode; if (local->hw.conf.beacon_int == 0) @@ -2431,7 +2442,8 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, MAC_FMT "\n", MAC_ARG(bssid), MAC_ARG(ifsta->bssid)); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 && - (bss = ieee80211_rx_bss_get(dev, bssid, local->hw.conf.channel))) { + (bss = ieee80211_rx_bss_get(dev, bssid, local->hw.conf.channel, + ifsta->ssid, ifsta->ssid_len))) { printk(KERN_DEBUG "%s: Selected IBSS BSSID " MAC_FMT " based on configured SSID\n", dev->name, MAC_ARG(bssid)); -- 1.5.2.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH] mac80211: honor IW_SCAN_THIS_ESSID in siwscan ioctl 2007-10-26 21:04 ` [PATCH] mac80211: store SSID " John W. Linville @ 2007-10-26 21:04 ` John W. Linville 2007-10-26 21:04 ` [PATCH] mac80211: only honor IW_SCAN_THIS_ESSID in STA, IBSS, and AP modes John W. Linville 0 siblings, 1 reply; 5+ messages in thread From: John W. Linville @ 2007-10-26 21:04 UTC (permalink / raw) To: stable; +Cc: linux-wireless, Bill Moss, Abhijeet Kolekar, John W. Linville From: Bill Moss <bmoss@clemson.edu> This patch fixes the problem of associating with wpa_secured hidden AP. Please try out. The original author of this patch is Bill Moss <bmoss@clemson.edu> Signed-off-by: Abhijeet Kolekar <abhijeet.kolekar@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- net/mac80211/ieee80211_ioctl.c | 40 ++++++++++++++++++++++++---------------- 1 files changed, 24 insertions(+), 16 deletions(-) diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c index e7904db..5bd103a 100644 --- a/net/mac80211/ieee80211_ioctl.c +++ b/net/mac80211/ieee80211_ioctl.c @@ -687,32 +687,40 @@ static int ieee80211_ioctl_giwap(struct net_device *dev, static int ieee80211_ioctl_siwscan(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *extra) + union iwreq_data *wrqu, char *extra) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct iw_scan_req *req = NULL; u8 *ssid = NULL; size_t ssid_len = 0; if (!netif_running(dev)) return -ENETDOWN; - switch (sdata->type) { - case IEEE80211_IF_TYPE_STA: - case IEEE80211_IF_TYPE_IBSS: - if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) { - ssid = sdata->u.sta.ssid; - ssid_len = sdata->u.sta.ssid_len; - } - break; - case IEEE80211_IF_TYPE_AP: - if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) { - ssid = sdata->u.ap.ssid; - ssid_len = sdata->u.ap.ssid_len; + if (wrqu->data.length == sizeof(struct iw_scan_req) && + wrqu->data.flags & IW_SCAN_THIS_ESSID) { + req = (struct iw_scan_req *)extra; + ssid = req->essid; + ssid_len = req->essid_len; + } else { + switch (sdata->type) { + case IEEE80211_IF_TYPE_STA: + case IEEE80211_IF_TYPE_IBSS: + if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) { + ssid = sdata->u.sta.ssid; + ssid_len = sdata->u.sta.ssid_len; + } + break; + case IEEE80211_IF_TYPE_AP: + if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) { + ssid = sdata->u.ap.ssid; + ssid_len = sdata->u.ap.ssid_len; + } + break; + default: + return -EOPNOTSUPP; } - break; - default: - return -EOPNOTSUPP; } return ieee80211_sta_req_scan(dev, ssid, ssid_len); -- 1.5.2.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH] mac80211: only honor IW_SCAN_THIS_ESSID in STA, IBSS, and AP modes 2007-10-26 21:04 ` [PATCH] mac80211: honor IW_SCAN_THIS_ESSID in siwscan ioctl John W. Linville @ 2007-10-26 21:04 ` John W. Linville 2007-10-26 21:04 ` [PATCH] mac80211: make ieee802_11_parse_elems return void John W. Linville 0 siblings, 1 reply; 5+ messages in thread From: John W. Linville @ 2007-10-26 21:04 UTC (permalink / raw) To: stable; +Cc: linux-wireless, John W. Linville From: John W. Linville <linville@tuxdriver.com> The previous IW_SCAN_THIS_ESSID patch left a hole allowing scan requests on interfaces in inappropriate modes. Signed-off-by: John W. Linville <linville@tuxdriver.com> --- net/mac80211/ieee80211_ioctl.c | 37 +++++++++++++++++++------------------ 1 files changed, 19 insertions(+), 18 deletions(-) diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c index 5bd103a..7b5b801 100644 --- a/net/mac80211/ieee80211_ioctl.c +++ b/net/mac80211/ieee80211_ioctl.c @@ -698,29 +698,30 @@ static int ieee80211_ioctl_siwscan(struct net_device *dev, if (!netif_running(dev)) return -ENETDOWN; + switch (sdata->type) { + case IEEE80211_IF_TYPE_STA: + case IEEE80211_IF_TYPE_IBSS: + if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) { + ssid = sdata->u.sta.ssid; + ssid_len = sdata->u.sta.ssid_len; + } + break; + case IEEE80211_IF_TYPE_AP: + if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) { + ssid = sdata->u.ap.ssid; + ssid_len = sdata->u.ap.ssid_len; + } + break; + default: + return -EOPNOTSUPP; + } + + /* if SSID was specified explicitly then use that */ if (wrqu->data.length == sizeof(struct iw_scan_req) && wrqu->data.flags & IW_SCAN_THIS_ESSID) { req = (struct iw_scan_req *)extra; ssid = req->essid; ssid_len = req->essid_len; - } else { - switch (sdata->type) { - case IEEE80211_IF_TYPE_STA: - case IEEE80211_IF_TYPE_IBSS: - if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) { - ssid = sdata->u.sta.ssid; - ssid_len = sdata->u.sta.ssid_len; - } - break; - case IEEE80211_IF_TYPE_AP: - if (local->scan_flags & IEEE80211_SCAN_MATCH_SSID) { - ssid = sdata->u.ap.ssid; - ssid_len = sdata->u.ap.ssid_len; - } - break; - default: - return -EOPNOTSUPP; - } } return ieee80211_sta_req_scan(dev, ssid, ssid_len); -- 1.5.2.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH] mac80211: make ieee802_11_parse_elems return void 2007-10-26 21:04 ` [PATCH] mac80211: only honor IW_SCAN_THIS_ESSID in STA, IBSS, and AP modes John W. Linville @ 2007-10-26 21:04 ` John W. Linville 2007-10-26 21:04 ` [PATCH] zd1201: avoid null ptr access of skb->dev John W. Linville 0 siblings, 1 reply; 5+ messages in thread From: John W. Linville @ 2007-10-26 21:04 UTC (permalink / raw) To: stable; +Cc: linux-wireless, John W. Linville From: John W. Linville <linville@tuxdriver.com> Some APs send management frames with junk padding after the last IE. We already account for a similar problem with some Apple Airport devices, but at least one device is known to send more than a single extra byte. The device in question is the Draytek Vigor2900: http://www.draytek.com.au/products/Vigor2900.php The junk in question looks like an IE that runs off the end of the frame. This cause us to return ParseFailed. Since the frame in question is an association response, this causes us to fail to associate with this AP. The return code from ieee802_11_parse_elems is superfluous. All callers still check for the presence of the specific IEs that interest them anyway. So, remove the return code so the parse never "fails". Acked-by: Michael Wu <flamingice@sourmilk.net> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- net/mac80211/ieee80211_sta.c | 56 ++++++----------------------------------- 1 files changed, 9 insertions(+), 47 deletions(-) diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index e78b51e..73d39e1 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c @@ -108,15 +108,11 @@ struct ieee802_11_elems { u8 wmm_param_len; }; -typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes; - - -static ParseRes ieee802_11_parse_elems(u8 *start, size_t len, - struct ieee802_11_elems *elems) +static void ieee802_11_parse_elems(u8 *start, size_t len, + struct ieee802_11_elems *elems) { size_t left = len; u8 *pos = start; - int unknown = 0; memset(elems, 0, sizeof(*elems)); @@ -127,15 +123,8 @@ static ParseRes ieee802_11_parse_elems(u8 *start, size_t len, elen = *pos++; left -= 2; - if (elen > left) { -#if 0 - if (net_ratelimit()) - printk(KERN_DEBUG "IEEE 802.11 element parse " - "failed (id=%d elen=%d left=%d)\n", - id, elen, left); -#endif - return ParseFailed; - } + if (elen > left) + return; switch (id) { case WLAN_EID_SSID: @@ -202,28 +191,15 @@ static ParseRes ieee802_11_parse_elems(u8 *start, size_t len, elems->ext_supp_rates_len = elen; break; default: -#if 0 - printk(KERN_DEBUG "IEEE 802.11 element parse ignored " - "unknown element (id=%d elen=%d)\n", - id, elen); -#endif - unknown++; break; } left -= elen; pos += elen; } - - /* Do not trigger error if left == 1 as Apple Airport base stations - * send AssocResps that are one spurious byte too long. */ - - return unknown ? ParseUnknown : ParseOK; } - - static int ecw2cw(int ecw) { int cw = 1; @@ -907,12 +883,7 @@ static void ieee80211_auth_challenge(struct net_device *dev, printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name); pos = mgmt->u.auth.variable; - if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems) - == ParseFailed) { - printk(KERN_DEBUG "%s: failed to parse Auth(challenge)\n", - dev->name); - return; - } + ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); if (!elems.challenge) { printk(KERN_DEBUG "%s: no challenge IE in shared key auth " "frame\n", dev->name); @@ -1200,12 +1171,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev, aid &= ~(BIT(15) | BIT(14)); pos = mgmt->u.assoc_resp.variable; - if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems) - == ParseFailed) { - printk(KERN_DEBUG "%s: failed to parse AssocResp\n", - dev->name); - return; - } + ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); if (!elems.supp_rates) { printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", @@ -1434,7 +1400,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev, struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee802_11_elems elems; size_t baselen; - int channel, invalid = 0, clen; + int channel, clen; struct ieee80211_sta_bss *bss; struct sta_info *sta; struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); @@ -1478,9 +1444,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev, #endif /* CONFIG_MAC80211_IBSS_DEBUG */ } - if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, - &elems) == ParseFailed) - invalid = 1; + ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); if (sdata->type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates && memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 && @@ -1699,9 +1663,7 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, if (baselen > len) return; - if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, - &elems) == ParseFailed) - return; + ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); if (elems.erp_info && elems.erp_info_len >= 1) ieee80211_handle_erp_ie(dev, elems.erp_info[0]); -- 1.5.2.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH] zd1201: avoid null ptr access of skb->dev 2007-10-26 21:04 ` [PATCH] mac80211: make ieee802_11_parse_elems return void John W. Linville @ 2007-10-26 21:04 ` John W. Linville 2007-10-26 21:04 ` [PATCH] ipw2100: send WEXT scan events John W. Linville 0 siblings, 1 reply; 5+ messages in thread From: John W. Linville @ 2007-10-26 21:04 UTC (permalink / raw) To: stable; +Cc: linux-wireless, John W. Linville From: John W. Linville <linville@tuxdriver.com> skb->dev is not set until eth_type_trans is called... Signed-off-by: John W. Linville <linville@tuxdriver.com> --- drivers/net/wireless/zd1201.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c index 935b144..d5c0c66 100644 --- a/drivers/net/wireless/zd1201.c +++ b/drivers/net/wireless/zd1201.c @@ -327,8 +327,8 @@ static void zd1201_usbrx(struct urb *urb) memcpy(skb_put(skb, 6), &data[datalen-8], 6); memcpy(skb_put(skb, 2), &data[datalen-24], 2); memcpy(skb_put(skb, len), data, len); - skb->dev->last_rx = jiffies; skb->protocol = eth_type_trans(skb, zd->dev); + skb->dev->last_rx = jiffies; zd->stats.rx_packets++; zd->stats.rx_bytes += skb->len; netif_rx(skb); @@ -384,8 +384,8 @@ static void zd1201_usbrx(struct urb *urb) memcpy(skb_put(skb, 2), &data[6], 2); memcpy(skb_put(skb, len), data+8, len); } - skb->dev->last_rx = jiffies; skb->protocol = eth_type_trans(skb, zd->dev); + skb->dev->last_rx = jiffies; zd->stats.rx_packets++; zd->stats.rx_bytes += skb->len; netif_rx(skb); -- 1.5.2.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH] ipw2100: send WEXT scan events 2007-10-26 21:04 ` [PATCH] zd1201: avoid null ptr access of skb->dev John W. Linville @ 2007-10-26 21:04 ` John W. Linville 2007-10-26 21:04 ` [PATCH] rtl8187: Fix more frag bit checking, rts duration calc John W. Linville 0 siblings, 1 reply; 5+ messages in thread From: John W. Linville @ 2007-10-26 21:04 UTC (permalink / raw) To: stable; +Cc: linux-wireless, Dan Williams, John W. Linville From: Dan Williams <dcbw@redhat.com> ipw2100 wasn't sending WEXT scan events at all on scan completion. And like ipw2200, the driver aggressively auto-scans, requiring non-user-requested scan events to be batched together and sent at specific intervals instead of many times per seconds. Signed-off-by: Dan Williams <dcbw@redhat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- drivers/net/wireless/ipw2100.c | 39 +++++++++++++++++++++++++++++++++++++++ drivers/net/wireless/ipw2100.h | 4 ++++ 2 files changed, 43 insertions(+), 0 deletions(-) diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 8990585..e690609 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -2102,12 +2102,46 @@ static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status) queue_delayed_work(priv->workqueue, &priv->rf_kill, round_jiffies(HZ)); } +static void send_scan_event(void *data) +{ + struct ipw2100_priv *priv = data; + union iwreq_data wrqu; + + wrqu.data.length = 0; + wrqu.data.flags = 0; + wireless_send_event(priv->net_dev, SIOCGIWSCAN, &wrqu, NULL); +} + +static void ipw2100_scan_event_later(struct work_struct *work) +{ + send_scan_event(container_of(work, struct ipw2100_priv, + scan_event_later.work)); +} + +static void ipw2100_scan_event_now(struct work_struct *work) +{ + send_scan_event(container_of(work, struct ipw2100_priv, + scan_event_now)); +} + static void isr_scan_complete(struct ipw2100_priv *priv, u32 status) { IPW_DEBUG_SCAN("scan complete\n"); /* Age the scan results... */ priv->ieee->scans++; priv->status &= ~STATUS_SCANNING; + + /* Only userspace-requested scan completion events go out immediately */ + if (!priv->user_requested_scan) { + if (!delayed_work_pending(&priv->scan_event_later)) + queue_delayed_work(priv->workqueue, + &priv->scan_event_later, + round_jiffies(msecs_to_jiffies(4000))); + } else { + priv->user_requested_scan = 0; + cancel_delayed_work(&priv->scan_event_later); + queue_work(priv->workqueue, &priv->scan_event_now); + } } #ifdef CONFIG_IPW2100_DEBUG @@ -4376,6 +4410,7 @@ static void ipw2100_kill_workqueue(struct ipw2100_priv *priv) cancel_delayed_work(&priv->wx_event_work); cancel_delayed_work(&priv->hang_check); cancel_delayed_work(&priv->rf_kill); + cancel_delayed_work(&priv->scan_event_later); destroy_workqueue(priv->workqueue); priv->workqueue = NULL; } @@ -6118,6 +6153,8 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, INIT_DELAYED_WORK(&priv->wx_event_work, ipw2100_wx_event_work); INIT_DELAYED_WORK(&priv->hang_check, ipw2100_hang_check); INIT_DELAYED_WORK(&priv->rf_kill, ipw2100_rf_kill); + INIT_WORK(&priv->scan_event_now, ipw2100_scan_event_now); + INIT_DELAYED_WORK(&priv->scan_event_later, ipw2100_scan_event_later); tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) ipw2100_irq_tasklet, (unsigned long)priv); @@ -7427,6 +7464,8 @@ static int ipw2100_wx_set_scan(struct net_device *dev, } IPW_DEBUG_WX("Initiating scan...\n"); + + priv->user_requested_scan = 1; if (ipw2100_set_scan_options(priv) || ipw2100_start_scan(priv)) { IPW_DEBUG_WX("Start scan failed.\n"); diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h index de7d384..1ee3348 100644 --- a/drivers/net/wireless/ipw2100.h +++ b/drivers/net/wireless/ipw2100.h @@ -588,6 +588,10 @@ struct ipw2100_priv { struct delayed_work wx_event_work; struct delayed_work hang_check; struct delayed_work rf_kill; + struct work_struct scan_event_now; + struct delayed_work scan_event_later; + + int user_requested_scan; u32 interrupts; int tx_interrupts; -- 1.5.2.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH] rtl8187: Fix more frag bit checking, rts duration calc 2007-10-26 21:04 ` [PATCH] ipw2100: send WEXT scan events John W. Linville @ 2007-10-26 21:04 ` John W. Linville 2007-10-26 21:04 ` [PATCH] zd1211rw, fix oops when ejecting install media John W. Linville 0 siblings, 1 reply; 5+ messages in thread From: John W. Linville @ 2007-10-26 21:04 UTC (permalink / raw) To: stable; +Cc: linux-wireless, Michael Wu, John W. Linville From: Michael Wu <flamingice@sourmilk.net> The wrong pointer is passed to ieee80211_get_morefrag. Fix this. While we're at it, reorder things so they look better and the rts duration calculation is done with the right length. Thanks to Christoph Hellwig for finding the ieee80211_get_morefrag issue. Signed-off-by: Michael Wu <flamingice@sourmilk.net> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- drivers/net/wireless/rtl8187_dev.c | 31 ++++++++++++++++--------------- 1 files changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index e61c6d5..66704b8 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -78,7 +78,8 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb, struct rtl8187_tx_hdr *hdr; struct rtl8187_tx_info *info; struct urb *urb; - u32 tmp; + __le16 rts_dur = 0; + u32 flags; urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { @@ -86,24 +87,24 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb, return 0; } - hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr)); - tmp = skb->len - sizeof(*hdr); - tmp |= RTL8187_TX_FLAG_NO_ENCRYPT; - tmp |= control->rts_cts_rate << 19; - tmp |= control->tx_rate << 24; - if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb)) - tmp |= RTL8187_TX_FLAG_MORE_FRAG; + flags = skb->len; + flags |= RTL8187_TX_FLAG_NO_ENCRYPT; + flags |= control->rts_cts_rate << 19; + flags |= control->tx_rate << 24; + if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb->data)) + flags |= RTL8187_TX_FLAG_MORE_FRAG; if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) { - tmp |= RTL8187_TX_FLAG_RTS; - hdr->rts_duration = - ieee80211_rts_duration(dev, skb->len, control); + flags |= RTL8187_TX_FLAG_RTS; + rts_dur = ieee80211_rts_duration(dev, skb->len, control); } if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) - tmp |= RTL8187_TX_FLAG_CTS; - hdr->flags = cpu_to_le32(tmp); + flags |= RTL8187_TX_FLAG_CTS; + + hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr)); + hdr->flags = cpu_to_le32(flags); hdr->len = 0; - tmp = control->retry_limit << 8; - hdr->retry = cpu_to_le32(tmp); + hdr->rts_duration = rts_dur; + hdr->retry = cpu_to_le32(control->retry_limit << 8); info = (struct rtl8187_tx_info *)skb->cb; info->control = kmemdup(control, sizeof(*control), GFP_ATOMIC); -- 1.5.2.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH] zd1211rw, fix oops when ejecting install media 2007-10-26 21:04 ` [PATCH] rtl8187: Fix more frag bit checking, rts duration calc John W. Linville @ 2007-10-26 21:04 ` John W. Linville 0 siblings, 0 replies; 5+ messages in thread From: John W. Linville @ 2007-10-26 21:04 UTC (permalink / raw) To: stable; +Cc: linux-wireless, Marc Pignat, John W. Linville From: Marc Pignat <marc.pignat@hevs.ch> The disconnect function can dereference the net_device structure when it is never allocated. This is the case when ejecting the device installer. Signed-off-by: Marc Pignat <marc.pignat@hevs.ch> Acked-by: Daniel Drake <dsd@gentoo.org> Signed-off-by: John W. Linville <linville@tuxdriver.com> --- drivers/net/wireless/zd1211rw/zd_usb.c | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index a9c339e..5326301 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -1041,14 +1041,17 @@ error: static void disconnect(struct usb_interface *intf) { struct net_device *netdev = zd_intf_to_netdev(intf); - struct zd_mac *mac = zd_netdev_mac(netdev); - struct zd_usb *usb = &mac->chip.usb; + struct zd_mac *mac; + struct zd_usb *usb; /* Either something really bad happened, or we're just dealing with * a DEVICE_INSTALLER. */ if (netdev == NULL) return; + mac = zd_netdev_mac(netdev); + usb = &mac->chip.usb; + dev_dbg_f(zd_usb_dev(usb), "\n"); zd_netdev_disconnect(netdev); -- 1.5.2.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2007-10-26 21:05 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2007-10-15 6:51 [PATCH] zd1211rw, fix oops when ejecting install media Marc Pignat 2007-10-15 11:05 ` Daniel Drake 2007-10-16 6:33 ` Marc Pignat 2007-10-16 13:02 ` Daniel Drake -- strict thread matches above, loose matches on Subject: below -- 2007-10-26 21:04 [PATCH] Add get_unaligned to ieee80211_get_radiotap_len John W. Linville 2007-10-26 21:04 ` [PATCH] Improve sanity checks on injected packets John W. Linville 2007-10-26 21:04 ` [PATCH] mac80211: filter locally-originated multicast frames John W. Linville 2007-10-26 21:04 ` [PATCH] libertas: fix endianness breakage John W. Linville 2007-10-26 21:04 ` [PATCH] libertas: more " John W. Linville 2007-10-26 21:04 ` [PATCH] ieee80211: fix TKIP QoS bug John W. Linville 2007-10-26 21:04 ` [PATCH] mac80211: reorder association debug output John W. Linville 2007-10-26 21:04 ` [PATCH] mac80211: store channel info in sta_bss_list John W. Linville 2007-10-26 21:04 ` [PATCH] mac80211: store SSID " John W. Linville 2007-10-26 21:04 ` [PATCH] mac80211: honor IW_SCAN_THIS_ESSID in siwscan ioctl John W. Linville 2007-10-26 21:04 ` [PATCH] mac80211: only honor IW_SCAN_THIS_ESSID in STA, IBSS, and AP modes John W. Linville 2007-10-26 21:04 ` [PATCH] mac80211: make ieee802_11_parse_elems return void John W. Linville 2007-10-26 21:04 ` [PATCH] zd1201: avoid null ptr access of skb->dev John W. Linville 2007-10-26 21:04 ` [PATCH] ipw2100: send WEXT scan events John W. Linville 2007-10-26 21:04 ` [PATCH] rtl8187: Fix more frag bit checking, rts duration calc John W. Linville 2007-10-26 21:04 ` [PATCH] zd1211rw, fix oops when ejecting install media John W. Linville
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).