139beb93cSSam Leffler /* 239beb93cSSam Leffler * IEEE 802.11 Common routines 3*4bc52338SCy Schubert * Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> 439beb93cSSam Leffler * 5f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license. 6f05cddf9SRui Paulo * See README for more details. 739beb93cSSam Leffler */ 839beb93cSSam Leffler 939beb93cSSam Leffler #ifndef IEEE802_11_COMMON_H 1039beb93cSSam Leffler #define IEEE802_11_COMMON_H 1139beb93cSSam Leffler 12780fb4a2SCy Schubert #include "defs.h" 13*4bc52338SCy Schubert #include "ieee802_11_defs.h" 14*4bc52338SCy Schubert 15*4bc52338SCy Schubert struct element { 16*4bc52338SCy Schubert u8 id; 17*4bc52338SCy Schubert u8 datalen; 18*4bc52338SCy Schubert u8 data[]; 19*4bc52338SCy Schubert } STRUCT_PACKED; 20780fb4a2SCy Schubert 2185732ac8SCy Schubert struct hostapd_hw_modes; 2285732ac8SCy Schubert 23325151a3SRui Paulo #define MAX_NOF_MB_IES_SUPPORTED 5 24325151a3SRui Paulo 25325151a3SRui Paulo struct mb_ies_info { 26325151a3SRui Paulo struct { 27325151a3SRui Paulo const u8 *ie; 28325151a3SRui Paulo u8 ie_len; 29325151a3SRui Paulo } ies[MAX_NOF_MB_IES_SUPPORTED]; 30325151a3SRui Paulo u8 nof_ies; 31325151a3SRui Paulo }; 32325151a3SRui Paulo 3339beb93cSSam Leffler /* Parsed Information Elements */ 3439beb93cSSam Leffler struct ieee802_11_elems { 35e28a4053SRui Paulo const u8 *ssid; 36e28a4053SRui Paulo const u8 *supp_rates; 37e28a4053SRui Paulo const u8 *ds_params; 38e28a4053SRui Paulo const u8 *challenge; 39e28a4053SRui Paulo const u8 *erp_info; 40e28a4053SRui Paulo const u8 *ext_supp_rates; 41e28a4053SRui Paulo const u8 *wpa_ie; 42e28a4053SRui Paulo const u8 *rsn_ie; 43e28a4053SRui Paulo const u8 *wmm; /* WMM Information or Parameter Element */ 44e28a4053SRui Paulo const u8 *wmm_tspec; 45e28a4053SRui Paulo const u8 *wps_ie; 46e28a4053SRui Paulo const u8 *supp_channels; 47e28a4053SRui Paulo const u8 *mdie; 48e28a4053SRui Paulo const u8 *ftie; 49e28a4053SRui Paulo const u8 *timeout_int; 50e28a4053SRui Paulo const u8 *ht_capabilities; 51e28a4053SRui Paulo const u8 *ht_operation; 525b9c547cSRui Paulo const u8 *mesh_config; 535b9c547cSRui Paulo const u8 *mesh_id; 545b9c547cSRui Paulo const u8 *peer_mgmt; 55f05cddf9SRui Paulo const u8 *vht_capabilities; 56f05cddf9SRui Paulo const u8 *vht_operation; 575b9c547cSRui Paulo const u8 *vht_opmode_notif; 58e28a4053SRui Paulo const u8 *vendor_ht_cap; 595b9c547cSRui Paulo const u8 *vendor_vht; 60f05cddf9SRui Paulo const u8 *p2p; 61f05cddf9SRui Paulo const u8 *wfd; 62f05cddf9SRui Paulo const u8 *link_id; 63f05cddf9SRui Paulo const u8 *interworking; 645b9c547cSRui Paulo const u8 *qos_map_set; 65f05cddf9SRui Paulo const u8 *hs20; 66f05cddf9SRui Paulo const u8 *ext_capab; 67f05cddf9SRui Paulo const u8 *bss_max_idle_period; 68f05cddf9SRui Paulo const u8 *ssid_list; 695b9c547cSRui Paulo const u8 *osen; 70780fb4a2SCy Schubert const u8 *mbo; 715b9c547cSRui Paulo const u8 *ampe; 725b9c547cSRui Paulo const u8 *mic; 73325151a3SRui Paulo const u8 *pref_freq_list; 74780fb4a2SCy Schubert const u8 *supp_op_classes; 75780fb4a2SCy Schubert const u8 *rrm_enabled; 7685732ac8SCy Schubert const u8 *cag_number; 7785732ac8SCy Schubert const u8 *ap_csn; 7885732ac8SCy Schubert const u8 *fils_indic; 7985732ac8SCy Schubert const u8 *dils; 8085732ac8SCy Schubert const u8 *assoc_delay_info; 8185732ac8SCy Schubert const u8 *fils_req_params; 8285732ac8SCy Schubert const u8 *fils_key_confirm; 8385732ac8SCy Schubert const u8 *fils_session; 8485732ac8SCy Schubert const u8 *fils_hlp; 8585732ac8SCy Schubert const u8 *fils_ip_addr_assign; 8685732ac8SCy Schubert const u8 *key_delivery; 8785732ac8SCy Schubert const u8 *fils_wrapped_data; 8885732ac8SCy Schubert const u8 *fils_pk; 8985732ac8SCy Schubert const u8 *fils_nonce; 9085732ac8SCy Schubert const u8 *owe_dh; 9185732ac8SCy Schubert const u8 *power_capab; 9285732ac8SCy Schubert const u8 *roaming_cons_sel; 9385732ac8SCy Schubert const u8 *password_id; 94*4bc52338SCy Schubert const u8 *oci; 95*4bc52338SCy Schubert const u8 *multi_ap; 96*4bc52338SCy Schubert const u8 *he_capabilities; 97e28a4053SRui Paulo 9839beb93cSSam Leffler u8 ssid_len; 9939beb93cSSam Leffler u8 supp_rates_len; 10039beb93cSSam Leffler u8 challenge_len; 10139beb93cSSam Leffler u8 ext_supp_rates_len; 10239beb93cSSam Leffler u8 wpa_ie_len; 10339beb93cSSam Leffler u8 rsn_ie_len; 1043157ba21SRui Paulo u8 wmm_len; /* 7 = WMM Information; 24 = WMM Parameter */ 1053157ba21SRui Paulo u8 wmm_tspec_len; 10639beb93cSSam Leffler u8 wps_ie_len; 10739beb93cSSam Leffler u8 supp_channels_len; 10839beb93cSSam Leffler u8 mdie_len; 10939beb93cSSam Leffler u8 ftie_len; 1105b9c547cSRui Paulo u8 mesh_config_len; 1115b9c547cSRui Paulo u8 mesh_id_len; 1125b9c547cSRui Paulo u8 peer_mgmt_len; 11339beb93cSSam Leffler u8 vendor_ht_cap_len; 1145b9c547cSRui Paulo u8 vendor_vht_len; 115f05cddf9SRui Paulo u8 p2p_len; 116f05cddf9SRui Paulo u8 wfd_len; 117f05cddf9SRui Paulo u8 interworking_len; 1185b9c547cSRui Paulo u8 qos_map_set_len; 119f05cddf9SRui Paulo u8 hs20_len; 120f05cddf9SRui Paulo u8 ext_capab_len; 121f05cddf9SRui Paulo u8 ssid_list_len; 1225b9c547cSRui Paulo u8 osen_len; 123780fb4a2SCy Schubert u8 mbo_len; 1245b9c547cSRui Paulo u8 ampe_len; 1255b9c547cSRui Paulo u8 mic_len; 126325151a3SRui Paulo u8 pref_freq_list_len; 127780fb4a2SCy Schubert u8 supp_op_classes_len; 128780fb4a2SCy Schubert u8 rrm_enabled_len; 12985732ac8SCy Schubert u8 cag_number_len; 13085732ac8SCy Schubert u8 fils_indic_len; 13185732ac8SCy Schubert u8 dils_len; 13285732ac8SCy Schubert u8 fils_req_params_len; 13385732ac8SCy Schubert u8 fils_key_confirm_len; 13485732ac8SCy Schubert u8 fils_hlp_len; 13585732ac8SCy Schubert u8 fils_ip_addr_assign_len; 13685732ac8SCy Schubert u8 key_delivery_len; 13785732ac8SCy Schubert u8 fils_wrapped_data_len; 13885732ac8SCy Schubert u8 fils_pk_len; 13985732ac8SCy Schubert u8 owe_dh_len; 14085732ac8SCy Schubert u8 power_capab_len; 14185732ac8SCy Schubert u8 roaming_cons_sel_len; 14285732ac8SCy Schubert u8 password_id_len; 143*4bc52338SCy Schubert u8 oci_len; 144*4bc52338SCy Schubert u8 multi_ap_len; 145*4bc52338SCy Schubert u8 he_capabilities_len; 146780fb4a2SCy Schubert 147325151a3SRui Paulo struct mb_ies_info mb_ies; 14839beb93cSSam Leffler }; 14939beb93cSSam Leffler 15039beb93cSSam Leffler typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes; 15139beb93cSSam Leffler 152e28a4053SRui Paulo ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, 15339beb93cSSam Leffler struct ieee802_11_elems *elems, 15439beb93cSSam Leffler int show_errors); 155e28a4053SRui Paulo int ieee802_11_ie_count(const u8 *ies, size_t ies_len); 156e28a4053SRui Paulo struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len, 157e28a4053SRui Paulo u32 oui_type); 158f05cddf9SRui Paulo struct ieee80211_hdr; 159f05cddf9SRui Paulo const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len); 160f05cddf9SRui Paulo 161f05cddf9SRui Paulo struct hostapd_wmm_ac_params { 162f05cddf9SRui Paulo int cwmin; 163f05cddf9SRui Paulo int cwmax; 164f05cddf9SRui Paulo int aifs; 165f05cddf9SRui Paulo int txop_limit; /* in units of 32us */ 166f05cddf9SRui Paulo int admission_control_mandatory; 167f05cddf9SRui Paulo }; 168f05cddf9SRui Paulo 169f05cddf9SRui Paulo int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[], 170f05cddf9SRui Paulo const char *name, const char *val); 1715b9c547cSRui Paulo enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel); 1725b9c547cSRui Paulo int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan); 173325151a3SRui Paulo enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq, 174325151a3SRui Paulo int sec_channel, int vht, 175325151a3SRui Paulo u8 *op_class, u8 *channel); 176*4bc52338SCy Schubert int ieee80211_chaninfo_to_channel(unsigned int freq, enum chan_width chanwidth, 177*4bc52338SCy Schubert int sec_channel, u8 *op_class, u8 *channel); 17885732ac8SCy Schubert int ieee80211_is_dfs(int freq, const struct hostapd_hw_modes *modes, 17985732ac8SCy Schubert u16 num_modes); 180780fb4a2SCy Schubert enum phy_type ieee80211_get_phy_type(int freq, int ht, int vht); 18139beb93cSSam Leffler 1825b9c547cSRui Paulo int supp_rates_11b_only(struct ieee802_11_elems *elems); 183325151a3SRui Paulo int mb_ies_info_by_ies(struct mb_ies_info *info, const u8 *ies_buf, 184325151a3SRui Paulo size_t ies_len); 185325151a3SRui Paulo struct wpabuf * mb_ies_by_info(struct mb_ies_info *info); 1865b9c547cSRui Paulo 1875b9c547cSRui Paulo const char * fc2str(u16 fc); 188780fb4a2SCy Schubert 189780fb4a2SCy Schubert struct oper_class_map { 190780fb4a2SCy Schubert enum hostapd_hw_mode mode; 191780fb4a2SCy Schubert u8 op_class; 192780fb4a2SCy Schubert u8 min_chan; 193780fb4a2SCy Schubert u8 max_chan; 194780fb4a2SCy Schubert u8 inc; 195780fb4a2SCy Schubert enum { BW20, BW40PLUS, BW40MINUS, BW80, BW2160, BW160, BW80P80 } bw; 196780fb4a2SCy Schubert enum { P2P_SUPP, NO_P2P_SUPP } p2p; 197780fb4a2SCy Schubert }; 198780fb4a2SCy Schubert 199780fb4a2SCy Schubert extern const struct oper_class_map global_op_class[]; 200780fb4a2SCy Schubert extern size_t global_op_class_size; 201780fb4a2SCy Schubert 202780fb4a2SCy Schubert const u8 * get_ie(const u8 *ies, size_t len, u8 eid); 20385732ac8SCy Schubert const u8 * get_ie_ext(const u8 *ies, size_t len, u8 ext); 204*4bc52338SCy Schubert const u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type); 205780fb4a2SCy Schubert 206780fb4a2SCy Schubert size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len); 207780fb4a2SCy Schubert 208*4bc52338SCy Schubert size_t add_multi_ap_ie(u8 *buf, size_t len, u8 value); 209*4bc52338SCy Schubert 21085732ac8SCy Schubert struct country_op_class { 21185732ac8SCy Schubert u8 country_op_class; 21285732ac8SCy Schubert u8 global_op_class; 21385732ac8SCy Schubert }; 21485732ac8SCy Schubert 21585732ac8SCy Schubert u8 country_to_global_op_class(const char *country, u8 op_class); 21685732ac8SCy Schubert 21785732ac8SCy Schubert const struct oper_class_map * get_oper_class(const char *country, u8 op_class); 218*4bc52338SCy Schubert int oper_class_bw_to_int(const struct oper_class_map *map); 21985732ac8SCy Schubert 22085732ac8SCy Schubert int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep, 22185732ac8SCy Schubert size_t nei_rep_len); 22285732ac8SCy Schubert 223*4bc52338SCy Schubert int ieee802_11_ext_capab(const u8 *ie, unsigned int capab); 224*4bc52338SCy Schubert 225*4bc52338SCy Schubert /* element iteration helpers */ 226*4bc52338SCy Schubert #define for_each_element(_elem, _data, _datalen) \ 227*4bc52338SCy Schubert for (_elem = (const struct element *) (_data); \ 228*4bc52338SCy Schubert (const u8 *) (_data) + (_datalen) - (const u8 *) _elem >= \ 229*4bc52338SCy Schubert (int) sizeof(*_elem) && \ 230*4bc52338SCy Schubert (const u8 *) (_data) + (_datalen) - (const u8 *) _elem >= \ 231*4bc52338SCy Schubert (int) sizeof(*_elem) + _elem->datalen; \ 232*4bc52338SCy Schubert _elem = (const struct element *) (_elem->data + _elem->datalen)) 233*4bc52338SCy Schubert 234*4bc52338SCy Schubert #define for_each_element_id(element, _id, data, datalen) \ 235*4bc52338SCy Schubert for_each_element(element, data, datalen) \ 236*4bc52338SCy Schubert if (element->id == (_id)) 237*4bc52338SCy Schubert 238*4bc52338SCy Schubert #define for_each_element_extid(element, extid, _data, _datalen) \ 239*4bc52338SCy Schubert for_each_element(element, _data, _datalen) \ 240*4bc52338SCy Schubert if (element->id == WLAN_EID_EXTENSION && \ 241*4bc52338SCy Schubert element->datalen > 0 && \ 242*4bc52338SCy Schubert element->data[0] == (extid)) 243*4bc52338SCy Schubert 244*4bc52338SCy Schubert #define for_each_subelement(sub, element) \ 245*4bc52338SCy Schubert for_each_element(sub, (element)->data, (element)->datalen) 246*4bc52338SCy Schubert 247*4bc52338SCy Schubert #define for_each_subelement_id(sub, id, element) \ 248*4bc52338SCy Schubert for_each_element_id(sub, id, (element)->data, (element)->datalen) 249*4bc52338SCy Schubert 250*4bc52338SCy Schubert #define for_each_subelement_extid(sub, extid, element) \ 251*4bc52338SCy Schubert for_each_element_extid(sub, extid, (element)->data, (element)->datalen) 252*4bc52338SCy Schubert 253*4bc52338SCy Schubert /** 254*4bc52338SCy Schubert * for_each_element_completed - Determine if element parsing consumed all data 255*4bc52338SCy Schubert * @element: Element pointer after for_each_element() or friends 256*4bc52338SCy Schubert * @data: Same data pointer as passed to for_each_element() or friends 257*4bc52338SCy Schubert * @datalen: Same data length as passed to for_each_element() or friends 258*4bc52338SCy Schubert * 259*4bc52338SCy Schubert * This function returns 1 if all the data was parsed or considered 260*4bc52338SCy Schubert * while walking the elements. Only use this if your for_each_element() 261*4bc52338SCy Schubert * loop cannot be broken out of, otherwise it always returns 0. 262*4bc52338SCy Schubert * 263*4bc52338SCy Schubert * If some data was malformed, this returns %false since the last parsed 264*4bc52338SCy Schubert * element will not fill the whole remaining data. 265*4bc52338SCy Schubert */ 266*4bc52338SCy Schubert static inline int for_each_element_completed(const struct element *element, 267*4bc52338SCy Schubert const void *data, size_t datalen) 268*4bc52338SCy Schubert { 269*4bc52338SCy Schubert return (const u8 *) element == (const u8 *) data + datalen; 270*4bc52338SCy Schubert } 271*4bc52338SCy Schubert 27239beb93cSSam Leffler #endif /* IEEE802_11_COMMON_H */ 273