Skip to contentSkip to conversation

Set of small fixes to net/d80211

PATCH In review Jouni Malinen 4 participants 14 messages Aug 7, 2006 – Aug 24, 2006

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover Set of small fixes to net/d80211

Here's a set of small fixes to net/d80211 from the Devicescape tree. Please consider applying.

--

Signature · 1 line
Jouni Malinen                                            PGP id EFC895FA
#1 lore raw

PATCH 1/6 d80211: Fix RTS threshold use

Fixed dot11RTSThreshold use which was off-by-3:
- must add FCS_LEN to the skb->len
- frame length needs to be greater than threshold; not greater than or equal

net/d80211/ieee80211.c +1 -1
Index: wireless-dev/net/d80211/ieee80211.c
===================================================================
@@ -762,7 +762,7 @@ ieee80211_tx_h_misc(struct ieee80211_txr
 	struct ieee80211_tx_control *control = tx->u.tx.control;
 
 	if (!is_multicast_ether_addr(hdr->addr1)) {
-		if (tx->skb->len >= tx->local->rts_threshold &&
+		if (tx->skb->len + FCS_LEN > tx->local->rts_threshold &&
 		    tx->local->rts_threshold < IEEE80211_MAX_RTS_THRESHOLD) {
 			control->use_rts_cts = 1;
 			control->retry_limit =

--

Signature · 1 line
Jouni Malinen                                            PGP id EFC895FA
#2 lore raw

PATCH 2/6 d80211: Fix PS-Poll frame dropping

In reply to Jouni Malinen

Fixed PS-Poll processing for STAs that are not authenticated or associated:
- 80211.ko dropped these frames even though it should have sent them to hostapd (this was broken by addition of IBSS support)

net/d80211/ieee80211.c +3 -2
Index: wireless-dev/net/d80211/ieee80211.c
===================================================================
@@ -3074,8 +3074,9 @@ ieee80211_rx_h_check(struct ieee80211_tx
 		     rx->sdata->type != IEEE80211_IF_TYPE_IBSS &&
 		     (!rx->sta || !(rx->sta->flags & WLAN_STA_ASSOC)))) {
 		if ((!(rx->fc & IEEE80211_FCTL_FROMDS) &&
-		     !(rx->fc & IEEE80211_FCTL_TODS)) ||
-		    !rx->u.rx.ra_match) {
+		     !(rx->fc & IEEE80211_FCTL_TODS) &&
+		     (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)
+		    || !rx->u.rx.ra_match) {
 			/* Drop IBSS frames and frames for other hosts
 			 * silently. */
 			return TXRX_DROP;

--

Signature · 1 line
Jouni Malinen                                            PGP id EFC895FA
#3 lore raw

PATCH 3/6 d80211: Fix PLCP header length comment

In reply to Jouni Malinen

Fixed a typo in a comment: PLCP header length is in microseconds, not milliseconds.

net/d80211/ieee80211.c +1 -1
Index: wireless-dev/net/d80211/ieee80211.c
===================================================================
@@ -637,7 +637,7 @@ static int ieee80211_frame_duration(stru
 		 * 802.11 (DS): 15.3.3, 802.11b: 18.3.4
 		 * aSIFSTime = 10 usec
 		 * aPreambleLength = 144 usec or 72 usec with short preamble
-		 * aPLCPHeaderLength = 48 ms or 24 ms with short preamble
+		 * aPLCPHeaderLength = 48 usec or 24 usec with short preamble
 		 */
 		dur = 10; /* aSIFSTime = 10 usec */
 		dur += short_preamble ? (72 + 24) : (144 + 48);

--

Signature · 1 line
Jouni Malinen                                            PGP id EFC895FA
#4 lore raw

PATCH 4/6 d80211: Send Layer 2 Update frames in kernel

In reply to Jouni Malinen

Send Layer 2 Update frame from the 802.11 code in kernel to the netdev that the STA is bound to. If the STA is bound to another VLAN netdev, send another update frame. This fixes an issue in which a local bridge table was not updated when hostapd sent this frame.

net/d80211/ieee80211_ioctl.c +55 -0
Index: wireless-dev/net/d80211/ieee80211_ioctl.c
===================================================================
@@ -15,6 +15,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/skbuff.h>
+#include <linux/etherdevice.h>
 #include <linux/if_arp.h>
 #include <linux/wireless.h>
 #include <net/iw_handler.h>
@@ -215,6 +216,52 @@ static int ieee80211_ioctl_flush(struct 
 }
 
 
+/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
+struct iapp_layer2_update {
+	u8 da[ETH_ALEN]; /* broadcast */
+	u8 sa[ETH_ALEN]; /* STA addr */
+	u16 len; /* 6 */
+	u8 dsap; /* 0 */
+	u8 ssap; /* 0 */
+	u8 control;
+	u8 xid_info[3];
+} __attribute__ ((packed));
+
+static void ieee80211_send_layer2_update(struct net_device *dev,
+					 const u8 *addr)
+{
+	struct iapp_layer2_update *msg;
+	struct sk_buff *skb;
+
+	/* Send Level 2 Update Frame to update forwarding tables in layer 2
+	 * bridge devices */
+
+	skb = dev_alloc_skb(sizeof(*msg));
+	if (skb == NULL)
+		return;
+	msg = (struct iapp_layer2_update *) skb_put(skb, sizeof(*msg));
+
+	/* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID)
+	 * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */
+
+	memset(msg->da, 0xff, ETH_ALEN);
+	memcpy(msg->sa, addr, ETH_ALEN);
+	msg->len = htons(6);
+	msg->dsap = 0;
+	msg->ssap = 0x01; /* NULL LSAP, CR Bit: Response */
+	msg->control = 0xaf; /* XID response lsb.1111F101.
+			      * F=0 (no poll command; unsolicited frame) */
+	msg->xid_info[0] = 0x81; /* XID format identifier */
+	msg->xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */
+	msg->xid_info[2] = 0; /* XID sender's receive window size (RW) */
+
+	skb->dev = dev;
+	skb->protocol = eth_type_trans(skb, dev);
+	memset(skb->cb, 0, sizeof(skb->cb));
+	netif_rx(skb);
+}
+
+
 static int ieee80211_ioctl_add_sta(struct net_device *dev,
 				   struct prism2_hostapd_param *param)
 {
@@ -296,6 +343,10 @@ static int ieee80211_ioctl_add_sta(struc
 
 	sta_info_put(sta);
 
+	if (sdata->type == IEEE80211_IF_TYPE_AP ||
+	    sdata->type == IEEE80211_IF_TYPE_VLAN)
+		ieee80211_send_layer2_update(dev, param->sta_addr);
+
 	return 0;
 }
 
@@ -1168,6 +1219,10 @@ static int ieee80211_ioctl_set_sta_vlan(
 			       dev->name, MAC_ARG(param->sta_addr),
                                new_vlan_dev->name);
 #endif
+			if (sta->dev != new_vlan_dev) {
+				ieee80211_send_layer2_update(new_vlan_dev,
+							     sta->addr);
+			}
                         sta->dev = new_vlan_dev;
 			sta->vlan_id = param->u.set_sta_vlan.vlan_id;
                         dev_put(new_vlan_dev);

--

Signature · 1 line
Jouni Malinen                                            PGP id EFC895FA
#5 lore raw

Re: [PATCH wireless-dev 4/6] d80211: Send Layer 2 Update frames in kernel

Quoted 4 lines · Jouni Malinen

Send Layer 2 Update frame from the 802.11 code in kernel to the netdev that the STA is bound to. If the STA is bound to another VLAN netdev, send another update frame. This fixes an issue in which a local bridge table was not updated when hostapd sent this frame.

This seems like a hack to me. Isn't there some netlink mechanism that can be used instead?

Jiri

Signature · 2 lines
Jiri Benc
SUSE Labs
#6 lore raw

Re: [PATCH wireless-dev 4/6] d80211: Send Layer 2 Update frames in kernel

In reply to Jouni Malinen
Quoted 4 lines · Jouni Malinen

Send Layer 2 Update frame from the 802.11 code in kernel to the netdev that the STA is bound to. If the STA is bound to another VLAN netdev, send another update frame. This fixes an issue in which a local bridge table was not updated when hostapd sent this frame.

I hope someone is going to describe why is this necessary and why it cannot be done in a less hackish way. Otherwise, I'd probably tend to ask for reverting this patch.

Thanks,

Jiri

Signature · 2 lines
Jiri Benc
SUSE Labs
#7 lore raw

Re: [PATCH wireless-dev 4/6] d80211: Send Layer 2 Update frames in kernel

Am Mittwoch, 23. August 2006 19:22 schrieb Jiri Benc:

Quoted 8 lines
Quoted 4 lines

Send Layer 2 Update frame from the 802.11 code in kernel to the netdev that the STA is bound to. If the STA is bound to another VLAN netdev, send another update frame. This fixes an issue in which a local bridge table was not updated when hostapd sent this frame.

I hope someone is going to describe why is this necessary and why it cannot be done in a less hackish way. Otherwise, I'd probably tend to ask for reverting this patch.

Imagine an ESS consisting of several APs in a switched wired network. Client roams from one AP to another. In order to update the FDB of the switches, a packet with the client MAC address needs to be originated from the ethernet interface of the AP the client has associated to, even if the client does not create traffic at the moment.

It's part of 802.11F.

Stefan

#8 lore raw

Re: [PATCH wireless-dev 4/6] d80211: Send Layer 2 Update frames in kernel

Quoted 5 lines · Stefan Rompf

Imagine an ESS consisting of several APs in a switched wired network. Client roams from one AP to another. In order to update the FDB of the switches, a packet with the client MAC address needs to be originated from the ethernet interface of the AP the client has associated to, even if the client does not create traffic at the moment.

Thanks for the explanation! I didn't thought about ESS when looking at that patch.

If I understand it right, it's not necessary to send the XID Update frame for each added STA. Shouldn't there be a flag indicating if the frame needs to be send? Userspace knows that information.

Thanks,

Jiri

Signature · 2 lines
Jiri Benc
SUSE Labs
#9 lore raw

Re: [PATCH wireless-dev 4/6] d80211: Send Layer 2 Update frames in kernel

In reply to Jiri Benc
Quoted 9 lines · Jiri Benc
Quoted 4 lines · Jouni Malinen

Send Layer 2 Update frame from the 802.11 code in kernel to the netdev that the STA is bound to. If the STA is bound to another VLAN netdev, send another update frame. This fixes an issue in which a local bridge table was not updated when hostapd sent this frame.

I hope someone is going to describe why is this necessary and why it cannot be done in a less hackish way. Otherwise, I'd probably tend to ask for reverting this patch.

Which part do you think is hackish here? Sending the layer 2 update frame or moving it to kernel?

Signature · 1 line
Jouni Malinen                                            PGP id EFC895FA
#10 lore raw

Re: [PATCH wireless-dev 4/6] d80211: Send Layer 2 Update frames in kernel

Quoted 2 lines · Jouni Malinen

Which part do you think is hackish here? Sending the layer 2 update frame or moving it to kernel?

The latter.

Is it really needed to send it unconditionally for each added STA? And cannot it be generated in userspace?

Thanks,

Jiri

Signature · 2 lines
Jiri Benc
SUSE Labs
#11 lore raw

Re: [PATCH wireless-dev 4/6] d80211: Send Layer 2 Update frames in kernel

Quoted 8 lines · Jiri Benc
Quoted 2 lines · Jouni Malinen

Which part do you think is hackish here? Sending the layer 2 update frame or moving it to kernel?

The latter.

Is it really needed to send it unconditionally for each added STA? And cannot it be generated in userspace?

Yes, it must be sent out whenever a STA associates with the AP, i.e., for every STA and for every association.. This is needed to update both the internal bridge tables in the AP and the external bridge tables in switches etc. connected to the same physical net in order to make sure that future frames to the STA's MAC address are delivered to the correct AP--and within that AP, to the correct port.

This was originally done in hostapd in userspace, but this showed a bug in which the local bridge tables did not get updated correctly in some specific configurations. In addition, doing this in hostapd would require that hostapd knows (or can learn) how the bridge configuration is done on the device and this information is not really needed for anything else, so there would not really be much point in keeping that functionality in hostapd.

The simplest solution for this seems to be to allow the layer 2 update frame to be sent through the exact same path as any data frame from the STA would be coming. This makes sure that it goes through the local bridge in the same way as other frames from the STA would go and it will also be sent out to correct external (wired/WDS) ports automatically based on bridge configuration.

Signature · 1 line
Jouni Malinen                                            PGP id EFC895FA
#12 lore raw

PATCH 5/6 d80211: Fix ieee80211_remove_tx_extra() if key not configured

In reply to Jouni Malinen

QoS header processing mangled unencrypted WMM frames on software retry. The QoS data needs to be removed even when encryption key is not configured.

net/d80211/ieee80211.c +5 -4
Index: wireless-dev/net/d80211/ieee80211.c
===================================================================
@@ -3977,11 +3977,11 @@ static void ieee80211_remove_tx_extra(st
 	pkt_data->requeue = control->requeue;
 	pkt_data->queue = control->queue;
 
-	if (key == NULL)
-		return;
-
 	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
 
+	if (key == NULL)
+		goto no_key;
+
 	switch (key->alg) {
 	case ALG_WEP:
 		iv_len = WEP_IV_LEN;
@@ -3996,7 +3996,7 @@ static void ieee80211_remove_tx_extra(st
 		mic_len = CCMP_MIC_LEN;
 		break;
 	default:
-		return;
+		goto no_key;
 	}
 
 	if (skb->len >= mic_len && key->force_sw_encrypt)
@@ -4006,6 +4006,7 @@ static void ieee80211_remove_tx_extra(st
 		skb_pull(skb, iv_len);
 	}
 
+no_key:
 	{
 		struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 		u16 fc = le16_to_cpu(hdr->frame_control);

--

Signature · 1 line
Jouni Malinen                                            PGP id EFC895FA
#13 lore raw

PATCH 6/6 d80211: Fix TKIP replay protection

In reply to Jouni Malinen

Fixed TKIP replay protection for the case where hwaccel is enabled. rx_initialized flag was not set in this case and the TSC validation was skipped for the frames.

net/d80211/tkip.c +1 -0
Index: wireless-dev/net/d80211/tkip.c
===================================================================
@@ -286,6 +286,7 @@ int ieee80211_tkip_decrypt_data(struct c
 
 	if (only_iv) {
 		res = TKIP_DECRYPT_OK;
+		key->u.tkip.rx_initialized[queue] = 1;
 		goto done;
 	}
 

--

Signature · 1 line
Jouni Malinen                                            PGP id EFC895FA