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