1f05cddf9SRui Paulo /* 2f05cddf9SRui Paulo * Common driver-related functions 385732ac8SCy Schubert * Copyright (c) 2003-2017, Jouni Malinen <j@w1.fi> 4f05cddf9SRui Paulo * 5f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license. 6f05cddf9SRui Paulo * See README for more details. 7f05cddf9SRui Paulo */ 8f05cddf9SRui Paulo 9f05cddf9SRui Paulo #include "includes.h" 10f05cddf9SRui Paulo #include "utils/common.h" 11f05cddf9SRui Paulo #include "driver.h" 12f05cddf9SRui Paulo 13f05cddf9SRui Paulo void wpa_scan_results_free(struct wpa_scan_results *res) 14f05cddf9SRui Paulo { 15f05cddf9SRui Paulo size_t i; 16f05cddf9SRui Paulo 17f05cddf9SRui Paulo if (res == NULL) 18f05cddf9SRui Paulo return; 19f05cddf9SRui Paulo 20f05cddf9SRui Paulo for (i = 0; i < res->num; i++) 21f05cddf9SRui Paulo os_free(res->res[i]); 22f05cddf9SRui Paulo os_free(res->res); 23f05cddf9SRui Paulo os_free(res); 24f05cddf9SRui Paulo } 25f05cddf9SRui Paulo 26f05cddf9SRui Paulo 27f05cddf9SRui Paulo const char * event_to_string(enum wpa_event_type event) 28f05cddf9SRui Paulo { 29f05cddf9SRui Paulo #define E2S(n) case EVENT_ ## n: return #n 30f05cddf9SRui Paulo switch (event) { 31f05cddf9SRui Paulo E2S(ASSOC); 32f05cddf9SRui Paulo E2S(DISASSOC); 33f05cddf9SRui Paulo E2S(MICHAEL_MIC_FAILURE); 34f05cddf9SRui Paulo E2S(SCAN_RESULTS); 35f05cddf9SRui Paulo E2S(ASSOCINFO); 36f05cddf9SRui Paulo E2S(INTERFACE_STATUS); 37f05cddf9SRui Paulo E2S(PMKID_CANDIDATE); 38f05cddf9SRui Paulo E2S(TDLS); 39f05cddf9SRui Paulo E2S(FT_RESPONSE); 40f05cddf9SRui Paulo E2S(IBSS_RSN_START); 41f05cddf9SRui Paulo E2S(AUTH); 42f05cddf9SRui Paulo E2S(DEAUTH); 43f05cddf9SRui Paulo E2S(ASSOC_REJECT); 44f05cddf9SRui Paulo E2S(AUTH_TIMED_OUT); 45f05cddf9SRui Paulo E2S(ASSOC_TIMED_OUT); 46f05cddf9SRui Paulo E2S(WPS_BUTTON_PUSHED); 47f05cddf9SRui Paulo E2S(TX_STATUS); 48f05cddf9SRui Paulo E2S(RX_FROM_UNKNOWN); 49f05cddf9SRui Paulo E2S(RX_MGMT); 50f05cddf9SRui Paulo E2S(REMAIN_ON_CHANNEL); 51f05cddf9SRui Paulo E2S(CANCEL_REMAIN_ON_CHANNEL); 52f05cddf9SRui Paulo E2S(RX_PROBE_REQ); 53f05cddf9SRui Paulo E2S(NEW_STA); 54f05cddf9SRui Paulo E2S(EAPOL_RX); 55f05cddf9SRui Paulo E2S(SIGNAL_CHANGE); 56f05cddf9SRui Paulo E2S(INTERFACE_ENABLED); 57f05cddf9SRui Paulo E2S(INTERFACE_DISABLED); 58f05cddf9SRui Paulo E2S(CHANNEL_LIST_CHANGED); 59f05cddf9SRui Paulo E2S(INTERFACE_UNAVAILABLE); 60f05cddf9SRui Paulo E2S(BEST_CHANNEL); 61f05cddf9SRui Paulo E2S(UNPROT_DEAUTH); 62f05cddf9SRui Paulo E2S(UNPROT_DISASSOC); 63f05cddf9SRui Paulo E2S(STATION_LOW_ACK); 64f05cddf9SRui Paulo E2S(IBSS_PEER_LOST); 65f05cddf9SRui Paulo E2S(DRIVER_GTK_REKEY); 66f05cddf9SRui Paulo E2S(SCHED_SCAN_STOPPED); 67f05cddf9SRui Paulo E2S(DRIVER_CLIENT_POLL_OK); 68f05cddf9SRui Paulo E2S(EAPOL_TX_STATUS); 69f05cddf9SRui Paulo E2S(CH_SWITCH); 70*206b73d0SCy Schubert E2S(CH_SWITCH_STARTED); 71f05cddf9SRui Paulo E2S(WNM); 725b9c547cSRui Paulo E2S(CONNECT_FAILED_REASON); 735b9c547cSRui Paulo E2S(DFS_RADAR_DETECTED); 745b9c547cSRui Paulo E2S(DFS_CAC_FINISHED); 755b9c547cSRui Paulo E2S(DFS_CAC_ABORTED); 765b9c547cSRui Paulo E2S(DFS_NOP_FINISHED); 775b9c547cSRui Paulo E2S(SURVEY); 785b9c547cSRui Paulo E2S(SCAN_STARTED); 795b9c547cSRui Paulo E2S(AVOID_FREQUENCIES); 805b9c547cSRui Paulo E2S(NEW_PEER_CANDIDATE); 815b9c547cSRui Paulo E2S(ACS_CHANNEL_SELECTED); 825b9c547cSRui Paulo E2S(DFS_CAC_STARTED); 83780fb4a2SCy Schubert E2S(P2P_LO_STOP); 8485732ac8SCy Schubert E2S(BEACON_LOSS); 8585732ac8SCy Schubert E2S(DFS_PRE_CAC_EXPIRED); 8685732ac8SCy Schubert E2S(EXTERNAL_AUTH); 8785732ac8SCy Schubert E2S(PORT_AUTHORIZED); 8885732ac8SCy Schubert E2S(STATION_OPMODE_CHANGED); 8985732ac8SCy Schubert E2S(INTERFACE_MAC_CHANGED); 9085732ac8SCy Schubert E2S(WDS_STA_INTERFACE_STATUS); 91*206b73d0SCy Schubert E2S(UPDATE_DH); 92f05cddf9SRui Paulo } 93f05cddf9SRui Paulo 94f05cddf9SRui Paulo return "UNKNOWN"; 95f05cddf9SRui Paulo #undef E2S 96f05cddf9SRui Paulo } 975b9c547cSRui Paulo 985b9c547cSRui Paulo 995b9c547cSRui Paulo const char * channel_width_to_string(enum chan_width width) 1005b9c547cSRui Paulo { 1015b9c547cSRui Paulo switch (width) { 1025b9c547cSRui Paulo case CHAN_WIDTH_20_NOHT: 1035b9c547cSRui Paulo return "20 MHz (no HT)"; 1045b9c547cSRui Paulo case CHAN_WIDTH_20: 1055b9c547cSRui Paulo return "20 MHz"; 1065b9c547cSRui Paulo case CHAN_WIDTH_40: 1075b9c547cSRui Paulo return "40 MHz"; 1085b9c547cSRui Paulo case CHAN_WIDTH_80: 1095b9c547cSRui Paulo return "80 MHz"; 1105b9c547cSRui Paulo case CHAN_WIDTH_80P80: 1115b9c547cSRui Paulo return "80+80 MHz"; 1125b9c547cSRui Paulo case CHAN_WIDTH_160: 1135b9c547cSRui Paulo return "160 MHz"; 1145b9c547cSRui Paulo default: 1155b9c547cSRui Paulo return "unknown"; 1165b9c547cSRui Paulo } 1175b9c547cSRui Paulo } 1185b9c547cSRui Paulo 1195b9c547cSRui Paulo 1204bc52338SCy Schubert int channel_width_to_int(enum chan_width width) 1214bc52338SCy Schubert { 1224bc52338SCy Schubert switch (width) { 1234bc52338SCy Schubert case CHAN_WIDTH_20_NOHT: 1244bc52338SCy Schubert case CHAN_WIDTH_20: 1254bc52338SCy Schubert return 20; 1264bc52338SCy Schubert case CHAN_WIDTH_40: 1274bc52338SCy Schubert return 40; 1284bc52338SCy Schubert case CHAN_WIDTH_80: 1294bc52338SCy Schubert return 80; 1304bc52338SCy Schubert case CHAN_WIDTH_80P80: 1314bc52338SCy Schubert case CHAN_WIDTH_160: 1324bc52338SCy Schubert return 160; 1334bc52338SCy Schubert default: 1344bc52338SCy Schubert return 0; 1354bc52338SCy Schubert } 1364bc52338SCy Schubert } 1374bc52338SCy Schubert 1384bc52338SCy Schubert 1395b9c547cSRui Paulo int ht_supported(const struct hostapd_hw_modes *mode) 1405b9c547cSRui Paulo { 1415b9c547cSRui Paulo if (!(mode->flags & HOSTAPD_MODE_FLAG_HT_INFO_KNOWN)) { 1425b9c547cSRui Paulo /* 1435b9c547cSRui Paulo * The driver did not indicate whether it supports HT. Assume 1445b9c547cSRui Paulo * it does to avoid connection issues. 1455b9c547cSRui Paulo */ 1465b9c547cSRui Paulo return 1; 1475b9c547cSRui Paulo } 1485b9c547cSRui Paulo 1495b9c547cSRui Paulo /* 1505b9c547cSRui Paulo * IEEE Std 802.11n-2009 20.1.1: 1515b9c547cSRui Paulo * An HT non-AP STA shall support all EQM rates for one spatial stream. 1525b9c547cSRui Paulo */ 1535b9c547cSRui Paulo return mode->mcs_set[0] == 0xff; 1545b9c547cSRui Paulo } 1555b9c547cSRui Paulo 1565b9c547cSRui Paulo 1575b9c547cSRui Paulo int vht_supported(const struct hostapd_hw_modes *mode) 1585b9c547cSRui Paulo { 1595b9c547cSRui Paulo if (!(mode->flags & HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN)) { 1605b9c547cSRui Paulo /* 1615b9c547cSRui Paulo * The driver did not indicate whether it supports VHT. Assume 1625b9c547cSRui Paulo * it does to avoid connection issues. 1635b9c547cSRui Paulo */ 1645b9c547cSRui Paulo return 1; 1655b9c547cSRui Paulo } 1665b9c547cSRui Paulo 1675b9c547cSRui Paulo /* 1685b9c547cSRui Paulo * A VHT non-AP STA shall support MCS 0-7 for one spatial stream. 1695b9c547cSRui Paulo * TODO: Verify if this complies with the standard 1705b9c547cSRui Paulo */ 1715b9c547cSRui Paulo return (mode->vht_mcs_set[0] & 0x3) != 3; 1725b9c547cSRui Paulo } 1735b9c547cSRui Paulo 1745b9c547cSRui Paulo 1755b9c547cSRui Paulo static int wpa_check_wowlan_trigger(const char *start, const char *trigger, 1765b9c547cSRui Paulo int capa_trigger, u8 *param_trigger) 1775b9c547cSRui Paulo { 1785b9c547cSRui Paulo if (os_strcmp(start, trigger) != 0) 1795b9c547cSRui Paulo return 0; 1805b9c547cSRui Paulo if (!capa_trigger) 1815b9c547cSRui Paulo return 0; 1825b9c547cSRui Paulo 1835b9c547cSRui Paulo *param_trigger = 1; 1845b9c547cSRui Paulo return 1; 1855b9c547cSRui Paulo } 1865b9c547cSRui Paulo 1875b9c547cSRui Paulo 1885b9c547cSRui Paulo struct wowlan_triggers * 1895b9c547cSRui Paulo wpa_get_wowlan_triggers(const char *wowlan_triggers, 1905b9c547cSRui Paulo const struct wpa_driver_capa *capa) 1915b9c547cSRui Paulo { 1925b9c547cSRui Paulo struct wowlan_triggers *triggers; 1935b9c547cSRui Paulo char *start, *end, *buf; 1945b9c547cSRui Paulo int last; 1955b9c547cSRui Paulo 1965b9c547cSRui Paulo if (!wowlan_triggers) 1975b9c547cSRui Paulo return NULL; 1985b9c547cSRui Paulo 1995b9c547cSRui Paulo buf = os_strdup(wowlan_triggers); 2005b9c547cSRui Paulo if (buf == NULL) 2015b9c547cSRui Paulo return NULL; 2025b9c547cSRui Paulo 2035b9c547cSRui Paulo triggers = os_zalloc(sizeof(*triggers)); 2045b9c547cSRui Paulo if (triggers == NULL) 2055b9c547cSRui Paulo goto out; 2065b9c547cSRui Paulo 2075b9c547cSRui Paulo #define CHECK_TRIGGER(trigger) \ 2085b9c547cSRui Paulo wpa_check_wowlan_trigger(start, #trigger, \ 2095b9c547cSRui Paulo capa->wowlan_triggers.trigger, \ 2105b9c547cSRui Paulo &triggers->trigger) 2115b9c547cSRui Paulo 2125b9c547cSRui Paulo start = buf; 2135b9c547cSRui Paulo while (*start != '\0') { 214780fb4a2SCy Schubert while (isblank((unsigned char) *start)) 2155b9c547cSRui Paulo start++; 2165b9c547cSRui Paulo if (*start == '\0') 2175b9c547cSRui Paulo break; 2185b9c547cSRui Paulo end = start; 219780fb4a2SCy Schubert while (!isblank((unsigned char) *end) && *end != '\0') 2205b9c547cSRui Paulo end++; 2215b9c547cSRui Paulo last = *end == '\0'; 2225b9c547cSRui Paulo *end = '\0'; 2235b9c547cSRui Paulo 2245b9c547cSRui Paulo if (!CHECK_TRIGGER(any) && 2255b9c547cSRui Paulo !CHECK_TRIGGER(disconnect) && 2265b9c547cSRui Paulo !CHECK_TRIGGER(magic_pkt) && 2275b9c547cSRui Paulo !CHECK_TRIGGER(gtk_rekey_failure) && 2285b9c547cSRui Paulo !CHECK_TRIGGER(eap_identity_req) && 2295b9c547cSRui Paulo !CHECK_TRIGGER(four_way_handshake) && 2305b9c547cSRui Paulo !CHECK_TRIGGER(rfkill_release)) { 2315b9c547cSRui Paulo wpa_printf(MSG_DEBUG, 2325b9c547cSRui Paulo "Unknown/unsupported wowlan trigger '%s'", 2335b9c547cSRui Paulo start); 2345b9c547cSRui Paulo os_free(triggers); 2355b9c547cSRui Paulo triggers = NULL; 2365b9c547cSRui Paulo goto out; 2375b9c547cSRui Paulo } 2385b9c547cSRui Paulo 2395b9c547cSRui Paulo if (last) 2405b9c547cSRui Paulo break; 2415b9c547cSRui Paulo start = end + 1; 2425b9c547cSRui Paulo } 2435b9c547cSRui Paulo #undef CHECK_TRIGGER 2445b9c547cSRui Paulo 2455b9c547cSRui Paulo out: 2465b9c547cSRui Paulo os_free(buf); 2475b9c547cSRui Paulo return triggers; 2485b9c547cSRui Paulo } 249780fb4a2SCy Schubert 250780fb4a2SCy Schubert 251780fb4a2SCy Schubert const char * driver_flag_to_string(u64 flag) 252780fb4a2SCy Schubert { 253780fb4a2SCy Schubert #define DF2S(x) case WPA_DRIVER_FLAGS_ ## x: return #x 254780fb4a2SCy Schubert switch (flag) { 255780fb4a2SCy Schubert DF2S(DRIVER_IE); 256780fb4a2SCy Schubert DF2S(SET_KEYS_AFTER_ASSOC); 257780fb4a2SCy Schubert DF2S(DFS_OFFLOAD); 2584bc52338SCy Schubert DF2S(4WAY_HANDSHAKE_PSK); 2594bc52338SCy Schubert DF2S(4WAY_HANDSHAKE_8021X); 260780fb4a2SCy Schubert DF2S(WIRED); 261780fb4a2SCy Schubert DF2S(SME); 262780fb4a2SCy Schubert DF2S(AP); 263780fb4a2SCy Schubert DF2S(SET_KEYS_AFTER_ASSOC_DONE); 264780fb4a2SCy Schubert DF2S(HT_2040_COEX); 265780fb4a2SCy Schubert DF2S(P2P_CONCURRENT); 266780fb4a2SCy Schubert DF2S(P2P_DEDICATED_INTERFACE); 267780fb4a2SCy Schubert DF2S(P2P_CAPABLE); 268780fb4a2SCy Schubert DF2S(AP_TEARDOWN_SUPPORT); 269780fb4a2SCy Schubert DF2S(P2P_MGMT_AND_NON_P2P); 270780fb4a2SCy Schubert DF2S(SANE_ERROR_CODES); 271780fb4a2SCy Schubert DF2S(OFFCHANNEL_TX); 272780fb4a2SCy Schubert DF2S(EAPOL_TX_STATUS); 273780fb4a2SCy Schubert DF2S(DEAUTH_TX_STATUS); 274780fb4a2SCy Schubert DF2S(BSS_SELECTION); 275780fb4a2SCy Schubert DF2S(TDLS_SUPPORT); 276780fb4a2SCy Schubert DF2S(TDLS_EXTERNAL_SETUP); 277780fb4a2SCy Schubert DF2S(PROBE_RESP_OFFLOAD); 278780fb4a2SCy Schubert DF2S(AP_UAPSD); 279780fb4a2SCy Schubert DF2S(INACTIVITY_TIMER); 280780fb4a2SCy Schubert DF2S(AP_MLME); 281780fb4a2SCy Schubert DF2S(SAE); 282780fb4a2SCy Schubert DF2S(OBSS_SCAN); 283780fb4a2SCy Schubert DF2S(IBSS); 284780fb4a2SCy Schubert DF2S(RADAR); 285780fb4a2SCy Schubert DF2S(DEDICATED_P2P_DEVICE); 286780fb4a2SCy Schubert DF2S(QOS_MAPPING); 287780fb4a2SCy Schubert DF2S(AP_CSA); 288780fb4a2SCy Schubert DF2S(MESH); 289780fb4a2SCy Schubert DF2S(ACS_OFFLOAD); 290780fb4a2SCy Schubert DF2S(KEY_MGMT_OFFLOAD); 291780fb4a2SCy Schubert DF2S(TDLS_CHANNEL_SWITCH); 292780fb4a2SCy Schubert DF2S(HT_IBSS); 293780fb4a2SCy Schubert DF2S(VHT_IBSS); 294780fb4a2SCy Schubert DF2S(SUPPORT_HW_MODE_ANY); 295780fb4a2SCy Schubert DF2S(OFFCHANNEL_SIMULTANEOUS); 296780fb4a2SCy Schubert DF2S(FULL_AP_CLIENT_STATE); 297780fb4a2SCy Schubert DF2S(P2P_LISTEN_OFFLOAD); 29885732ac8SCy Schubert DF2S(SUPPORT_FILS); 29985732ac8SCy Schubert DF2S(BEACON_RATE_LEGACY); 30085732ac8SCy Schubert DF2S(BEACON_RATE_HT); 30185732ac8SCy Schubert DF2S(BEACON_RATE_VHT); 30285732ac8SCy Schubert DF2S(MGMT_TX_RANDOM_TA); 30385732ac8SCy Schubert DF2S(MGMT_TX_RANDOM_TA_CONNECTED); 30485732ac8SCy Schubert DF2S(SCHED_SCAN_RELATIVE_RSSI); 30585732ac8SCy Schubert DF2S(HE_CAPABILITIES); 30685732ac8SCy Schubert DF2S(FILS_SK_OFFLOAD); 30785732ac8SCy Schubert DF2S(OCE_STA); 30885732ac8SCy Schubert DF2S(OCE_AP); 30985732ac8SCy Schubert DF2S(OCE_STA_CFON); 31085732ac8SCy Schubert DF2S(MFP_OPTIONAL); 311780fb4a2SCy Schubert } 312780fb4a2SCy Schubert return "UNKNOWN"; 313780fb4a2SCy Schubert #undef DF2S 314780fb4a2SCy Schubert } 315