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