Search Linux Wireless

RE: Possible regression regarding multiple WLAN_EID_AP_CHAN_REPORT in beacon frames

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




> -----Original Message-----
> From: Johannes Berg [mailto:johannes@xxxxxxxxxxxxxxxx]
> Sent: Thursday, May 17, 2012 12:50 PM
> To: Drews, Paul
> Cc: Paul Stewart; linville@xxxxxxxxxxxxx
> Subject: RE: Possible regression regarding multiple
> WLAN_EID_AP_CHAN_REPORT in beacon frames
> 
> On Thu, 2012-05-17 at 14:48 +0000, Drews, Paul wrote:
> 
 
> I thought about that for a bit, but couldn't find anything that would
> allow you to list the single values since you can't do |= in an
> initializer.
> 
> > I gather my dynamic-initialization method is not likely to
> > be accepted even if shown to be multiple-CPU-safe?
> 
> Well, I just think it's the wrong trade-off -- the code may be a bit
> more readable but there's a lot more code and a lot more data section
> which doesn't seem worthwhile when the alternative isn't hugely complex
> either.
> 
> johannes

Ok, I have a version of the patch that I'm happy with at this point.
() Builds with no errors or warning and works on 3.4-rc7
() Passes checkpatch.pl
() Does static-initialization of the bitmap in a way that lets the
    author specify the values in any old order.  One incremental
    line of source-code per value.  Pretty easy to maintain the
    list of values.
() Relies on constant-folding to keep the bitmap initialization compact
    without extra footprint in code-section or data-section.  This
    all works with shift operators instead of (shudder) bitfield operators
    I originally thought I would have to use.
() Uses the standard bitops, no need to roll-your-own
() Is 32-bit and 64-bit compatible with one #ifdef in the
    "boiler-plate" section of the code.  I don't see a way around
   this #ifdef

Patch follows:
=======================================================
>From c89677fd19f0731c363748b9147cd872d5fbd568 Mon Sep 17 00:00:00 2001
From: Paul Drews <paul.drews@xxxxxxxxx>
Date: Thu, 17 May 2012 14:07:11 -0700
Subject: [PATCH] mac80211:  Allow a multiplicity of WLAN_EID_AP_CHAN_REPORT

According to IEEE Std 802.11-2012, Section 10.11.18, Table
8-67, and the grammar for dot11APChannelReportTable indicate
that the WLAN_EID_AP_CHAN_REPORT element can appear multiple
times in a frame, but the frame parser was flagging a parse
error in this case.

This patch changes the logic when parsing information
elements in frames so that it checks a bitmap of element ids
that must not be duplicated.  If present in this bitmap the
element must appear at most once, otherwise duplicates are
allowed.  This approach allows for an older kernel version
to work gracefully with newly-defined element ids that it
doesn't know about.

Signed-off-by: Paul Drews <paul.drews@xxxxxxxxx>
---
 net/mac80211/util.c |  139 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 137 insertions(+), 2 deletions(-)

diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 32f7a3b..1c5014b 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -565,6 +565,142 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL(ieee80211_queue_delayed_work);
 
