1f05cddf9SRui Paulo /* 2f05cddf9SRui Paulo * Common driver-related functions 3f05cddf9SRui Paulo * Copyright (c) 2003-2011, 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(STKSTART); 39f05cddf9SRui Paulo E2S(TDLS); 40f05cddf9SRui Paulo E2S(FT_RESPONSE); 41f05cddf9SRui Paulo E2S(IBSS_RSN_START); 42f05cddf9SRui Paulo E2S(AUTH); 43f05cddf9SRui Paulo E2S(DEAUTH); 44f05cddf9SRui Paulo E2S(ASSOC_REJECT); 45f05cddf9SRui Paulo E2S(AUTH_TIMED_OUT); 46f05cddf9SRui Paulo E2S(ASSOC_TIMED_OUT); 47f05cddf9SRui Paulo E2S(WPS_BUTTON_PUSHED); 48f05cddf9SRui Paulo E2S(TX_STATUS); 49f05cddf9SRui Paulo E2S(RX_FROM_UNKNOWN); 50f05cddf9SRui Paulo E2S(RX_MGMT); 51f05cddf9SRui Paulo E2S(REMAIN_ON_CHANNEL); 52f05cddf9SRui Paulo E2S(CANCEL_REMAIN_ON_CHANNEL); 53f05cddf9SRui Paulo E2S(RX_PROBE_REQ); 54f05cddf9SRui Paulo E2S(NEW_STA); 55f05cddf9SRui Paulo E2S(EAPOL_RX); 56f05cddf9SRui Paulo E2S(SIGNAL_CHANGE); 57f05cddf9SRui Paulo E2S(INTERFACE_ENABLED); 58f05cddf9SRui Paulo E2S(INTERFACE_DISABLED); 59f05cddf9SRui Paulo E2S(CHANNEL_LIST_CHANGED); 60f05cddf9SRui Paulo E2S(INTERFACE_UNAVAILABLE); 61f05cddf9SRui Paulo E2S(BEST_CHANNEL); 62f05cddf9SRui Paulo E2S(UNPROT_DEAUTH); 63f05cddf9SRui Paulo E2S(UNPROT_DISASSOC); 64f05cddf9SRui Paulo E2S(STATION_LOW_ACK); 65f05cddf9SRui Paulo E2S(IBSS_PEER_LOST); 66f05cddf9SRui Paulo E2S(DRIVER_GTK_REKEY); 67f05cddf9SRui Paulo E2S(SCHED_SCAN_STOPPED); 68f05cddf9SRui Paulo E2S(DRIVER_CLIENT_POLL_OK); 69f05cddf9SRui Paulo E2S(EAPOL_TX_STATUS); 70f05cddf9SRui Paulo E2S(CH_SWITCH); 71f05cddf9SRui Paulo E2S(WNM); 72*5b9c547cSRui Paulo E2S(CONNECT_FAILED_REASON); 73*5b9c547cSRui Paulo E2S(DFS_RADAR_DETECTED); 74*5b9c547cSRui Paulo E2S(DFS_CAC_FINISHED); 75*5b9c547cSRui Paulo E2S(DFS_CAC_ABORTED); 76*5b9c547cSRui Paulo E2S(DFS_NOP_FINISHED); 77*5b9c547cSRui Paulo E2S(SURVEY); 78*5b9c547cSRui Paulo E2S(SCAN_STARTED); 79*5b9c547cSRui Paulo E2S(AVOID_FREQUENCIES); 80*5b9c547cSRui Paulo E2S(NEW_PEER_CANDIDATE); 81*5b9c547cSRui Paulo E2S(ACS_CHANNEL_SELECTED); 82*5b9c547cSRui Paulo E2S(DFS_CAC_STARTED); 83f05cddf9SRui Paulo } 84f05cddf9SRui Paulo 85f05cddf9SRui Paulo return "UNKNOWN"; 86f05cddf9SRui Paulo #undef E2S 87f05cddf9SRui Paulo } 88*5b9c547cSRui Paulo 89*5b9c547cSRui Paulo 90*5b9c547cSRui Paulo const char * channel_width_to_string(enum chan_width width) 91*5b9c547cSRui Paulo { 92*5b9c547cSRui Paulo switch (width) { 93*5b9c547cSRui Paulo case CHAN_WIDTH_20_NOHT: 94*5b9c547cSRui Paulo return "20 MHz (no HT)"; 95*5b9c547cSRui Paulo case CHAN_WIDTH_20: 96*5b9c547cSRui Paulo return "20 MHz"; 97*5b9c547cSRui Paulo case CHAN_WIDTH_40: 98*5b9c547cSRui Paulo return "40 MHz"; 99*5b9c547cSRui Paulo case CHAN_WIDTH_80: 100*5b9c547cSRui Paulo return "80 MHz"; 101*5b9c547cSRui Paulo case CHAN_WIDTH_80P80: 102*5b9c547cSRui Paulo return "80+80 MHz"; 103*5b9c547cSRui Paulo case CHAN_WIDTH_160: 104*5b9c547cSRui Paulo return "160 MHz"; 105*5b9c547cSRui Paulo default: 106*5b9c547cSRui Paulo return "unknown"; 107*5b9c547cSRui Paulo } 108*5b9c547cSRui Paulo } 109*5b9c547cSRui Paulo 110*5b9c547cSRui Paulo 111*5b9c547cSRui Paulo int ht_supported(const struct hostapd_hw_modes *mode) 112*5b9c547cSRui Paulo { 113*5b9c547cSRui Paulo if (!(mode->flags & HOSTAPD_MODE_FLAG_HT_INFO_KNOWN)) { 114*5b9c547cSRui Paulo /* 115*5b9c547cSRui Paulo * The driver did not indicate whether it supports HT. Assume 116*5b9c547cSRui Paulo * it does to avoid connection issues. 117*5b9c547cSRui Paulo */ 118*5b9c547cSRui Paulo return 1; 119*5b9c547cSRui Paulo } 120*5b9c547cSRui Paulo 121*5b9c547cSRui Paulo /* 122*5b9c547cSRui Paulo * IEEE Std 802.11n-2009 20.1.1: 123*5b9c547cSRui Paulo * An HT non-AP STA shall support all EQM rates for one spatial stream. 124*5b9c547cSRui Paulo */ 125*5b9c547cSRui Paulo return mode->mcs_set[0] == 0xff; 126*5b9c547cSRui Paulo } 127*5b9c547cSRui Paulo 128*5b9c547cSRui Paulo 129*5b9c547cSRui Paulo int vht_supported(const struct hostapd_hw_modes *mode) 130*5b9c547cSRui Paulo { 131*5b9c547cSRui Paulo if (!(mode->flags & HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN)) { 132*5b9c547cSRui Paulo /* 133*5b9c547cSRui Paulo * The driver did not indicate whether it supports VHT. Assume 134*5b9c547cSRui Paulo * it does to avoid connection issues. 135*5b9c547cSRui Paulo */ 136*5b9c547cSRui Paulo return 1; 137*5b9c547cSRui Paulo } 138*5b9c547cSRui Paulo 139*5b9c547cSRui Paulo /* 140*5b9c547cSRui Paulo * A VHT non-AP STA shall support MCS 0-7 for one spatial stream. 141*5b9c547cSRui Paulo * TODO: Verify if this complies with the standard 142*5b9c547cSRui Paulo */ 143*5b9c547cSRui Paulo return (mode->vht_mcs_set[0] & 0x3) != 3; 144*5b9c547cSRui Paulo } 145*5b9c547cSRui Paulo 146*5b9c547cSRui Paulo 147*5b9c547cSRui Paulo static int wpa_check_wowlan_trigger(const char *start, const char *trigger, 148*5b9c547cSRui Paulo int capa_trigger, u8 *param_trigger) 149*5b9c547cSRui Paulo { 150*5b9c547cSRui Paulo if (os_strcmp(start, trigger) != 0) 151*5b9c547cSRui Paulo return 0; 152*5b9c547cSRui Paulo if (!capa_trigger) 153*5b9c547cSRui Paulo return 0; 154*5b9c547cSRui Paulo 155*5b9c547cSRui Paulo *param_trigger = 1; 156*5b9c547cSRui Paulo return 1; 157*5b9c547cSRui Paulo } 158*5b9c547cSRui Paulo 159*5b9c547cSRui Paulo 160*5b9c547cSRui Paulo struct wowlan_triggers * 161*5b9c547cSRui Paulo wpa_get_wowlan_triggers(const char *wowlan_triggers, 162*5b9c547cSRui Paulo const struct wpa_driver_capa *capa) 163*5b9c547cSRui Paulo { 164*5b9c547cSRui Paulo struct wowlan_triggers *triggers; 165*5b9c547cSRui Paulo char *start, *end, *buf; 166*5b9c547cSRui Paulo int last; 167*5b9c547cSRui Paulo 168*5b9c547cSRui Paulo if (!wowlan_triggers) 169*5b9c547cSRui Paulo return NULL; 170*5b9c547cSRui Paulo 171*5b9c547cSRui Paulo buf = os_strdup(wowlan_triggers); 172*5b9c547cSRui Paulo if (buf == NULL) 173*5b9c547cSRui Paulo return NULL; 174*5b9c547cSRui Paulo 175*5b9c547cSRui Paulo triggers = os_zalloc(sizeof(*triggers)); 176*5b9c547cSRui Paulo if (triggers == NULL) 177*5b9c547cSRui Paulo goto out; 178*5b9c547cSRui Paulo 179*5b9c547cSRui Paulo #define CHECK_TRIGGER(trigger) \ 180*5b9c547cSRui Paulo wpa_check_wowlan_trigger(start, #trigger, \ 181*5b9c547cSRui Paulo capa->wowlan_triggers.trigger, \ 182*5b9c547cSRui Paulo &triggers->trigger) 183*5b9c547cSRui Paulo 184*5b9c547cSRui Paulo start = buf; 185*5b9c547cSRui Paulo while (*start != '\0') { 186*5b9c547cSRui Paulo while (isblank(*start)) 187*5b9c547cSRui Paulo start++; 188*5b9c547cSRui Paulo if (*start == '\0') 189*5b9c547cSRui Paulo break; 190*5b9c547cSRui Paulo end = start; 191*5b9c547cSRui Paulo while (!isblank(*end) && *end != '\0') 192*5b9c547cSRui Paulo end++; 193*5b9c547cSRui Paulo last = *end == '\0'; 194*5b9c547cSRui Paulo *end = '\0'; 195*5b9c547cSRui Paulo 196*5b9c547cSRui Paulo if (!CHECK_TRIGGER(any) && 197*5b9c547cSRui Paulo !CHECK_TRIGGER(disconnect) && 198*5b9c547cSRui Paulo !CHECK_TRIGGER(magic_pkt) && 199*5b9c547cSRui Paulo !CHECK_TRIGGER(gtk_rekey_failure) && 200*5b9c547cSRui Paulo !CHECK_TRIGGER(eap_identity_req) && 201*5b9c547cSRui Paulo !CHECK_TRIGGER(four_way_handshake) && 202*5b9c547cSRui Paulo !CHECK_TRIGGER(rfkill_release)) { 203*5b9c547cSRui Paulo wpa_printf(MSG_DEBUG, 204*5b9c547cSRui Paulo "Unknown/unsupported wowlan trigger '%s'", 205*5b9c547cSRui Paulo start); 206*5b9c547cSRui Paulo os_free(triggers); 207*5b9c547cSRui Paulo triggers = NULL; 208*5b9c547cSRui Paulo goto out; 209*5b9c547cSRui Paulo } 210*5b9c547cSRui Paulo 211*5b9c547cSRui Paulo if (last) 212*5b9c547cSRui Paulo break; 213*5b9c547cSRui Paulo start = end + 1; 214*5b9c547cSRui Paulo } 215*5b9c547cSRui Paulo #undef CHECK_TRIGGER 216*5b9c547cSRui Paulo 217*5b9c547cSRui Paulo out: 218*5b9c547cSRui Paulo os_free(buf); 219*5b9c547cSRui Paulo return triggers; 220*5b9c547cSRui Paulo } 221