1189251Ssam/* 2189251Ssam * IEEE 802.11 Common routines 3346981Scy * Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> 4189251Ssam * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7189251Ssam */ 8189251Ssam 9189251Ssam#ifndef IEEE802_11_COMMON_H 10189251Ssam#define IEEE802_11_COMMON_H 11189251Ssam 12337817Scy#include "defs.h" 13346981Scy#include "ieee802_11_defs.h" 14337817Scy 15346981Scystruct element { 16346981Scy u8 id; 17346981Scy u8 datalen; 18346981Scy u8 data[]; 19346981Scy} STRUCT_PACKED; 20346981Scy 21346981Scystruct hostapd_hw_modes; 22346981Scy 23289549Srpaulo#define MAX_NOF_MB_IES_SUPPORTED 5 24289549Srpaulo 25289549Srpaulostruct mb_ies_info { 26289549Srpaulo struct { 27289549Srpaulo const u8 *ie; 28289549Srpaulo u8 ie_len; 29289549Srpaulo } ies[MAX_NOF_MB_IES_SUPPORTED]; 30289549Srpaulo u8 nof_ies; 31289549Srpaulo}; 32289549Srpaulo 33189251Ssam/* Parsed Information Elements */ 34189251Ssamstruct ieee802_11_elems { 35214734Srpaulo const u8 *ssid; 36214734Srpaulo const u8 *supp_rates; 37214734Srpaulo const u8 *ds_params; 38214734Srpaulo const u8 *challenge; 39214734Srpaulo const u8 *erp_info; 40214734Srpaulo const u8 *ext_supp_rates; 41214734Srpaulo const u8 *wpa_ie; 42214734Srpaulo const u8 *rsn_ie; 43214734Srpaulo const u8 *wmm; /* WMM Information or Parameter Element */ 44214734Srpaulo const u8 *wmm_tspec; 45214734Srpaulo const u8 *wps_ie; 46214734Srpaulo const u8 *supp_channels; 47214734Srpaulo const u8 *mdie; 48214734Srpaulo const u8 *ftie; 49214734Srpaulo const u8 *timeout_int; 50214734Srpaulo const u8 *ht_capabilities; 51214734Srpaulo const u8 *ht_operation; 52281806Srpaulo const u8 *mesh_config; 53281806Srpaulo const u8 *mesh_id; 54281806Srpaulo const u8 *peer_mgmt; 55252726Srpaulo const u8 *vht_capabilities; 56252726Srpaulo const u8 *vht_operation; 57281806Srpaulo const u8 *vht_opmode_notif; 58214734Srpaulo const u8 *vendor_ht_cap; 59281806Srpaulo const u8 *vendor_vht; 60252726Srpaulo const u8 *p2p; 61252726Srpaulo const u8 *wfd; 62252726Srpaulo const u8 *link_id; 63252726Srpaulo const u8 *interworking; 64281806Srpaulo const u8 *qos_map_set; 65252726Srpaulo const u8 *hs20; 66252726Srpaulo const u8 *ext_capab; 67252726Srpaulo const u8 *bss_max_idle_period; 68252726Srpaulo const u8 *ssid_list; 69281806Srpaulo const u8 *osen; 70337817Scy const u8 *mbo; 71281806Srpaulo const u8 *ampe; 72281806Srpaulo const u8 *mic; 73289549Srpaulo const u8 *pref_freq_list; 74337817Scy const u8 *supp_op_classes; 75337817Scy const u8 *rrm_enabled; 76346981Scy const u8 *cag_number; 77346981Scy const u8 *ap_csn; 78346981Scy const u8 *fils_indic; 79346981Scy const u8 *dils; 80346981Scy const u8 *assoc_delay_info; 81346981Scy const u8 *fils_req_params; 82346981Scy const u8 *fils_key_confirm; 83346981Scy const u8 *fils_session; 84346981Scy const u8 *fils_hlp; 85346981Scy const u8 *fils_ip_addr_assign; 86346981Scy const u8 *key_delivery; 87346981Scy const u8 *fils_wrapped_data; 88346981Scy const u8 *fils_pk; 89346981Scy const u8 *fils_nonce; 90346981Scy const u8 *owe_dh; 91346981Scy const u8 *power_capab; 92346981Scy const u8 *roaming_cons_sel; 93346981Scy const u8 *password_id; 94346981Scy const u8 *oci; 95346981Scy const u8 *multi_ap; 96346981Scy const u8 *he_capabilities; 97351611Scy const u8 *he_operation; 98214734Srpaulo 99189251Ssam u8 ssid_len; 100189251Ssam u8 supp_rates_len; 101189251Ssam u8 challenge_len; 102189251Ssam u8 ext_supp_rates_len; 103189251Ssam u8 wpa_ie_len; 104189251Ssam u8 rsn_ie_len; 105209158Srpaulo u8 wmm_len; /* 7 = WMM Information; 24 = WMM Parameter */ 106209158Srpaulo u8 wmm_tspec_len; 107189251Ssam u8 wps_ie_len; 108189251Ssam u8 supp_channels_len; 109189251Ssam u8 mdie_len; 110189251Ssam u8 ftie_len; 111281806Srpaulo u8 mesh_config_len; 112281806Srpaulo u8 mesh_id_len; 113281806Srpaulo u8 peer_mgmt_len; 114189251Ssam u8 vendor_ht_cap_len; 115281806Srpaulo u8 vendor_vht_len; 116252726Srpaulo u8 p2p_len; 117252726Srpaulo u8 wfd_len; 118252726Srpaulo u8 interworking_len; 119281806Srpaulo u8 qos_map_set_len; 120252726Srpaulo u8 hs20_len; 121252726Srpaulo u8 ext_capab_len; 122252726Srpaulo u8 ssid_list_len; 123281806Srpaulo u8 osen_len; 124337817Scy u8 mbo_len; 125281806Srpaulo u8 ampe_len; 126281806Srpaulo u8 mic_len; 127289549Srpaulo u8 pref_freq_list_len; 128337817Scy u8 supp_op_classes_len; 129337817Scy u8 rrm_enabled_len; 130346981Scy u8 cag_number_len; 131346981Scy u8 fils_indic_len; 132346981Scy u8 dils_len; 133346981Scy u8 fils_req_params_len; 134346981Scy u8 fils_key_confirm_len; 135346981Scy u8 fils_hlp_len; 136346981Scy u8 fils_ip_addr_assign_len; 137346981Scy u8 key_delivery_len; 138346981Scy u8 fils_wrapped_data_len; 139346981Scy u8 fils_pk_len; 140346981Scy u8 owe_dh_len; 141346981Scy u8 power_capab_len; 142346981Scy u8 roaming_cons_sel_len; 143346981Scy u8 password_id_len; 144346981Scy u8 oci_len; 145346981Scy u8 multi_ap_len; 146346981Scy u8 he_capabilities_len; 147351611Scy u8 he_operation_len; 148337817Scy 149289549Srpaulo struct mb_ies_info mb_ies; 150189251Ssam}; 151189251Ssam 152189251Ssamtypedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes; 153189251Ssam 154214734SrpauloParseRes ieee802_11_parse_elems(const u8 *start, size_t len, 155189251Ssam struct ieee802_11_elems *elems, 156189251Ssam int show_errors); 157214734Srpauloint ieee802_11_ie_count(const u8 *ies, size_t ies_len); 158214734Srpaulostruct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len, 159214734Srpaulo u32 oui_type); 160252726Srpaulostruct ieee80211_hdr; 161252726Srpauloconst u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len); 162189251Ssam 163252726Srpaulostruct hostapd_wmm_ac_params { 164252726Srpaulo int cwmin; 165252726Srpaulo int cwmax; 166252726Srpaulo int aifs; 167252726Srpaulo int txop_limit; /* in units of 32us */ 168252726Srpaulo int admission_control_mandatory; 169252726Srpaulo}; 170252726Srpaulo 171252726Srpauloint hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[], 172252726Srpaulo const char *name, const char *val); 173281806Srpauloenum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel); 174281806Srpauloint ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan); 175289549Srpauloenum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq, 176289549Srpaulo int sec_channel, int vht, 177289549Srpaulo u8 *op_class, u8 *channel); 178346981Scyint ieee80211_chaninfo_to_channel(unsigned int freq, enum chan_width chanwidth, 179346981Scy int sec_channel, u8 *op_class, u8 *channel); 180346981Scyint ieee80211_is_dfs(int freq, const struct hostapd_hw_modes *modes, 181346981Scy u16 num_modes); 182337817Scyenum phy_type ieee80211_get_phy_type(int freq, int ht, int vht); 183252726Srpaulo 184281806Srpauloint supp_rates_11b_only(struct ieee802_11_elems *elems); 185289549Srpauloint mb_ies_info_by_ies(struct mb_ies_info *info, const u8 *ies_buf, 186289549Srpaulo size_t ies_len); 187289549Srpaulostruct wpabuf * mb_ies_by_info(struct mb_ies_info *info); 188281806Srpaulo 189281806Srpauloconst char * fc2str(u16 fc); 190351611Scyconst char * reason2str(u16 reason); 191351611Scyconst char * status2str(u16 status); 192337817Scy 193337817Scystruct oper_class_map { 194337817Scy enum hostapd_hw_mode mode; 195337817Scy u8 op_class; 196337817Scy u8 min_chan; 197337817Scy u8 max_chan; 198337817Scy u8 inc; 199337817Scy enum { BW20, BW40PLUS, BW40MINUS, BW80, BW2160, BW160, BW80P80 } bw; 200337817Scy enum { P2P_SUPP, NO_P2P_SUPP } p2p; 201337817Scy}; 202337817Scy 203337817Scyextern const struct oper_class_map global_op_class[]; 204337817Scyextern size_t global_op_class_size; 205337817Scy 206337817Scyconst u8 * get_ie(const u8 *ies, size_t len, u8 eid); 207346981Scyconst u8 * get_ie_ext(const u8 *ies, size_t len, u8 ext); 208346981Scyconst u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type); 209337817Scy 210337817Scysize_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len); 211337817Scy 212346981Scysize_t add_multi_ap_ie(u8 *buf, size_t len, u8 value); 213346981Scy 214346981Scystruct country_op_class { 215346981Scy u8 country_op_class; 216346981Scy u8 global_op_class; 217346981Scy}; 218346981Scy 219346981Scyu8 country_to_global_op_class(const char *country, u8 op_class); 220346981Scy 221346981Scyconst struct oper_class_map * get_oper_class(const char *country, u8 op_class); 222346981Scyint oper_class_bw_to_int(const struct oper_class_map *map); 223346981Scy 224346981Scyint ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep, 225346981Scy size_t nei_rep_len); 226346981Scy 227346981Scyint ieee802_11_ext_capab(const u8 *ie, unsigned int capab); 228346981Scy 229346981Scy/* element iteration helpers */ 230346981Scy#define for_each_element(_elem, _data, _datalen) \ 231346981Scy for (_elem = (const struct element *) (_data); \ 232346981Scy (const u8 *) (_data) + (_datalen) - (const u8 *) _elem >= \ 233346981Scy (int) sizeof(*_elem) && \ 234346981Scy (const u8 *) (_data) + (_datalen) - (const u8 *) _elem >= \ 235346981Scy (int) sizeof(*_elem) + _elem->datalen; \ 236346981Scy _elem = (const struct element *) (_elem->data + _elem->datalen)) 237346981Scy 238346981Scy#define for_each_element_id(element, _id, data, datalen) \ 239346981Scy for_each_element(element, data, datalen) \ 240346981Scy if (element->id == (_id)) 241346981Scy 242346981Scy#define for_each_element_extid(element, extid, _data, _datalen) \ 243346981Scy for_each_element(element, _data, _datalen) \ 244346981Scy if (element->id == WLAN_EID_EXTENSION && \ 245346981Scy element->datalen > 0 && \ 246346981Scy element->data[0] == (extid)) 247346981Scy 248346981Scy#define for_each_subelement(sub, element) \ 249346981Scy for_each_element(sub, (element)->data, (element)->datalen) 250346981Scy 251346981Scy#define for_each_subelement_id(sub, id, element) \ 252346981Scy for_each_element_id(sub, id, (element)->data, (element)->datalen) 253346981Scy 254346981Scy#define for_each_subelement_extid(sub, extid, element) \ 255346981Scy for_each_element_extid(sub, extid, (element)->data, (element)->datalen) 256346981Scy 257346981Scy/** 258346981Scy * for_each_element_completed - Determine if element parsing consumed all data 259346981Scy * @element: Element pointer after for_each_element() or friends 260346981Scy * @data: Same data pointer as passed to for_each_element() or friends 261346981Scy * @datalen: Same data length as passed to for_each_element() or friends 262346981Scy * 263346981Scy * This function returns 1 if all the data was parsed or considered 264346981Scy * while walking the elements. Only use this if your for_each_element() 265346981Scy * loop cannot be broken out of, otherwise it always returns 0. 266346981Scy * 267346981Scy * If some data was malformed, this returns %false since the last parsed 268346981Scy * element will not fill the whole remaining data. 269346981Scy */ 270346981Scystatic inline int for_each_element_completed(const struct element *element, 271346981Scy const void *data, size_t datalen) 272346981Scy{ 273346981Scy return (const u8 *) element == (const u8 *) data + datalen; 274346981Scy} 275346981Scy 276189251Ssam#endif /* IEEE802_11_COMMON_H */ 277