+
+/*
+ * Bitmap of information element IDs that do not allow multiple occurrences in
+ * a beacon frame or probe reponse.  Any EIDS that do not have their respective
+ * bit set are either unknown to the code (e.g., newly define by the 802.11
+ * spec after this list was last updated) or are known but are defined to allow
+ * multiple instances.  This allows the beacon-frame parser to flag
+ * parse-errors for known-prohibited duplicates but be permissive for future
+ * things it may not know about yet.
+ *
+ * A few macros help with static-initialization of the bitmap.
+ */
+
+#define ALL_MASKS(idx) ( \
+	CONDITIONAL_MASK(WLAN_EID_SSID, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_SUPP_RATES, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_FH_PARAMS, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_DS_PARAMS, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_CF_PARAMS, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_TIM, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_IBSS_PARAMS, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_CHALLENGE, idx) | \
+\
+	CONDITIONAL_MASK(WLAN_EID_COUNTRY, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_HP_PARAMS, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_HP_TABLE, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_REQUEST, idx) | \
+\
+	CONDITIONAL_MASK(WLAN_EID_QBSS_LOAD, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_EDCA_PARAM_SET, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_TSPEC, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_TCLAS, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_SCHEDULE, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_TS_DELAY, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_TCLAS_PROCESSING, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_QOS_CAPA, idx) | \
+	/* 802.11z */ \
+	CONDITIONAL_MASK(WLAN_EID_LINK_ID, idx) | \
+	/* 802.11s */ \
+	CONDITIONAL_MASK(WLAN_EID_MESH_CONFIG, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_MESH_ID, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_LINK_METRIC_REPORT, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_CONGESTION_NOTIFICATION, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_PEER_MGMT, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_CHAN_SWITCH_PARAM, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_MESH_AWAKE_WINDOW, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_BEACON_TIMING, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_MCCAOP_SETUP_REQ, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_MCCAOP_SETUP_RESP, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_MCCAOP_ADVERT, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_MCCAOP_TEARDOWN, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_GANN, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_RANN, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_PREQ, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_PREP, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_PERR, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_PXU, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_PXUC, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_AUTH_MESH_PEER_EXCH, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_MIC, idx) | \
+\
+	CONDITIONAL_MASK(WLAN_EID_PWR_CONSTRAINT, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_PWR_CAPABILITY, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_TPC_REQUEST, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_TPC_REPORT, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_SUPPORTED_CHANNELS, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_CHANNEL_SWITCH, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_MEASURE_REQUEST, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_MEASURE_REPORT, idx) | \
+	/* allow multiple WLAN_EID_QUIET */ \
+	CONDITIONAL_MASK(WLAN_EID_IBSS_DFS, idx) | \
+\
+	CONDITIONAL_MASK(WLAN_EID_ERP_INFO, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_EXT_SUPP_RATES, idx) | \
+\
+	CONDITIONAL_MASK(WLAN_EID_HT_CAPABILITY, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_HT_INFORMATION, idx) | \
+\
+	CONDITIONAL_MASK(WLAN_EID_RSN, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_MMIE, idx) | \
+	/* duplicate of WLAN_EID_VENDOR_SPECIFIC WLAN_EID_WPA */ \
+	/* duplicate of WLAN_EID_VENDOR_SPECIFIC WLAN_EID_GENERIC */ \
+	/* allow multiple WLAN_EID_VENDOR_SPECIFIC */ \
+	CONDITIONAL_MASK(WLAN_EID_QOS_PARAMETER, idx) | \
+\
+	/* allow multiple WLAN_EID_AP_CHAN_REPORT */ \
+	CONDITIONAL_MASK(WLAN_EID_NEIGHBOR_REPORT, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_RCPI, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_BSS_AVG_ACCESS_DELAY, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_ANTENNA_INFO, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_RSNI, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_MEASUREMENT_PILOT_TX_INFO, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_BSS_AVAILABLE_CAPACITY, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_BSS_AC_ACCESS_DELAY, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_RRM_ENABLED_CAPABILITIES, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_MULTIPLE_BSSID, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_BSS_COEX_2040, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_OVERLAP_BSS_SCAN_PARAM, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_EXT_CAPABILITY, idx) | \
+\
+	CONDITIONAL_MASK(WLAN_EID_MOBILITY_DOMAIN, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_FAST_BSS_TRANSITION, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_TIMEOUT_INTERVAL, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_RIC_DATA, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_RIC_DESCRIPTOR, idx) | \
+\
+	CONDITIONAL_MASK(WLAN_EID_DSE_REGISTERED_LOCATION, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_SUPPORTED_REGULATORY_CLASSES, idx) | \
+	CONDITIONAL_MASK(WLAN_EID_EXT_CHANSWITCH_ANN, idx) | \
+	0)
+
+#define CONDITIONAL_MASK(ordinal, idx) \
+	((BIT_WORD(ordinal) == idx) ?  BIT_MASK(ordinal) : 0)
+
+#if BITS_PER_LONG == 32
+static DECLARE_BITMAP(singleton_map, 256) = {
+	[0] = ALL_MASKS(0),
+	[1] = ALL_MASKS(1),
+	[2] = ALL_MASKS(2),
+	[3] = ALL_MASKS(3),
+	[4] = ALL_MASKS(4),
+	[5] = ALL_MASKS(5),
+	[6] = ALL_MASKS(6),
+	[7] = ALL_MASKS(7),
+};
+#elif BITS_PER_LONG == 64
+static DECLARE_BITMAP(singleton_map, 256) = {
+	[0] = ALL_MASKS(0),
+	[1] = ALL_MASKS(1),
+	[2] = ALL_MASKS(2),
+	[3] = ALL_MASKS(3),
+};
+#else
+#error "adjust your <asm/bitsperlong.h> defines"
+#endif
+
 u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
 			       struct ieee802_11_elems *elems,
 			       u64 filter, u32 crc)
@@ -592,8 +728,7 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
 			break;
 		}
 
-		if (id != WLAN_EID_VENDOR_SPECIFIC &&
-		    id != WLAN_EID_QUIET &&
+		if (test_bit(id, singleton_map) &&
 		    test_bit(id, seen_elems)) {
 			elems->parse_error = true;
 			left -= elen;
-- 
1.7.3.4
=======================================================
��.n��������+%������w��{.n�����{���zW����ܨ}���Ơz�j:+v�����w����ޙ��&�)ߡ�a����z�ޗ���ݢj��w�f



[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux