SOURCES: madwifi-ng-009-csa_ie_handling_fix.patch (NEW), madwifi-n...

mguevara mguevara at pld-linux.org
Sat Oct 21 03:05:21 CEST 2006


Author: mguevara                     Date: Sat Oct 21 01:05:21 2006 GMT
Module: SOURCES                       Tag: HEAD
---- Log message:
- from lintrack distro - in the madwifi-ng-0.9.3 milestone queue

---- Files affected:
SOURCES:
   madwifi-ng-009-csa_ie_handling_fix.patch (NONE -> 1.1)  (NEW), madwifi-ng-010-true_radiotap_parser.patch (NONE -> 1.1)  (NEW), madwifi-ng-011-suppress_plaintext.patch (NONE -> 1.1)  (NEW)

---- Diffs:

================================================================
Index: SOURCES/madwifi-ng-009-csa_ie_handling_fix.patch
diff -u /dev/null SOURCES/madwifi-ng-009-csa_ie_handling_fix.patch:1.1
--- /dev/null	Sat Oct 21 03:05:21 2006
+++ SOURCES/madwifi-ng-009-csa_ie_handling_fix.patch	Sat Oct 21 03:05:16 2006
@@ -0,0 +1,348 @@
+#
+# madwifi-0.9.2 csa_ie_handling_fix.diff
+#
+# This patch fixes susceptibility to remote abuse of Channel Switch
+# Announcement Information Elements by injection of Beacon Frame
+# packets and improves the reliability of channel switch procedure under
+# conditions of frequent beacon misses.
+# 
+# For a more detailed description see ticket #101.
+#
+# 2006-09-07, Michal Wrobel <xmxwx at asn.pl>
+#
+Index: madwifi/net80211/ieee80211.h
+===================================================================
+--- madwifi/net80211/ieee80211.h	(revision 961)
++++ madwifi/net80211/ieee80211.h	(revision 962)
+@@ -363,6 +363,24 @@
+ 	u_int8_t country_triplet[IEEE80211_COUNTRY_MAX_TRIPLETS * 3];
+ } __packed;
+ 
++/*
++ * Channel Switch Announcement information element.
++ */
++struct ieee80211_ie_csa {
++	u_int8_t csa_id;	/* IEEE80211_ELEMID_CHANSWITCHANN */
++	u_int8_t csa_len;	/* == 3 */
++	u_int8_t csa_mode;	/* Channel Switch Mode: 1 == stop transmission until CS */
++	u_int8_t csa_chan;	/* New Channel Number */
++	u_int8_t csa_count;	/* TBTTs until Channel Switch happens */
++} __packed;
++
++/* minimal Channel Switch Count in the initial announcement */
++#define IEEE80211_CSA_PROTECTION_PERIOD 3
++
++/* maximum allowed deviance of measurement of intervals between CSA in Beacons */
++#define IEEE80211_CSA_SANITY_THRESHOLD 100    
++
++
+ /* does frame have QoS sequence control data */
+ #define	IEEE80211_QOS_HAS_SEQ(wh) \
+ 	(((wh)->i_fc[0] & \
+Index: madwifi/net80211/ieee80211_scan.h
+===================================================================
+--- madwifi/net80211/ieee80211_scan.h	(revision 961)
++++ madwifi/net80211/ieee80211_scan.h	(revision 962)
+@@ -138,7 +138,7 @@
+ 	u_int8_t *ssid;
+ 	u_int8_t *rates;
+ 	u_int8_t *xrates;
+-	u_int8_t *doth;
++	u_int8_t *csa;
+ 	u_int8_t *wpa;
+ 	u_int8_t *rsn;
+ 	u_int8_t *wme;
+Index: madwifi/net80211/ieee80211_input.c
+===================================================================
+--- madwifi/net80211/ieee80211_input.c	(revision 961)
++++ madwifi/net80211/ieee80211_input.c	(revision 962)
+@@ -2237,58 +2237,200 @@
+ 	return c;
+ }
+ 
++static void
++ieee80211_doth_cancel_cs(struct ieee80211vap *vap)
++{
++	del_timer(&vap->iv_csa_timer);
++	if (vap->iv_csa_jiffies) 
++		IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH,
++				"channel switch cancelled (was: to %u in %u "
++				"tbtt, mode %u)\n", vap->iv_csa_chan->ic_ieee,
++				vap->iv_csa_count, vap->iv_csa_mode);
++	vap->iv_csa_jiffies = 0;
++}
++
++static void
++ieee80211_doth_switch_channel(struct ieee80211vap *vap)
++{
++	struct ieee80211com *ic = vap->iv_ic;
++
++	IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH,
++			"%s: Channel switch to %d NOW!\n",
++			__func__, vap->iv_csa_chan->ic_ieee);
++#if 0
++	/* XXX does not belong here? */
++	/* XXX doesn't stop management frames */
++	/* XXX who restarts the queue? */
++	/* NB: for now, error here is non-catastrophic.
++	 *     in the future we may need to ensure we
++	 *     stop xmit on this channel.
++	 */
++	netif_stop_queue(ic->ic_dev);
++#endif
++
++	vap->iv_csa_jiffies = 0; /* supress "cancel" msg */
++	ieee80211_doth_cancel_cs(vap);
++
++	ic->ic_prevchan = ic->ic_curchan;
++	ic->ic_curchan = ic->ic_bsschan = vap->iv_csa_chan;
++	ic->ic_set_channel(ic);
++}
++
++static void
++ieee80211_doth_switch_channel_tmr(unsigned long arg)
++{
++	struct ieee80211vap *vap = (struct ieee80211vap *)arg;
++	ieee80211_doth_switch_channel(vap);
++}
++
+ static int
+-ieee80211_parse_dothparams(struct ieee80211vap *vap, u_int8_t *frm,
++ieee80211_parse_csaie(struct ieee80211_node *ni, u_int8_t *frm,
+ 	const struct ieee80211_frame *wh)
+ {
++	struct ieee80211vap *vap = ni->ni_vap;
+ 	struct ieee80211com *ic = vap->iv_ic;
+-	u_int len = frm[1];
+-	u_int8_t chan, tbtt;
++	struct ieee80211_channel *c;
++	struct ieee80211_ie_csa *csa_ie = (struct ieee80211_ie_csa *)frm;
+ 
+-	if (len < 4 - 2) {		/* XXX ie struct definition */
++	if (!frm) {
++		/* we had CS underway but now we got Beacon without CSA IE */
++		/* XXX abuse? */
++
++		IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH,
++				"%s: channel switch is scheduled, but we got "
++				"Beacon without CSA IE!\n", __func__);
++
++		ieee80211_doth_cancel_cs(vap);
++		return 0;
++	}
++
++	if (csa_ie->csa_len != 3) {
+ 		IEEE80211_DISCARD_IE(vap,
+ 			IEEE80211_MSG_ELEMID | IEEE80211_MSG_DOTH,
+-			wh, "channel switch", "too short, len %u", len);
++			wh, "channel switch", "invalid length %u",
++			csa_ie->csa_len);
+ 		return -1;
+ 	}
+-	chan = frm[3];
+-	if (isclr(ic->ic_chan_avail, chan)) {
++
++	if (isclr(ic->ic_chan_avail, csa_ie->csa_chan)) {
+ 		IEEE80211_DISCARD_IE(vap,
+ 			IEEE80211_MSG_ELEMID | IEEE80211_MSG_DOTH,
+-			wh, "channel switch", "invalid channel %u", chan);
++			wh, "channel switch", "invalid channel %u", 
++			csa_ie->csa_chan);
+ 		return -1;
+ 	}
+-	tbtt = frm[4];
+-	IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH,
+-		"%s: channel switch to %d in %d tbtt\n", __func__, chan, tbtt);
+-	if (tbtt <= 1) {
+-		struct ieee80211_channel *c;
+ 
+-		IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH,
+-			"%s: Channel switch to %d NOW!\n", __func__, chan);
+-#if 0
+-		/* XXX does not belong here? */
+-		/* XXX doesn't stop management frames */
+-		/* XXX who restarts the queue? */
+-		/* NB: for now, error here is non-catastrophic.
+-		 *     in the future we may need to ensure we
+-		 *     stop xmit on this channel.
+-		 */
+-		netif_stop_queue(ic->ic_dev);
+-#endif
+-		if ((c = ieee80211_doth_findchan(vap, chan)) == NULL) {
+-			/* XXX something wrong */
+-			IEEE80211_DISCARD_IE(vap,
++	if ((c = ieee80211_doth_findchan(vap, csa_ie->csa_chan)) == NULL) {
++		/* XXX something wrong */
++		IEEE80211_DISCARD_IE(vap,
+ 				IEEE80211_MSG_ELEMID | IEEE80211_MSG_DOTH,
+ 				wh, "channel switch",
+-				"channel %u lookup failed", chan);
++				"channel %u lookup failed", csa_ie->csa_chan);
++		return -1;
++	}
++
++	IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH,
++		"%s: channel switch to %u in %u tbtt (mode %u) announced\n",
++		__func__, csa_ie->csa_chan, csa_ie->csa_count,
++		csa_ie->csa_mode);
++
++	if (vap->iv_csa_jiffies) {
++		/* CSA was received recently */
++		if (c != vap->iv_csa_chan) {
++			/* XXX abuse? */
++			IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH,
++					"%s: channel switch channel "
++					"changed from %u to %u!\n", __func__,
++					vap->iv_csa_chan->ic_ieee,
++					csa_ie->csa_chan);
++
++			if (vap->iv_csa_count > IEEE80211_CSA_PROTECTION_PERIOD)
++				ieee80211_doth_cancel_cs(vap);
+ 			return 0;
+ 		}
+-		ic->ic_prevchan = ic->ic_curchan;
+-		ic->ic_curchan = ic->ic_bsschan = c;
+-		ic->ic_set_channel(ic);
+-		return 1;
++
++		if (csa_ie->csa_mode != vap->iv_csa_mode) {
++			/* Can be abused, but with no (to little) impact. */
++
++			/* CS mode change has no influence on our actions since
++			 * we don't respect cs modes at all (yet). Complain and
++			 * forget. */
++			IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH,
++					"%s: channel switch mode changed from "
++					"%u to %u!\n", __func__, 
++					vap->iv_csa_mode, csa_ie->csa_mode);
++		}
++
++		if (csa_ie->csa_count >= vap->iv_csa_count) {
++			/* XXX abuse? what for? */
++			IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH,
++					"%s: channel switch count didn't "
++					"decrease (%u -> %u)!\n", __func__,
++					vap->iv_csa_count, csa_ie->csa_count);
++			return 0;
++		}
++
++		{
++			u_int32_t elapsed = IEEE80211_JIFFIES_TO_TU(
++			    jiffies - vap->iv_csa_jiffies);
++			u_int32_t cnt_diff = vap->iv_csa_count -
++			  csa_ie->csa_count;
++			u_int32_t expected = ni->ni_intval * cnt_diff;
++			int32_t delta = elapsed - expected;
++			if (delta < 0)
++				delta = -delta;
++			if (delta > IEEE80211_CSA_SANITY_THRESHOLD) {
++				/* XXX abuse? for now, it's safer to cancel CS
++				 * than to follow it blindly */
++				IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH,
++						"%s: %u.%02u bintvals elapsed, "
++						"but count dropped by %u (delta"
++						" = %u TUs)\n", __func__,
++						elapsed / ni->ni_intval,
++						elapsed * 100 / ni->ni_intval 
++						% 100, cnt_diff, delta);
++
++				ieee80211_doth_cancel_cs(vap);
++				return 0;
++			}
++		}
++
++		vap->iv_csa_count = csa_ie->csa_count;
++		mod_timer(&vap->iv_csa_timer, jiffies + 
++				IEEE80211_TU_TO_JIFFIES(vap->iv_csa_count
++				  * ni->ni_intval + 10));
++	} else {
++		/* CSA wasn't received recently, so this is the first one in
++		 * the sequence. */
++
++		if (csa_ie->csa_count < IEEE80211_CSA_PROTECTION_PERIOD) {
++			/* XXX abuse? */
++			IEEE80211_DISCARD_IE(vap,
++					IEEE80211_MSG_ELEMID | 
++					IEEE80211_MSG_DOTH,
++					wh, "channel switch",
++					"initial announcement: channel switch"
++					" would occur too soon (in %u tbtt)",
++					csa_ie->csa_count);
++			return 0;
++		}
++
++		vap->iv_csa_mode = csa_ie->csa_mode;
++		vap->iv_csa_count = csa_ie->csa_count;
++		vap->iv_csa_chan = c;
++
++		vap->iv_csa_timer.function = ieee80211_doth_switch_channel_tmr;
++		vap->iv_csa_timer.data = (unsigned long)vap;
++		vap->iv_csa_timer.expires = jiffies + IEEE80211_TU_TO_JIFFIES(
++		    vap->iv_csa_count * ni->ni_intval + 10);
++		add_timer(&vap->iv_csa_timer);
+ 	}
++
++	vap->iv_csa_jiffies = jiffies;
++
++	if (vap->iv_csa_count <= 1)
++		ieee80211_doth_switch_channel(vap);
++
+ 	return 0;
+ }
+ 
+@@ -2485,7 +2627,7 @@
+ 				break;
+ 			case IEEE80211_ELEMID_CHANSWITCHANN:
+ 				if (ic->ic_flags & IEEE80211_F_DOTH)
+-					scan.doth = frm;
++					scan.csa = frm;
+ 				break;
+ 			default:
+ 				IEEE80211_DISCARD_IE(vap, IEEE80211_MSG_ELEMID,
+@@ -2628,8 +2770,8 @@
+ 				ni->ni_flags &= ~IEEE80211_NODE_UAPSD;
+ 			if (scan.ath != NULL)
+ 				ieee80211_parse_athParams(ni, scan.ath);
+-			if (scan.doth != NULL)
+-				ieee80211_parse_dothparams(vap, scan.doth, wh);
++			if (scan.csa != NULL || vap->iv_csa_jiffies)
++				ieee80211_parse_csaie(ni, scan.csa, wh);
+ 			if (scan.tim != NULL) {
+ 				/*
+ 				 * Check the TIM. For now we drop out of
+Index: madwifi/net80211/ieee80211_var.h
+===================================================================
+--- madwifi/net80211/ieee80211_var.h	(revision 961)
++++ madwifi/net80211/ieee80211_var.h	(revision 962)
+@@ -87,6 +87,7 @@
+ #define	IEEE80211_MS_TO_TU(x)	(((x) * 1000) / 1024)
+ #define	IEEE80211_TU_TO_MS(x)	(((x) * 1024) / 1000)
+ #define	IEEE80211_TU_TO_JIFFIES(x) ((IEEE80211_TU_TO_MS(x) * HZ) / 1000)
++#define	IEEE80211_JIFFIES_TO_TU(x) IEEE80211_MS_TO_TU((x) * 1000 / HZ)
+ 
+ #define IEEE80211_PWRCONSTRAINT_VAL(ic) \
+ 	(((ic)->ic_bsschan->ic_maxregpower > (ic)->ic_curchanmaxpwr) ? \
+@@ -341,6 +342,11 @@
+ 	u_int iv_scanvalid;			/* scan cache valid threshold */
+ 	struct ieee80211_roam iv_roam;		/* sta-mode roaming state */
+ 
++	u_int32_t iv_csa_jiffies;		/* last csa recv jiffies */
++	u_int8_t iv_csa_count;			/* last csa count */
++	struct ieee80211_channel *iv_csa_chan;	/* last csa channel */
++	u_int8_t iv_csa_mode;			/* last csa mode */
++	struct timer_list iv_csa_timer;		/* csa timer */
+ 	u_int32_t *iv_aid_bitmap;		/* association id map */
+ 	u_int16_t iv_max_aid;
+ 	u_int16_t iv_sta_assoc;			/* stations associated */
+Index: madwifi/net80211/ieee80211_proto.c
+===================================================================
+--- madwifi/net80211/ieee80211_proto.c	(revision 961)
++++ madwifi/net80211/ieee80211_proto.c	(revision 962)
+@@ -125,6 +125,7 @@
+ 	init_timer(&vap->iv_mgtsend);
+ 	init_timer(&vap->iv_xrvapstart);
+ 	init_timer(&vap->iv_swbmiss);
++	init_timer(&vap->iv_csa_timer);
+ 	vap->iv_mgtsend.function = ieee80211_tx_timeout;
+ 	vap->iv_mgtsend.data = (unsigned long) vap;
+ 

================================================================
Index: SOURCES/madwifi-ng-010-true_radiotap_parser.patch
diff -u /dev/null SOURCES/madwifi-ng-010-true_radiotap_parser.patch:1.1
--- /dev/null	Sat Oct 21 03:05:21 2006
+++ SOURCES/madwifi-ng-010-true_radiotap_parser.patch	Sat Oct 21 03:05:16 2006
@@ -0,0 +1,154 @@
+#
+# madwifi-0.9.2 true_radiotap_parser.diff
+#
+# This patch adds radiotap header parsing capability to ieee80211_monitor_encap.
+# It allows userspace applications to send frames encapsulated in radiotap
+# header containing any arbitrary subset of fields (from the set of known ones)
+# instead of the fixed ath_tx_radiotap_header. It properly handles extended
+# field presence bitmaps and removes FCS from the end of the frame if it is
+# present according to an apropriate radiotap header flag. Parsing stops after
+# encountering unknown field.
+#
+# 2006-09-18, Michal Wrobel <xmxwx at asn.pl>
+#
+--- madwifi/net80211/ieee80211_monitor.c
++++ madwifi/net80211/ieee80211_monitor.c
+@@ -165,6 +163,107 @@
+ 			ph->try0 = 1;
+                 break;
+ 	}
++	case ARPHRD_IEEE80211_RADIOTAP: {
++		struct ieee80211_frame *wh = NULL;
++		struct ieee80211_radiotap_header *rh =
++			(struct ieee80211_radiotap_header *)skb->data;
++		u_int32_t present, present_ext;
++		u_int16_t len;
++		u_int8_t *start = skb->data + sizeof(struct ieee80211_radiotap_header);
++		u_int8_t *p = start;
++		u_int8_t *end = skb->data + skb->len;
++		u_int8_t bit, flags = 0;
++
++		if (skb->len < sizeof(*rh) || rh->it_version != 0)
++			break;
++
++		present_ext = present = le32_to_cpu(rh->it_present);
++		len = le16_to_cpu(rh->it_len);
++
++		if (skb->len < len)
++			break;
++
++		/* skip the chain of additional bitmaps following it_present */
++		while (present_ext & (1 << IEEE80211_RADIOTAP_EXT)) {
++			if (p+4 > end) {
++				/* An extended bitmap would now follow, but there is 
++				 * no place for it. Stop parsing. */
++				present = 0;
++				break;
++			}
++			present_ext = le32_to_cpu(*(u_int32_t*)p);
++			p += 4;
++		}
++
++		for (bit = 0; present && p < end; present >>= 1, bit++) {
++			if ((present & 1) == 0)
++				continue;
++			switch (bit) {
++				case IEEE80211_RADIOTAP_RATE:
++					ph->rate0 = *p;
++					p++;
++					break;
++
++				case IEEE80211_RADIOTAP_DBM_TX_POWER:
++					ph->power = *p;
++					p++;
++					break;
++
++				case IEEE80211_RADIOTAP_FLAGS:
++					flags = *p;
++					p++;
++					break;
++
++				case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
++				case IEEE80211_RADIOTAP_DB_ANTNOISE:
++				case IEEE80211_RADIOTAP_ANTENNA:
++				case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
++				case IEEE80211_RADIOTAP_DBM_ANTNOISE:
++					/* 8-bit */
++					p++;
++					break;
++
++				case IEEE80211_RADIOTAP_FHSS:
++					/* 2 x 8-bit */
++					p += 2;
++					break;
++
++				case IEEE80211_RADIOTAP_LOCK_QUALITY:
++				case IEEE80211_RADIOTAP_TX_ATTENUATION:
++				case IEEE80211_RADIOTAP_DB_TX_ATTENUATION:
++					/* 16-bit */
++					p = start + roundup(p - start, 2) + 2;
++					break;
++
++				case IEEE80211_RADIOTAP_CHANNEL:
++					/* 2 x 16-bit */
++					p = start + roundup(p - start, 2) + 4;
++					break;
++
++				case IEEE80211_RADIOTAP_FCS:
++					/* 32-bit */
++					p = start + roundup(p - start, 4) + 4;
++					break;
++
++				case IEEE80211_RADIOTAP_TSFT:
++					/* 64-bit */
++					p = start + roundup(p - start, 8) + 8;
++					break;
++
++				default:
++					present = 0;
++					break;
++			}
++		}
++		skb_pull(skb, len);
++		if (flags & IEEE80211_RADIOTAP_F_FCS)
++			/* Remove FCS from the end of frames to transmit */
++			skb_trim(skb, skb->len - IEEE80211_CRC_LEN);
++		wh = (struct ieee80211_frame *)skb->data;
++		if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL) 
++			ph->try0 = 1;
++                break;
++	}
+ 	case ARPHRD_IEEE80211_ATHDESC: {
+ 		if (skb->len > ATHDESC_HEADER_SIZE) {
+ 			struct ar5212_openbsd_desc *desc =
+@@ -182,16 +281,6 @@
+ 		}
+ 		break;
+ 	}	
+-	case ARPHRD_IEEE80211_RADIOTAP: {
+-		if(skb->len >  sizeof(struct ath_tx_radiotap_header)) {
+-			struct ath_tx_radiotap_header *wh = (struct ath_tx_radiotap_header *) skb->data;
+-			ph->power = wh->wt_txpower;
+-			ph->rate0 = wh->wt_rate;
+-			ph->try0 = 1;
+-			skb_pull(skb, sizeof(struct ath_tx_radiotap_header));
+-		}
+-		break;
+-	}
+ 	default:
+ 		break;
+ 	}
+--- madwifi/net80211/ieee80211_radiotap.h
++++ madwifi/net80211/ieee80211_radiotap.h
+@@ -216,5 +216,11 @@
+ #define	IEEE80211_RADIOTAP_F_FRAG	0x08	/* sent/received
+ 						 * with fragmentation
+ 						 */
++#define	IEEE80211_RADIOTAP_F_FCS	0x10	/* frame includes FCS */
++#define	IEEE80211_RADIOTAP_F_DATAPAD	0x20	/* frame has padding between
++						 * 802.11 header and payload
++						 * (to 32-bit boundary)
++						 */
++#define	IEEE80211_RADIOTAP_F_BADFCS	0x40	/* does not pass FCS check */
+ 
+ #endif /* _NET_IF_IEEE80211RADIOTAP_H_ */

