1 /* 2 * Common driver-related functions 3 * Copyright (c) 2003-2017, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "includes.h" 10 #include "utils/common.h" 11 #include "driver.h" 12 wpa_scan_results_free(struct wpa_scan_results * res)13 void wpa_scan_results_free(struct wpa_scan_results *res) 14 { 15 size_t i; 16 17 if (res == NULL) 18 return; 19 20 for (i = 0; i < res->num; i++) 21 os_free(res->res[i]); 22 os_free(res->res); 23 os_free(res); 24 } 25 26 event_to_string(enum wpa_event_type event)27 const char * event_to_string(enum wpa_event_type event) 28 { 29 #define E2S(n) case EVENT_ ## n: return #n 30 switch (event) { 31 E2S(ASSOC); 32 E2S(DISASSOC); 33 E2S(MICHAEL_MIC_FAILURE); 34 E2S(SCAN_RESULTS); 35 E2S(ASSOCINFO); 36 E2S(INTERFACE_STATUS); 37 E2S(PMKID_CANDIDATE); 38 E2S(TDLS); 39 E2S(FT_RESPONSE); 40 E2S(IBSS_RSN_START); 41 E2S(AUTH); 42 E2S(DEAUTH); 43 E2S(ASSOC_REJECT); 44 E2S(AUTH_TIMED_OUT); 45 E2S(ASSOC_TIMED_OUT); 46 E2S(WPS_BUTTON_PUSHED); 47 E2S(TX_STATUS); 48 E2S(RX_FROM_UNKNOWN); 49 E2S(RX_MGMT); 50 E2S(REMAIN_ON_CHANNEL); 51 E2S(CANCEL_REMAIN_ON_CHANNEL); 52 E2S(RX_PROBE_REQ); 53 E2S(NEW_STA); 54 E2S(EAPOL_RX); 55 E2S(SIGNAL_CHANGE); 56 E2S(INTERFACE_ENABLED); 57 E2S(INTERFACE_DISABLED); 58 E2S(CHANNEL_LIST_CHANGED); 59 E2S(INTERFACE_UNAVAILABLE); 60 E2S(BEST_CHANNEL); 61 E2S(UNPROT_DEAUTH); 62 E2S(UNPROT_DISASSOC); 63 E2S(STATION_LOW_ACK); 64 E2S(IBSS_PEER_LOST); 65 E2S(DRIVER_GTK_REKEY); 66 E2S(SCHED_SCAN_STOPPED); 67 E2S(DRIVER_CLIENT_POLL_OK); 68 E2S(EAPOL_TX_STATUS); 69 E2S(CH_SWITCH); 70 E2S(CH_SWITCH_STARTED); 71 E2S(WNM); 72 E2S(CONNECT_FAILED_REASON); 73 E2S(DFS_RADAR_DETECTED); 74 E2S(DFS_CAC_FINISHED); 75 E2S(DFS_CAC_ABORTED); 76 E2S(DFS_NOP_FINISHED); 77 E2S(SURVEY); 78 E2S(SCAN_STARTED); 79 E2S(AVOID_FREQUENCIES); 80 E2S(NEW_PEER_CANDIDATE); 81 E2S(ACS_CHANNEL_SELECTED); 82 E2S(DFS_CAC_STARTED); 83 E2S(P2P_LO_STOP); 84 E2S(BEACON_LOSS); 85 E2S(DFS_PRE_CAC_EXPIRED); 86 E2S(EXTERNAL_AUTH); 87 E2S(PORT_AUTHORIZED); 88 E2S(STATION_OPMODE_CHANGED); 89 E2S(INTERFACE_MAC_CHANGED); 90 E2S(WDS_STA_INTERFACE_STATUS); 91 E2S(UPDATE_DH); 92 E2S(UNPROT_BEACON); 93 E2S(TX_WAIT_EXPIRE); 94 E2S(BSS_COLOR_COLLISION); 95 E2S(CCA_STARTED_NOTIFY); 96 E2S(CCA_ABORTED_NOTIFY); 97 E2S(CCA_NOTIFY); 98 E2S(PASN_AUTH); 99 E2S(LINK_CH_SWITCH); 100 E2S(LINK_CH_SWITCH_STARTED); 101 E2S(TID_LINK_MAP); 102 E2S(LINK_RECONFIG); 103 E2S(MLD_INTERFACE_FREED); 104 } 105 106 return "UNKNOWN"; 107 #undef E2S 108 } 109 110 channel_width_to_string(enum chan_width width)111 const char * channel_width_to_string(enum chan_width width) 112 { 113 switch (width) { 114 case CHAN_WIDTH_20_NOHT: 115 return "20 MHz (no HT)"; 116 case CHAN_WIDTH_20: 117 return "20 MHz"; 118 case CHAN_WIDTH_40: 119 return "40 MHz"; 120 case CHAN_WIDTH_80: 121 return "80 MHz"; 122 case CHAN_WIDTH_80P80: 123 return "80+80 MHz"; 124 case CHAN_WIDTH_160: 125 return "160 MHz"; 126 case CHAN_WIDTH_320: 127 return "320 MHz"; 128 default: 129 return "unknown"; 130 } 131 } 132 133 channel_width_to_int(enum chan_width width)134 int channel_width_to_int(enum chan_width width) 135 { 136 switch (width) { 137 case CHAN_WIDTH_20_NOHT: 138 case CHAN_WIDTH_20: 139 return 20; 140 case CHAN_WIDTH_40: 141 return 40; 142 case CHAN_WIDTH_80: 143 return 80; 144 case CHAN_WIDTH_80P80: 145 case CHAN_WIDTH_160: 146 return 160; 147 case CHAN_WIDTH_320: 148 return 320; 149 default: 150 return 0; 151 } 152 } 153 154 ht_supported(const struct hostapd_hw_modes * mode)155 int ht_supported(const struct hostapd_hw_modes *mode) 156 { 157 if (!(mode->flags & HOSTAPD_MODE_FLAG_HT_INFO_KNOWN)) { 158 /* 159 * The driver did not indicate whether it supports HT. Assume 160 * it does to avoid connection issues. 161 */ 162 return 1; 163 } 164 165 /* 166 * IEEE Std 802.11n-2009 20.1.1: 167 * An HT non-AP STA shall support all EQM rates for one spatial stream. 168 */ 169 return mode->mcs_set[0] == 0xff; 170 } 171 172 vht_supported(const struct hostapd_hw_modes * mode)173 int vht_supported(const struct hostapd_hw_modes *mode) 174 { 175 if (!(mode->flags & HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN)) { 176 /* 177 * The driver did not indicate whether it supports VHT. Assume 178 * it does to avoid connection issues. 179 */ 180 return 1; 181 } 182 183 /* 184 * A VHT non-AP STA shall support MCS 0-7 for one spatial stream. 185 * TODO: Verify if this complies with the standard 186 */ 187 return (mode->vht_mcs_set[0] & 0x3) != 3; 188 } 189 190 he_supported(const struct hostapd_hw_modes * hw_mode,enum ieee80211_op_mode op_mode)191 bool he_supported(const struct hostapd_hw_modes *hw_mode, 192 enum ieee80211_op_mode op_mode) 193 { 194 if (!(hw_mode->flags & HOSTAPD_MODE_FLAG_HE_INFO_KNOWN)) { 195 /* 196 * The driver did not indicate whether it supports HE. Assume 197 * it does to avoid connection issues. 198 */ 199 return true; 200 } 201 202 return hw_mode->he_capab[op_mode].he_supported; 203 } 204 205 wpa_check_wowlan_trigger(const char * start,const char * trigger,int capa_trigger,u8 * param_trigger)206 static int wpa_check_wowlan_trigger(const char *start, const char *trigger, 207 int capa_trigger, u8 *param_trigger) 208 { 209 if (os_strcmp(start, trigger) != 0) 210 return 0; 211 if (!capa_trigger) 212 return 0; 213 214 *param_trigger = 1; 215 return 1; 216 } 217 218 219 struct wowlan_triggers * wpa_get_wowlan_triggers(const char * wowlan_triggers,const struct wpa_driver_capa * capa)220 wpa_get_wowlan_triggers(const char *wowlan_triggers, 221 const struct wpa_driver_capa *capa) 222 { 223 struct wowlan_triggers *triggers; 224 char *start, *end, *buf; 225 int last; 226 227 if (!wowlan_triggers) 228 return NULL; 229 230 buf = os_strdup(wowlan_triggers); 231 if (buf == NULL) 232 return NULL; 233 234 triggers = os_zalloc(sizeof(*triggers)); 235 if (triggers == NULL) 236 goto out; 237 238 #define CHECK_TRIGGER(trigger) \ 239 wpa_check_wowlan_trigger(start, #trigger, \ 240 capa->wowlan_triggers.trigger, \ 241 &triggers->trigger) 242 243 start = buf; 244 while (*start != '\0') { 245 while (isblank((unsigned char) *start)) 246 start++; 247 if (*start == '\0') 248 break; 249 end = start; 250 while (!isblank((unsigned char) *end) && *end != '\0') 251 end++; 252 last = *end == '\0'; 253 *end = '\0'; 254 255 if (!CHECK_TRIGGER(any) && 256 !CHECK_TRIGGER(disconnect) && 257 !CHECK_TRIGGER(magic_pkt) && 258 !CHECK_TRIGGER(gtk_rekey_failure) && 259 !CHECK_TRIGGER(eap_identity_req) && 260 !CHECK_TRIGGER(four_way_handshake) && 261 !CHECK_TRIGGER(rfkill_release)) { 262 wpa_printf(MSG_DEBUG, 263 "Unknown/unsupported wowlan trigger '%s'", 264 start); 265 os_free(triggers); 266 triggers = NULL; 267 goto out; 268 } 269 270 if (last) 271 break; 272 start = end + 1; 273 } 274 #undef CHECK_TRIGGER 275 276 out: 277 os_free(buf); 278 return triggers; 279 } 280 281 driver_flag_to_string(u64 flag)282 const char * driver_flag_to_string(u64 flag) 283 { 284 #define DF2S(x) case WPA_DRIVER_FLAGS_ ## x: return #x 285 switch (flag) { 286 DF2S(DRIVER_IE); 287 DF2S(SET_KEYS_AFTER_ASSOC); 288 DF2S(DFS_OFFLOAD); 289 DF2S(4WAY_HANDSHAKE_PSK); 290 DF2S(4WAY_HANDSHAKE_8021X); 291 DF2S(WIRED); 292 DF2S(SME); 293 DF2S(AP); 294 DF2S(SET_KEYS_AFTER_ASSOC_DONE); 295 DF2S(HT_2040_COEX); 296 DF2S(P2P_CONCURRENT); 297 DF2S(P2P_DEDICATED_INTERFACE); 298 DF2S(P2P_CAPABLE); 299 DF2S(AP_TEARDOWN_SUPPORT); 300 DF2S(P2P_MGMT_AND_NON_P2P); 301 DF2S(VALID_ERROR_CODES); 302 DF2S(OFFCHANNEL_TX); 303 DF2S(EAPOL_TX_STATUS); 304 DF2S(DEAUTH_TX_STATUS); 305 DF2S(BSS_SELECTION); 306 DF2S(TDLS_SUPPORT); 307 DF2S(TDLS_EXTERNAL_SETUP); 308 DF2S(PROBE_RESP_OFFLOAD); 309 DF2S(AP_UAPSD); 310 DF2S(INACTIVITY_TIMER); 311 DF2S(AP_MLME); 312 DF2S(SAE); 313 DF2S(OBSS_SCAN); 314 DF2S(IBSS); 315 DF2S(RADAR); 316 DF2S(DEDICATED_P2P_DEVICE); 317 DF2S(QOS_MAPPING); 318 DF2S(AP_CSA); 319 DF2S(MESH); 320 DF2S(ACS_OFFLOAD); 321 DF2S(KEY_MGMT_OFFLOAD); 322 DF2S(TDLS_CHANNEL_SWITCH); 323 DF2S(HT_IBSS); 324 DF2S(VHT_IBSS); 325 DF2S(SUPPORT_HW_MODE_ANY); 326 DF2S(OFFCHANNEL_SIMULTANEOUS); 327 DF2S(FULL_AP_CLIENT_STATE); 328 DF2S(P2P_LISTEN_OFFLOAD); 329 DF2S(SUPPORT_FILS); 330 DF2S(BEACON_RATE_LEGACY); 331 DF2S(BEACON_RATE_HT); 332 DF2S(BEACON_RATE_VHT); 333 DF2S(MGMT_TX_RANDOM_TA); 334 DF2S(MGMT_TX_RANDOM_TA_CONNECTED); 335 DF2S(SCHED_SCAN_RELATIVE_RSSI); 336 DF2S(HE_CAPABILITIES); 337 DF2S(FILS_SK_OFFLOAD); 338 DF2S(OCE_STA); 339 DF2S(OCE_AP); 340 DF2S(OCE_STA_CFON); 341 DF2S(MFP_OPTIONAL); 342 DF2S(SELF_MANAGED_REGULATORY); 343 DF2S(FTM_RESPONDER); 344 DF2S(CONTROL_PORT); 345 DF2S(VLAN_OFFLOAD); 346 DF2S(UPDATE_FT_IES); 347 DF2S(SAFE_PTK0_REKEYS); 348 DF2S(BEACON_PROTECTION); 349 DF2S(EXTENDED_KEY_ID); 350 } 351 return "UNKNOWN"; 352 #undef DF2S 353 } 354 355 driver_flag2_to_string(u64 flag2)356 const char * driver_flag2_to_string(u64 flag2) 357 { 358 #define DF2S(x) case WPA_DRIVER_FLAGS2_ ## x: return #x 359 switch (flag2) { 360 DF2S(CONTROL_PORT_RX); 361 DF2S(CONTROL_PORT_TX_STATUS); 362 DF2S(SEC_LTF_AP); 363 DF2S(SEC_RTT_AP); 364 DF2S(PROT_RANGE_NEG_AP); 365 DF2S(BEACON_RATE_HE); 366 DF2S(BEACON_PROTECTION_CLIENT); 367 DF2S(OCV); 368 DF2S(AP_SME); 369 DF2S(SA_QUERY_OFFLOAD_AP); 370 DF2S(RADAR_BACKGROUND); 371 DF2S(SEC_LTF_STA); 372 DF2S(SEC_RTT_STA); 373 DF2S(PROT_RANGE_NEG_STA); 374 DF2S(MLO); 375 DF2S(SCAN_MIN_PREQ); 376 DF2S(SAE_OFFLOAD_STA); 377 DF2S(SPP_AMSDU); 378 } 379 return "UNKNOWN"; 380 #undef DF2S 381 } 382