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 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(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(WNM); 71 E2S(CONNECT_FAILED_REASON); 72 E2S(DFS_RADAR_DETECTED); 73 E2S(DFS_CAC_FINISHED); 74 E2S(DFS_CAC_ABORTED); 75 E2S(DFS_NOP_FINISHED); 76 E2S(SURVEY); 77 E2S(SCAN_STARTED); 78 E2S(AVOID_FREQUENCIES); 79 E2S(NEW_PEER_CANDIDATE); 80 E2S(ACS_CHANNEL_SELECTED); 81 E2S(DFS_CAC_STARTED); 82 E2S(P2P_LO_STOP); 83 E2S(BEACON_LOSS); 84 E2S(DFS_PRE_CAC_EXPIRED); 85 E2S(EXTERNAL_AUTH); 86 E2S(PORT_AUTHORIZED); 87 E2S(STATION_OPMODE_CHANGED); 88 E2S(INTERFACE_MAC_CHANGED); 89 E2S(WDS_STA_INTERFACE_STATUS); 90 } 91 92 return "UNKNOWN"; 93 #undef E2S 94 } 95 96 97 const char * channel_width_to_string(enum chan_width width) 98 { 99 switch (width) { 100 case CHAN_WIDTH_20_NOHT: 101 return "20 MHz (no HT)"; 102 case CHAN_WIDTH_20: 103 return "20 MHz"; 104 case CHAN_WIDTH_40: 105 return "40 MHz"; 106 case CHAN_WIDTH_80: 107 return "80 MHz"; 108 case CHAN_WIDTH_80P80: 109 return "80+80 MHz"; 110 case CHAN_WIDTH_160: 111 return "160 MHz"; 112 default: 113 return "unknown"; 114 } 115 } 116 117 118 int ht_supported(const struct hostapd_hw_modes *mode) 119 { 120 if (!(mode->flags & HOSTAPD_MODE_FLAG_HT_INFO_KNOWN)) { 121 /* 122 * The driver did not indicate whether it supports HT. Assume 123 * it does to avoid connection issues. 124 */ 125 return 1; 126 } 127 128 /* 129 * IEEE Std 802.11n-2009 20.1.1: 130 * An HT non-AP STA shall support all EQM rates for one spatial stream. 131 */ 132 return mode->mcs_set[0] == 0xff; 133 } 134 135 136 int vht_supported(const struct hostapd_hw_modes *mode) 137 { 138 if (!(mode->flags & HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN)) { 139 /* 140 * The driver did not indicate whether it supports VHT. Assume 141 * it does to avoid connection issues. 142 */ 143 return 1; 144 } 145 146 /* 147 * A VHT non-AP STA shall support MCS 0-7 for one spatial stream. 148 * TODO: Verify if this complies with the standard 149 */ 150 return (mode->vht_mcs_set[0] & 0x3) != 3; 151 } 152 153 154 static int wpa_check_wowlan_trigger(const char *start, const char *trigger, 155 int capa_trigger, u8 *param_trigger) 156 { 157 if (os_strcmp(start, trigger) != 0) 158 return 0; 159 if (!capa_trigger) 160 return 0; 161 162 *param_trigger = 1; 163 return 1; 164 } 165 166 167 struct wowlan_triggers * 168 wpa_get_wowlan_triggers(const char *wowlan_triggers, 169 const struct wpa_driver_capa *capa) 170 { 171 struct wowlan_triggers *triggers; 172 char *start, *end, *buf; 173 int last; 174 175 if (!wowlan_triggers) 176 return NULL; 177 178 buf = os_strdup(wowlan_triggers); 179 if (buf == NULL) 180 return NULL; 181 182 triggers = os_zalloc(sizeof(*triggers)); 183 if (triggers == NULL) 184 goto out; 185 186 #define CHECK_TRIGGER(trigger) \ 187 wpa_check_wowlan_trigger(start, #trigger, \ 188 capa->wowlan_triggers.trigger, \ 189 &triggers->trigger) 190 191 start = buf; 192 while (*start != '\0') { 193 while (isblank((unsigned char) *start)) 194 start++; 195 if (*start == '\0') 196 break; 197 end = start; 198 while (!isblank((unsigned char) *end) && *end != '\0') 199 end++; 200 last = *end == '\0'; 201 *end = '\0'; 202 203 if (!CHECK_TRIGGER(any) && 204 !CHECK_TRIGGER(disconnect) && 205 !CHECK_TRIGGER(magic_pkt) && 206 !CHECK_TRIGGER(gtk_rekey_failure) && 207 !CHECK_TRIGGER(eap_identity_req) && 208 !CHECK_TRIGGER(four_way_handshake) && 209 !CHECK_TRIGGER(rfkill_release)) { 210 wpa_printf(MSG_DEBUG, 211 "Unknown/unsupported wowlan trigger '%s'", 212 start); 213 os_free(triggers); 214 triggers = NULL; 215 goto out; 216 } 217 218 if (last) 219 break; 220 start = end + 1; 221 } 222 #undef CHECK_TRIGGER 223 224 out: 225 os_free(buf); 226 return triggers; 227 } 228 229 230 const char * driver_flag_to_string(u64 flag) 231 { 232 #define DF2S(x) case WPA_DRIVER_FLAGS_ ## x: return #x 233 switch (flag) { 234 DF2S(DRIVER_IE); 235 DF2S(SET_KEYS_AFTER_ASSOC); 236 DF2S(DFS_OFFLOAD); 237 DF2S(4WAY_HANDSHAKE); 238 DF2S(WIRED); 239 DF2S(SME); 240 DF2S(AP); 241 DF2S(SET_KEYS_AFTER_ASSOC_DONE); 242 DF2S(HT_2040_COEX); 243 DF2S(P2P_CONCURRENT); 244 DF2S(P2P_DEDICATED_INTERFACE); 245 DF2S(P2P_CAPABLE); 246 DF2S(AP_TEARDOWN_SUPPORT); 247 DF2S(P2P_MGMT_AND_NON_P2P); 248 DF2S(SANE_ERROR_CODES); 249 DF2S(OFFCHANNEL_TX); 250 DF2S(EAPOL_TX_STATUS); 251 DF2S(DEAUTH_TX_STATUS); 252 DF2S(BSS_SELECTION); 253 DF2S(TDLS_SUPPORT); 254 DF2S(TDLS_EXTERNAL_SETUP); 255 DF2S(PROBE_RESP_OFFLOAD); 256 DF2S(AP_UAPSD); 257 DF2S(INACTIVITY_TIMER); 258 DF2S(AP_MLME); 259 DF2S(SAE); 260 DF2S(OBSS_SCAN); 261 DF2S(IBSS); 262 DF2S(RADAR); 263 DF2S(DEDICATED_P2P_DEVICE); 264 DF2S(QOS_MAPPING); 265 DF2S(AP_CSA); 266 DF2S(MESH); 267 DF2S(ACS_OFFLOAD); 268 DF2S(KEY_MGMT_OFFLOAD); 269 DF2S(TDLS_CHANNEL_SWITCH); 270 DF2S(HT_IBSS); 271 DF2S(VHT_IBSS); 272 DF2S(SUPPORT_HW_MODE_ANY); 273 DF2S(OFFCHANNEL_SIMULTANEOUS); 274 DF2S(FULL_AP_CLIENT_STATE); 275 DF2S(P2P_LISTEN_OFFLOAD); 276 DF2S(SUPPORT_FILS); 277 DF2S(BEACON_RATE_LEGACY); 278 DF2S(BEACON_RATE_HT); 279 DF2S(BEACON_RATE_VHT); 280 DF2S(MGMT_TX_RANDOM_TA); 281 DF2S(MGMT_TX_RANDOM_TA_CONNECTED); 282 DF2S(SCHED_SCAN_RELATIVE_RSSI); 283 DF2S(HE_CAPABILITIES); 284 DF2S(FILS_SK_OFFLOAD); 285 DF2S(OCE_STA); 286 DF2S(OCE_AP); 287 DF2S(OCE_STA_CFON); 288 DF2S(MFP_OPTIONAL); 289 } 290 return "UNKNOWN"; 291 #undef DF2S 292 } 293