Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 291230
b: refs/heads/master
c: fcff4f1
h: refs/heads/master
v: v3
  • Loading branch information
Paul Stewart authored and John W. Linville committed Mar 7, 2012
1 parent db9203d commit 4abf006
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 23 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: eb9bc6e9a0ac668d2283b8fea1534f8ba31d1692
refs/heads/master: fcff4f108dce0692410f390a05565f4b1b84577f
41 changes: 41 additions & 0 deletions trunk/net/mac80211/ieee80211_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,44 @@ struct ieee80211_bss {
*/
bool has_erp_value;
u8 erp_value;

/* Keep track of the corruption of the last beacon/probe response. */
u8 corrupt_data;

/* Keep track of what bits of information we have valid info for. */
u8 valid_data;
};

/**
* enum ieee80211_corrupt_data_flags - BSS data corruption flags
* @IEEE80211_BSS_CORRUPT_BEACON: last beacon frame received was corrupted
* @IEEE80211_BSS_CORRUPT_PROBE_RESP: last probe response received was corrupted
*
* These are bss flags that are attached to a bss in the
* @corrupt_data field of &struct ieee80211_bss.
*/
enum ieee80211_bss_corrupt_data_flags {
IEEE80211_BSS_CORRUPT_BEACON = BIT(0),
IEEE80211_BSS_CORRUPT_PROBE_RESP = BIT(1)
};

/**
* enum ieee80211_valid_data_flags - BSS valid data flags
* @IEEE80211_BSS_VALID_DTIM: DTIM data was gathered from non-corrupt IE
* @IEEE80211_BSS_VALID_WMM: WMM/UAPSD data was gathered from non-corrupt IE
* @IEEE80211_BSS_VALID_RATES: Supported rates were gathered from non-corrupt IE
* @IEEE80211_BSS_VALID_ERP: ERP flag was gathered from non-corrupt IE
*
* These are bss flags that are attached to a bss in the
* @valid_data field of &struct ieee80211_bss. They show which parts
* of the data structure were recieved as a result of an un-corrupted
* beacon/probe response.
*/
enum ieee80211_bss_valid_data_flags {
IEEE80211_BSS_VALID_DTIM = BIT(0),
IEEE80211_BSS_VALID_WMM = BIT(1),
IEEE80211_BSS_VALID_RATES = BIT(2),
IEEE80211_BSS_VALID_ERP = BIT(3)
};

static inline u8 *bss_mesh_cfg(struct ieee80211_bss *bss)
Expand Down Expand Up @@ -1120,6 +1158,9 @@ struct ieee802_11_elems {
u8 quiet_elem_len;
u8 num_of_quiet_elem; /* can be more the one */
u8 timeout_int_len;

/* whether a parse error occurred while retrieving these elements */
bool parse_error;
};

static inline struct ieee80211_local *hw_to_local(
Expand Down
14 changes: 14 additions & 0 deletions trunk/net/mac80211/mlme.c
Original file line number Diff line number Diff line change
Expand Up @@ -3446,6 +3446,20 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
}
run_again(ifmgd, assoc_data->timeout);

if (bss->corrupt_data) {
char *corrupt_type = "data";
if (bss->corrupt_data & IEEE80211_BSS_CORRUPT_BEACON) {
if (bss->corrupt_data &
IEEE80211_BSS_CORRUPT_PROBE_RESP)
corrupt_type = "beacon and probe response";
else
corrupt_type = "beacon";
} else if (bss->corrupt_data & IEEE80211_BSS_CORRUPT_PROBE_RESP)
corrupt_type = "probe response";
printk(KERN_DEBUG "%s: associating with AP with corrupt %s\n",
sdata->name, corrupt_type);
}

err = 0;
goto out;
err_clear:
Expand Down
71 changes: 51 additions & 20 deletions trunk/net/mac80211/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,43 +104,74 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
cbss->free_priv = ieee80211_rx_bss_free;
bss = (void *)cbss->priv;

if (elems->parse_error) {
if (beacon)
bss->corrupt_data |= IEEE80211_BSS_CORRUPT_BEACON;
else
bss->corrupt_data |= IEEE80211_BSS_CORRUPT_PROBE_RESP;
} else {
if (beacon)
bss->corrupt_data &= ~IEEE80211_BSS_CORRUPT_BEACON;
else
bss->corrupt_data &= ~IEEE80211_BSS_CORRUPT_PROBE_RESP;
}

