1f05cddf9SRui Paulo /* 2f05cddf9SRui Paulo * Common driver-related functions 3*85732ac8SCy 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); 70f05cddf9SRui Paulo E2S(WNM); 715b9c547cSRui Paulo E2S(CONNECT_FAILED_REASON); 725b9c547cSRui Paulo E2S(DFS_RADAR_DETECTED); 735b9c547cSRui Paulo E2S(DFS_CAC_FINISHED); 745b9c547cSRui Paulo E2S(DFS_CAC_ABORTED); 755b9c547cSRui Paulo E2S(DFS_NOP_FINISHED); 765b9c547cSRui Paulo E2S(SURVEY); 775b9c547cSRui Paulo E2S(SCAN_STARTED); 785b9c547cSRui Paulo E2S(AVOID_FREQUENCIES); 795b9c547cSRui Paulo E2S(NEW_PEER_CANDIDATE); 805b9c547cSRui Paulo E2S(ACS_CHANNEL_SELECTED); 815b9c547cSRui Paulo E2S(DFS_CAC_STARTED); 82780fb4a2SCy Schubert E2S(P2P_LO_STOP); 83*85732ac8SCy Schubert E2S(BEACON_LOSS); 84*85732ac8SCy Schubert E2S(DFS_PRE_CAC_EXPIRED); 85*85732ac8SCy Schubert E2S(EXTERNAL_AUTH); 86*85732ac8SCy Schubert E2S(PORT_AUTHORIZED); 87*85732ac8SCy Schubert E2S(STATION_OPMODE_CHANGED); 88*85732ac8SCy Schubert E2S(INTERFACE_MAC_CHANGED); 89*85732ac8SCy Schubert E2S(WDS_STA_INTERFACE_STATUS); 90f05cddf9SRui Paulo } 91f05cddf9SRui Paulo 92f05cddf9SRui Paulo return "UNKNOWN"; 93f05cddf9SRui Paulo #undef E2S 94f05cddf9SRui Paulo } 955b9c547cSRui Paulo 965b9c547cSRui Paulo 975b9c547cSRui Paulo const char * channel_width_to_string(enum chan_width width) 985b9c547cSRui Paulo { 995b9c547cSRui Paulo switch (width) { 1005b9c547cSRui Paulo case CHAN_WIDTH_20_NOHT: 1015b9c547cSRui Paulo return "20 MHz (no HT)"; 1025b9c547cSRui Paulo case CHAN_WIDTH_20: 1035b9c547cSRui Paulo return "20 MHz"; 1045b9c547cSRui Paulo case CHAN_WIDTH_40: 1055b9c547cSRui Paulo return "40 MHz"; 1065b9c547cSRui Paulo case CHAN_WIDTH_80: 1075b9c547cSRui Paulo return "80 MHz"; 1085b9c547cSRui Paulo case CHAN_WIDTH_80P80: 1095b9c547cSRui Paulo return "80+80 MHz"; 1105b9c547cSRui Paulo case CHAN_WIDTH_160: 1115b9c547cSRui Paulo return "160 MHz"; 1125b9c547cSRui Paulo default: 1135b9c547cSRui Paulo return "unknown"; 1145b9c547cSRui Paulo } 1155b9c547cSRui Paulo } 1165b9c547cSRui Paulo 1175b9c547cSRui Paulo 1185b9c547cSRui Paulo int ht_supported(const struct hostapd_hw_modes *mode) 1195b9c547cSRui Paulo { 1205b9c547cSRui Paulo if (!(mode->flags & HOSTAPD_MODE_FLAG_HT_INFO_KNOWN)) { 1215b9c547cSRui Paulo /* 1225b9c547cSRui Paulo * The driver did not indicate whether it supports HT. Assume 1235b9c547cSRui Paulo * it does to avoid connection issues. 1245b9c547cSRui Paulo */ 1255b9c547cSRui Paulo return 1; 1265b9c547cSRui Paulo } 1275b9c547cSRui Paulo 1285b9c547cSRui Paulo /* 1295b9c547cSRui Paulo * IEEE Std 802.11n-2009 20.1.1: 1305b9c547cSRui Paulo * An HT non-AP STA shall support all EQM rates for one spatial stream. 1315b9c547cSRui Paulo */ 1325b9c547cSRui Paulo return mode->mcs_set[0] == 0xff; 1335b9c547cSRui Paulo } 1345b9c547cSRui Paulo 1355b9c547cSRui Paulo 1365b9c547cSRui Paulo int vht_supported(const struct hostapd_hw_modes *mode) 1375b9c547cSRui Paulo { 1385b9c547cSRui Paulo if (!(mode->flags & HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN)) { 1395b9c547cSRui Paulo /* 1405b9c547cSRui Paulo * The driver did not indicate whether it supports VHT. Assume 1415b9c547cSRui Paulo * it does to avoid connection issues. 1425b9c547cSRui Paulo */ 1435b9c547cSRui Paulo return 1; 1445b9c547cSRui Paulo } 1455b9c547cSRui Paulo 1465b9c547cSRui Paulo /* 1475b9c547cSRui Paulo * A VHT non-AP STA shall support MCS 0-7 for one spatial stream. 1485b9c547cSRui Paulo * TODO: Verify if this complies with the standard 1495b9c547cSRui Paulo */ 1505b9c547cSRui Paulo return (mode->vht_mcs_set[0] & 0x3) != 3; 1515b9c547cSRui Paulo } 1525b9c547cSRui Paulo 1535b9c547cSRui Paulo 1545b9c547cSRui Paulo static int wpa_check_wowlan_trigger(const char *start, const char *trigger, 1555b9c547cSRui Paulo int capa_trigger, u8 *param_trigger) 1565b9c547cSRui Paulo { 1575b9c547cSRui Paulo if (os_strcmp(start, trigger) != 0) 1585b9c547cSRui Paulo return 0; 1595b9c547cSRui Paulo if (!capa_trigger) 1605b9c547cSRui Paulo return 0; 1615b9c547cSRui Paulo 1625b9c547cSRui Paulo *param_trigger = 1; 1635b9c547cSRui Paulo return 1; 1645b9c547cSRui Paulo } 1655b9c547cSRui Paulo 1665b9c547cSRui Paulo 1675b9c547cSRui Paulo struct wowlan_triggers * 1685b9c547cSRui Paulo wpa_get_wowlan_triggers(const char *wowlan_triggers, 1695b9c547cSRui Paulo const struct wpa_driver_capa *capa) 1705b9c547cSRui Paulo { 1715b9c547cSRui Paulo struct wowlan_triggers *triggers; 1725b9c547cSRui Paulo char *start, *end, *buf; 1735b9c547cSRui Paulo int last; 1745b9c547cSRui Paulo 1755b9c547cSRui Paulo if (!wowlan_triggers) 1765b9c547cSRui Paulo return NULL; 1775b9c547cSRui Paulo 1785b9c547cSRui Paulo buf = os_strdup(wowlan_triggers); 1795b9c547cSRui Paulo if (buf == NULL) 1805b9c547cSRui Paulo return NULL; 1815b9c547cSRui Paulo 1825b9c547cSRui Paulo triggers = os_zalloc(sizeof(*triggers)); 1835b9c547cSRui Paulo if (triggers == NULL) 1845b9c547cSRui Paulo goto out; 1855b9c547cSRui Paulo 1865b9c547cSRui Paulo #define CHECK_TRIGGER(trigger) \ 1875b9c547cSRui Paulo wpa_check_wowlan_trigger(start, #trigger, \ 1885b9c547cSRui Paulo capa->wowlan_triggers.trigger, \ 1895b9c547cSRui Paulo &triggers->trigger) 1905b9c547cSRui Paulo 1915b9c547cSRui Paulo start = buf; 1925b9c547cSRui Paulo while (*start != '\0') { 193780fb4a2SCy Schubert while (isblank((unsigned char) *start)) 1945b9c547cSRui Paulo start++; 1955b9c547cSRui Paulo if (*start == '\0') 1965b9c547cSRui Paulo break; 1975b9c547cSRui Paulo end = start; 198780fb4a2SCy Schubert while (!isblank((unsigned char) *end) && *end != '\0') 1995b9c547cSRui Paulo end++; 2005b9c547cSRui Paulo last = *end == '\0'; 2015b9c547cSRui Paulo *end = '\0'; 2025b9c547cSRui Paulo 2035b9c547cSRui Paulo if (!CHECK_TRIGGER(any) && 2045b9c547cSRui Paulo !CHECK_TRIGGER(disconnect) && 2055b9c547cSRui Paulo !CHECK_TRIGGER(magic_pkt) && 2065b9c547cSRui Paulo !CHECK_TRIGGER(gtk_rekey_failure) && 2075b9c547cSRui Paulo !CHECK_TRIGGER(eap_identity_req) && 2085b9c547cSRui Paulo !CHECK_TRIGGER(four_way_handshake) && 2095b9c547cSRui Paulo !CHECK_TRIGGER(rfkill_release)) { 2105b9c547cSRui Paulo wpa_printf(MSG_DEBUG, 2115b9c547cSRui Paulo "Unknown/unsupported wowlan trigger '%s'", 2125b9c547cSRui Paulo start); 2135b9c547cSRui Paulo os_free(triggers); 2145b9c547cSRui Paulo triggers = NULL; 2155b9c547cSRui Paulo goto out; 2165b9c547cSRui Paulo } 2175b9c547cSRui Paulo 2185b9c547cSRui Paulo if (last) 2195b9c547cSRui Paulo break; 2205b9c547cSRui Paulo start = end + 1; 2215b9c547cSRui Paulo } 2225b9c547cSRui Paulo #undef CHECK_TRIGGER 2235b9c547cSRui Paulo 2245b9c547cSRui Paulo out: 2255b9c547cSRui Paulo os_free(buf); 2265b9c547cSRui Paulo return triggers; 2275b9c547cSRui Paulo } 228780fb4a2SCy Schubert 229780fb4a2SCy Schubert 230780fb4a2SCy Schubert const char * driver_flag_to_string(u64 flag) 231780fb4a2SCy Schubert { 232780fb4a2SCy Schubert #define DF2S(x) case WPA_DRIVER_FLAGS_ ## x: return #x 233780fb4a2SCy Schubert switch (flag) { 234780fb4a2SCy Schubert DF2S(DRIVER_IE); 235780fb4a2SCy Schubert DF2S(SET_KEYS_AFTER_ASSOC); 236780fb4a2SCy Schubert DF2S(DFS_OFFLOAD); 237780fb4a2SCy Schubert DF2S(4WAY_HANDSHAKE); 238780fb4a2SCy Schubert DF2S(WIRED); 239780fb4a2SCy Schubert DF2S(SME); 240780fb4a2SCy Schubert DF2S(AP); 241780fb4a2SCy Schubert DF2S(SET_KEYS_AFTER_ASSOC_DONE); 242780fb4a2SCy Schubert DF2S(HT_2040_COEX); 243780fb4a2SCy Schubert DF2S(P2P_CONCURRENT); 244780fb4a2SCy Schubert DF2S(P2P_DEDICATED_INTERFACE); 245780fb4a2SCy Schubert DF2S(P2P_CAPABLE); 246780fb4a2SCy Schubert DF2S(AP_TEARDOWN_SUPPORT); 247780fb4a2SCy Schubert DF2S(P2P_MGMT_AND_NON_P2P); 248780fb4a2SCy Schubert DF2S(SANE_ERROR_CODES); 249780fb4a2SCy Schubert DF2S(OFFCHANNEL_TX); 250780fb4a2SCy Schubert DF2S(EAPOL_TX_STATUS); 251780fb4a2SCy Schubert DF2S(DEAUTH_TX_STATUS); 252780fb4a2SCy Schubert DF2S(BSS_SELECTION); 253780fb4a2SCy Schubert DF2S(TDLS_SUPPORT); 254780fb4a2SCy Schubert DF2S(TDLS_EXTERNAL_SETUP); 255780fb4a2SCy Schubert DF2S(PROBE_RESP_OFFLOAD); 256780fb4a2SCy Schubert DF2S(AP_UAPSD); 257780fb4a2SCy Schubert DF2S(INACTIVITY_TIMER); 258780fb4a2SCy Schubert DF2S(AP_MLME); 259780fb4a2SCy Schubert DF2S(SAE); 260780fb4a2SCy Schubert DF2S(OBSS_SCAN); 261780fb4a2SCy Schubert DF2S(IBSS); 262780fb4a2SCy Schubert DF2S(RADAR); 263780fb4a2SCy Schubert DF2S(DEDICATED_P2P_DEVICE); 264780fb4a2SCy Schubert DF2S(QOS_MAPPING); 265780fb4a2SCy Schubert DF2S(AP_CSA); 266780fb4a2SCy Schubert DF2S(MESH); 267780fb4a2SCy Schubert DF2S(ACS_OFFLOAD); 268780fb4a2SCy Schubert DF2S(KEY_MGMT_OFFLOAD); 269780fb4a2SCy Schubert DF2S(TDLS_CHANNEL_SWITCH); 270780fb4a2SCy Schubert DF2S(HT_IBSS); 271780fb4a2SCy Schubert DF2S(VHT_IBSS); 272780fb4a2SCy Schubert DF2S(SUPPORT_HW_MODE_ANY); 273780fb4a2SCy Schubert DF2S(OFFCHANNEL_SIMULTANEOUS); 274780fb4a2SCy Schubert DF2S(FULL_AP_CLIENT_STATE); 275780fb4a2SCy Schubert DF2S(P2P_LISTEN_OFFLOAD); 276*85732ac8SCy Schubert DF2S(SUPPORT_FILS); 277*85732ac8SCy Schubert DF2S(BEACON_RATE_LEGACY); 278*85732ac8SCy Schubert DF2S(BEACON_RATE_HT); 279*85732ac8SCy Schubert DF2S(BEACON_RATE_VHT); 280*85732ac8SCy Schubert DF2S(MGMT_TX_RANDOM_TA); 281*85732ac8SCy Schubert DF2S(MGMT_TX_RANDOM_TA_CONNECTED); 282*85732ac8SCy Schubert DF2S(SCHED_SCAN_RELATIVE_RSSI); 283*85732ac8SCy Schubert DF2S(HE_CAPABILITIES); 284*85732ac8SCy Schubert DF2S(FILS_SK_OFFLOAD); 285*85732ac8SCy Schubert DF2S(OCE_STA); 286*85732ac8SCy Schubert DF2S(OCE_AP); 287*85732ac8SCy Schubert DF2S(OCE_STA_CFON); 288*85732ac8SCy Schubert DF2S(MFP_OPTIONAL); 289780fb4a2SCy Schubert } 290780fb4a2SCy Schubert return "UNKNOWN"; 291780fb4a2SCy Schubert #undef DF2S 292780fb4a2SCy Schubert } 293