diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-08-22 14:59:50 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-09-21 10:29:41 +0200 |
commit | 3489e3b6396ee9944a6a2e19e675ca54c36993b4 (patch) | |
tree | cd55cfac1c96ff4b888a9606fd6a0d8eb65bb446 /freebsd/contrib/wpa/src/common/ieee802_11_common.c | |
parent | ck: Define CK_MD_PPC32_LWSYNC if available (diff) | |
download | rtems-libbsd-3489e3b6396ee9944a6a2e19e675ca54c36993b4.tar.bz2 |
Update to FreeBSD head 2018-09-17
Git mirror commit 6c2192b1ef8c50788c751f878552526800b1e319.
Update #3472.
Diffstat (limited to 'freebsd/contrib/wpa/src/common/ieee802_11_common.c')
-rw-r--r-- | freebsd/contrib/wpa/src/common/ieee802_11_common.c | 212 |
1 files changed, 192 insertions, 20 deletions
diff --git a/freebsd/contrib/wpa/src/common/ieee802_11_common.c b/freebsd/contrib/wpa/src/common/ieee802_11_common.c index ba7ef0a8..286fdcf8 100644 --- a/freebsd/contrib/wpa/src/common/ieee802_11_common.c +++ b/freebsd/contrib/wpa/src/common/ieee802_11_common.c @@ -117,6 +117,11 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, elems->osen = pos; elems->osen_len = elen; break; + case MBO_OUI_TYPE: + /* MBO-OCE */ + elems->mbo = pos; + elems->mbo_len = elen; + break; default: wpa_printf(MSG_MSGDUMP, "Unknown WFA " "information element ignored " @@ -368,6 +373,14 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, elems->mb_ies.ies[elems->mb_ies.nof_ies].ie_len = elen; elems->mb_ies.nof_ies++; break; + case WLAN_EID_SUPPORTED_OPERATING_CLASSES: + elems->supp_op_classes = pos; + elems->supp_op_classes_len = elen; + break; + case WLAN_EID_RRM_ENABLED_CAPABILITIES: + elems->rrm_enabled = pos; + elems->rrm_enabled_len = elen; + break; default: unknown++; if (!show_errors) @@ -400,8 +413,8 @@ int ieee802_11_ie_count(const u8 *ies, size_t ies_len) pos = ies; end = ies + ies_len; - while (pos + 2 <= end) { - if (pos + 2 + pos[1] > end) + while (end - pos >= 2) { + if (2 + pos[1] > end - pos) break; count++; pos += 2 + pos[1]; @@ -421,8 +434,8 @@ struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len, end = ies + ies_len; ie = NULL; - while (pos + 1 < end) { - if (pos + 2 + pos[1] > end) + while (end - pos > 1) { + if (2 + pos[1] > end - pos) return NULL; if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && WPA_GET_BE32(&pos[2]) == oui_type) { @@ -443,8 +456,8 @@ struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len, * There may be multiple vendor IEs in the message, so need to * concatenate their data fields. */ - while (pos + 1 < end) { - if (pos + 2 + pos[1] > end) + while (end - pos > 1) { + if (2 + pos[1] > end - pos) break; if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && WPA_GET_BE32(&pos[2]) == oui_type) @@ -572,7 +585,8 @@ enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel) { u8 op_class; - return ieee80211_freq_to_channel_ext(freq, 0, 0, &op_class, channel); + return ieee80211_freq_to_channel_ext(freq, 0, VHT_CHANWIDTH_USE_HT, + &op_class, channel); } @@ -581,7 +595,7 @@ enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel) * for HT40 and VHT. DFS channels are not covered. * @freq: Frequency (MHz) to convert * @sec_channel: 0 = non-HT40, 1 = sec. channel above, -1 = sec. channel below - * @vht: 0 - non-VHT, 1 - 80 MHz + * @vht: VHT channel width (VHT_CHANWIDTH_*) * @op_class: Buffer for returning operating class * @channel: Buffer for returning channel number * Returns: hw_mode on success, NUM_HOSTAPD_MODES on failure @@ -590,6 +604,8 @@ enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq, int sec_channel, int vht, u8 *op_class, u8 *channel) { + u8 vht_opclass; + /* TODO: more operating classes */ if (sec_channel > 1 || sec_channel < -1) @@ -633,17 +649,32 @@ enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq, return HOSTAPD_MODE_IEEE80211A; } + switch (vht) { + case VHT_CHANWIDTH_80MHZ: + vht_opclass = 128; + break; + case VHT_CHANWIDTH_160MHZ: + vht_opclass = 129; + break; + case VHT_CHANWIDTH_80P80MHZ: + vht_opclass = 130; + break; + default: + vht_opclass = 0; + break; + } + /* 5 GHz, channels 36..48 */ if (freq >= 5180 && freq <= 5240) { if ((freq - 5000) % 5) return NUM_HOSTAPD_MODES; - if (sec_channel == 1) + if (vht_opclass) + *op_class = vht_opclass; + else if (sec_channel == 1) *op_class = 116; else if (sec_channel == -1) *op_class = 117; - else if (vht) - *op_class = 128; else *op_class = 115; @@ -652,31 +683,40 @@ enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq, return HOSTAPD_MODE_IEEE80211A; } - /* 5 GHz, channels 149..161 */ - if (freq >= 5745 && freq <= 5805) { + /* 5 GHz, channels 149..169 */ + if (freq >= 5745 && freq <= 5845) { if ((freq - 5000) % 5) return NUM_HOSTAPD_MODES; - if (sec_channel == 1) + if (vht_opclass) + *op_class = vht_opclass; + else if (sec_channel == 1) *op_class = 126; else if (sec_channel == -1) *op_class = 127; - else if (vht) - *op_class = 128; - else + else if (freq <= 5805) *op_class = 124; + else + *op_class = 125; *channel = (freq - 5000) / 5; return HOSTAPD_MODE_IEEE80211A; } - /* 5 GHz, channels 149..169 */ - if (freq >= 5745 && freq <= 5845) { + /* 5 GHz, channels 100..140 */ + if (freq >= 5000 && freq <= 5700) { if ((freq - 5000) % 5) return NUM_HOSTAPD_MODES; - *op_class = 125; + if (vht_opclass) + *op_class = vht_opclass; + else if (sec_channel == 1) + *op_class = 122; + else if (sec_channel == -1) + *op_class = 123; + else + *op_class = 121; *channel = (freq - 5000) / 5; @@ -1147,3 +1187,135 @@ struct wpabuf * mb_ies_by_info(struct mb_ies_info *info) return mb_ies; } + + +const struct oper_class_map global_op_class[] = { + { HOSTAPD_MODE_IEEE80211G, 81, 1, 13, 1, BW20, P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211G, 82, 14, 14, 1, BW20, NO_P2P_SUPP }, + + /* Do not enable HT40 on 2.4 GHz for P2P use for now */ + { HOSTAPD_MODE_IEEE80211G, 83, 1, 9, 1, BW40PLUS, NO_P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211G, 84, 5, 13, 1, BW40MINUS, NO_P2P_SUPP }, + + { HOSTAPD_MODE_IEEE80211A, 115, 36, 48, 4, BW20, P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 116, 36, 44, 8, BW40PLUS, P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 117, 40, 48, 8, BW40MINUS, P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 118, 52, 64, 4, BW20, NO_P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 119, 52, 60, 8, BW40PLUS, NO_P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 120, 56, 64, 8, BW40MINUS, NO_P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 121, 100, 140, 4, BW20, NO_P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 122, 100, 132, 8, BW40PLUS, NO_P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 123, 104, 136, 8, BW40MINUS, NO_P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 124, 149, 161, 4, BW20, P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 125, 149, 169, 4, BW20, P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 126, 149, 157, 8, BW40PLUS, P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 127, 153, 161, 8, BW40MINUS, P2P_SUPP }, + + /* + * IEEE P802.11ac/D7.0 Table E-4 actually talks about channel center + * frequency index 42, 58, 106, 122, 138, 155 with channel spacing of + * 80 MHz, but currently use the following definition for simplicity + * (these center frequencies are not actual channels, which makes + * wpas_p2p_allow_channel() fail). wpas_p2p_verify_80mhz() should take + * care of removing invalid channels. + */ + { HOSTAPD_MODE_IEEE80211A, 128, 36, 161, 4, BW80, P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 129, 50, 114, 16, BW160, P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 130, 36, 161, 4, BW80P80, P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211AD, 180, 1, 4, 1, BW2160, P2P_SUPP }, + { -1, 0, 0, 0, 0, BW20, NO_P2P_SUPP } +}; + + +static enum phy_type ieee80211_phy_type_by_freq(int freq) +{ + enum hostapd_hw_mode hw_mode; + u8 channel; + + hw_mode = ieee80211_freq_to_chan(freq, &channel); + + switch (hw_mode) { + case HOSTAPD_MODE_IEEE80211A: + return PHY_TYPE_OFDM; + case HOSTAPD_MODE_IEEE80211B: + return PHY_TYPE_HRDSSS; + case HOSTAPD_MODE_IEEE80211G: + return PHY_TYPE_ERP; + case HOSTAPD_MODE_IEEE80211AD: + return PHY_TYPE_DMG; + default: + return PHY_TYPE_UNSPECIFIED; + }; +} + + +/* ieee80211_get_phy_type - Derive the phy type by freq and bandwidth */ +enum phy_type ieee80211_get_phy_type(int freq, int ht, int vht) +{ + if (vht) + return PHY_TYPE_VHT; + if (ht) + return PHY_TYPE_HT; + + return ieee80211_phy_type_by_freq(freq); +} + + +size_t global_op_class_size = ARRAY_SIZE(global_op_class); + + +/** + * get_ie - Fetch a specified information element from IEs buffer + * @ies: Information elements buffer + * @len: Information elements buffer length + * @eid: Information element identifier (WLAN_EID_*) + * Returns: Pointer to the information element (id field) or %NULL if not found + * + * This function returns the first matching information element in the IEs + * buffer or %NULL in case the element is not found. + */ +const u8 * get_ie(const u8 *ies, size_t len, u8 eid) +{ + const u8 *end; + + if (!ies) + return NULL; + + end = ies + len; + + while (end - ies > 1) { + if (2 + ies[1] > end - ies) + break; + + if (ies[0] == eid) + return ies; + + ies += 2 + ies[1]; + } + + return NULL; +} + + +size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len) +{ + /* + * MBO IE requires 6 bytes without the attributes: EID (1), length (1), + * OUI (3), OUI type (1). + */ + if (len < 6 + attr_len) { + wpa_printf(MSG_DEBUG, + "MBO: Not enough room in buffer for MBO IE: buf len = %zu, attr_len = %zu", + len, attr_len); + return 0; + } + + *buf++ = WLAN_EID_VENDOR_SPECIFIC; + *buf++ = attr_len + 4; + WPA_PUT_BE24(buf, OUI_WFA); + buf += 3; + *buf++ = MBO_OUI_TYPE; + os_memcpy(buf, attr, attr_len); + + return 6 + attr_len; +} |