================================================================
Index: SOURCES/madwifi-ng-011-suppress_plaintext.patch
diff -u /dev/null SOURCES/madwifi-ng-011-suppress_plaintext.patch:1.1
--- /dev/null	Sat Oct 21 03:05:21 2006
+++ SOURCES/madwifi-ng-011-suppress_plaintext.patch	Sat Oct 21 03:05:16 2006
@@ -0,0 +1,22 @@
+#
+# madwifi-0.9.2 suppress_plaintext.diff
+#
+# This patch disables sending packets plaintext when F_PRIVACY is set, but
+# there is no default transmit key. It improves the security, because it
+# suppresses sending any data packets before a secure connection is established
+# via WPA/RSN.
+#
+# Closes Lintrack ticket #103.
+#
+# 2006-09-18, Michal Wrobel <xmxwx at asn.pl>
+#
+--- madwifi/net80211/ieee80211_output.c
++++ madwifi/net80211/ieee80211_output.c
+@@ -820,6 +820,7 @@
+ 				"no default transmit key (%s) deftxkey %u",
+ 				__func__, vap->iv_def_txkey);
+ 			vap->iv_stats.is_tx_nodefkey++;
++			goto bad;
+ 		}
+ 	} else
+ 		key = NULL;		
================================================================


More information about the pld-cvs-commit mailing list