/* save the ERP value so that it is available at association time */
if (elems->erp_info && elems->erp_info_len >= 1) {
if (elems->erp_info && elems->erp_info_len >= 1 &&
(!elems->parse_error ||
!(bss->valid_data & IEEE80211_BSS_VALID_ERP))) {
bss->erp_value = elems->erp_info[0];
bss->has_erp_value = true;
if (!elems->parse_error)
bss->valid_data |= IEEE80211_BSS_VALID_ERP;
}

if (elems->tim) {
if (elems->tim && (!elems->parse_error ||
!(bss->valid_data & IEEE80211_BSS_VALID_DTIM))) {
struct ieee80211_tim_ie *tim_ie =
(struct ieee80211_tim_ie *)elems->tim;
bss->dtim_period = tim_ie->dtim_period;
if (!elems->parse_error)
bss->valid_data |= IEEE80211_BSS_VALID_DTIM;
}

/* If the beacon had no TIM IE, or it was invalid, use 1 */
if (beacon && !bss->dtim_period)
bss->dtim_period = 1;

/* replace old supported rates if we get new values */
srlen = 0;
if (elems->supp_rates) {
clen = IEEE80211_MAX_SUPP_RATES;
if (clen > elems->supp_rates_len)
clen = elems->supp_rates_len;
memcpy(bss->supp_rates, elems->supp_rates, clen);
srlen += clen;
}
if (elems->ext_supp_rates) {
clen = IEEE80211_MAX_SUPP_RATES - srlen;
if (clen > elems->ext_supp_rates_len)
clen = elems->ext_supp_rates_len;
memcpy(bss->supp_rates + srlen, elems->ext_supp_rates, clen);
srlen += clen;
if (!elems->parse_error ||
!(bss->valid_data & IEEE80211_BSS_VALID_RATES)) {
srlen = 0;
if (elems->supp_rates) {
clen = IEEE80211_MAX_SUPP_RATES;
if (clen > elems->supp_rates_len)
clen = elems->supp_rates_len;
memcpy(bss->supp_rates, elems->supp_rates, clen);
srlen += clen;
}
if (elems->ext_supp_rates) {
clen = IEEE80211_MAX_SUPP_RATES - srlen;
if (clen > elems->ext_supp_rates_len)
clen = elems->ext_supp_rates_len;
memcpy(bss->supp_rates + srlen, elems->ext_supp_rates,
clen);
srlen += clen;
}
if (srlen) {
bss->supp_rates_len = srlen;
if (!elems->parse_error)
bss->valid_data |= IEEE80211_BSS_VALID_RATES;
}
}
if (srlen)
bss->supp_rates_len = srlen;

bss->wmm_used = elems->wmm_param || elems->wmm_info;
bss->uapsd_supported = is_uapsd_supported(elems);
if (!elems->parse_error ||
!(bss->valid_data & IEEE80211_BSS_VALID_WMM)) {
bss->wmm_used = elems->wmm_param || elems->wmm_info;
bss->uapsd_supported = is_uapsd_supported(elems);
if (!elems->parse_error)
bss->valid_data |= IEEE80211_BSS_VALID_WMM;
}

if (!beacon)
bss->last_probe_resp = jiffies;
Expand Down
37 changes: 35 additions & 2 deletions trunk/net/mac80211/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -572,24 +572,40 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
size_t left = len;
u8 *pos = start;
bool calc_crc = filter != 0;
DECLARE_BITMAP(seen_elems, 256);

bitmap_zero(seen_elems, 256);
memset(elems, 0, sizeof(*elems));
elems->ie_start = start;
elems->total_len = len;

while (left >= 2) {
u8 id, elen;
bool elem_parse_failed;

id = *pos++;
elen = *pos++;
left -= 2;

if (elen > left)
if (elen > left) {
elems->parse_error = true;
break;
}

if (id != WLAN_EID_VENDOR_SPECIFIC &&
id != WLAN_EID_QUIET &&
test_bit(id, seen_elems)) {
elems->parse_error = true;
left -= elen;
pos += elen;
continue;
}

if (calc_crc && id < 64 && (filter & (1ULL << id)))
crc = crc32_be(crc, pos - 2, elen + 2);

elem_parse_failed = false;

switch (id) {
case WLAN_EID_SSID:
elems->ssid = pos;
Expand All @@ -615,7 +631,8 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
if (elen >= sizeof(struct ieee80211_tim_ie)) {
elems->tim = (void *)pos;
elems->tim_len = elen;
}
} else
elem_parse_failed = true;
break;
case WLAN_EID_IBSS_PARAMS:
elems->ibss_params = pos;
Expand Down Expand Up @@ -664,10 +681,14 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
case WLAN_EID_HT_CAPABILITY:
if (elen >= sizeof(struct ieee80211_ht_cap))
elems->ht_cap_elem = (void *)pos;
else
elem_parse_failed = true;
break;
case WLAN_EID_HT_INFORMATION:
if (elen >= sizeof(struct ieee80211_ht_info))
elems->ht_info_elem = (void *)pos;
else
elem_parse_failed = true;
break;
case WLAN_EID_MESH_ID:
elems->mesh_id = pos;
Expand All @@ -676,6 +697,8 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
case WLAN_EID_MESH_CONFIG:
if (elen >= sizeof(struct ieee80211_meshconf_ie))
elems->mesh_config = (void *)pos;
else
elem_parse_failed = true;
break;
case WLAN_EID_PEER_MGMT:
elems->peering = pos;
Expand All @@ -696,6 +719,8 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
case WLAN_EID_RANN:
if (elen >= sizeof(struct ieee80211_rann_ie))
elems->rann = (void *)pos;
else
elem_parse_failed = true;
break;
case WLAN_EID_CHANNEL_SWITCH:
elems->ch_switch_elem = pos;
Expand Down Expand Up @@ -724,10 +749,18 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
break;
}

if (elem_parse_failed)
elems->parse_error = true;
else
set_bit(id, seen_elems);

left -= elen;
pos += elen;
}

if (left != 0)
elems->parse_error = true;

return crc;
}

Expand Down

0 comments on commit 4abf006

Please sign in to comment.