Home | History | Annotate | Download | only in drivers
      1 /*
      2  * Common driver-related functions
      3  * Copyright (c) 2003-2017, Jouni Malinen <j (at) 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 channel_width_to_int(enum chan_width width)
    119 {
    120 	switch (width) {
    121 	case CHAN_WIDTH_20_NOHT:
    122 	case CHAN_WIDTH_20:
    123 		return 20;
    124 	case CHAN_WIDTH_40:
    125 		return 40;
    126 	case CHAN_WIDTH_80:
    127 		return 80;
    128 	case CHAN_WIDTH_80P80:
    129 	case CHAN_WIDTH_160:
    130 		return 160;
    131 	default:
    132 		return 0;
    133 	}
    134 }
    135 
    136 
    137 int ht_supported(const struct hostapd_hw_modes *mode)
    138 {
    139 	if (!(mode->flags & HOSTAPD_MODE_FLAG_HT_INFO_KNOWN)) {
    140 		/*
    141 		 * The driver did not indicate whether it supports HT. Assume
    142 		 * it does to avoid connection issues.
    143 		 */
    144 		return 1;
    145 	}
    146 
    147 	/*
    148 	 * IEEE Std 802.11n-2009 20.1.1:
    149 	 * An HT non-AP STA shall support all EQM rates for one spatial stream.
    150 	 */
    151 	return mode->mcs_set[0] == 0xff;
    152 }
    153 
    154 
    155 int vht_supported(const struct hostapd_hw_modes *mode)
    156 {
    157 	if (!(mode->flags & HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN)) {
    158 		/*
    159 		 * The driver did not indicate whether it supports VHT. Assume
    160 		 * it does to avoid connection issues.
    161 		 */
    162 		return 1;
    163 	}
    164 
    165 	/*
    166 	 * A VHT non-AP STA shall support MCS 0-7 for one spatial stream.
    167 	 * TODO: Verify if this complies with the standard
    168 	 */
    169 	return (mode->vht_mcs_set[0] & 0x3) != 3;
    170 }
    171 
    172 
    173 static int wpa_check_wowlan_trigger(const char *start, const char *trigger,
    174 				    int capa_trigger, u8 *param_trigger)
    175 {
    176 	if (os_strcmp(start, trigger) != 0)
    177 		return 0;
    178 	if (!capa_trigger)
    179 		return 0;
    180 
    181 	*param_trigger = 1;
    182 	return 1;
    183 }
    184 
    185 
    186 struct wowlan_triggers *
    187 wpa_get_wowlan_triggers(const char *wowlan_triggers,
    188 			const struct wpa_driver_capa *capa)
    189 {
    190 	struct wowlan_triggers *triggers;
    191 	char *start, *end, *buf;
    192 	int last;
    193 
    194 	if (!wowlan_triggers)
    195 		return NULL;
    196 
    197 	buf = os_strdup(wowlan_triggers);
    198 	if (buf == NULL)
    199 		return NULL;
    200 
    201 	triggers = os_zalloc(sizeof(*triggers));
    202 	if (triggers == NULL)
    203 		goto out;
    204 
    205 #define CHECK_TRIGGER(trigger) \
    206 	wpa_check_wowlan_trigger(start, #trigger,			\
    207 				  capa->wowlan_triggers.trigger,	\
    208 				  &triggers->trigger)
    209 
    210 	start = buf;
    211 	while (*start != '\0') {
    212 		while (isblank((unsigned char) *start))
    213 			start++;
    214 		if (*start == '\0')
    215 			break;
    216 		end = start;
    217 		while (!isblank((unsigned char) *end) && *end != '\0')
    218 			end++;
    219 		last = *end == '\0';
    220 		*end = '\0';
    221 
    222 		if (!CHECK_TRIGGER(any) &&
    223 		    !CHECK_TRIGGER(disconnect) &&
    224 		    !CHECK_TRIGGER(magic_pkt) &&
    225 		    !CHECK_TRIGGER(gtk_rekey_failure) &&
    226 		    !CHECK_TRIGGER(eap_identity_req) &&
    227 		    !CHECK_TRIGGER(four_way_handshake) &&
    228 		    !CHECK_TRIGGER(rfkill_release)) {
    229 			wpa_printf(MSG_DEBUG,
    230 				   "Unknown/unsupported wowlan trigger '%s'",
    231 				   start);
    232 			os_free(triggers);
    233 			triggers = NULL;
    234 			goto out;
    235 		}
    236 
    237 		if (last)
    238 			break;
    239 		start = end + 1;
    240 	}
    241 #undef CHECK_TRIGGER
    242 
    243 out:
    244 	os_free(buf);
    245 	return triggers;
    246 }
    247 
    248 
    249 const char * driver_flag_to_string(u64 flag)
    250 {
    251 #define DF2S(x) case WPA_DRIVER_FLAGS_ ## x: return #x
    252 	switch (flag) {
    253 	DF2S(DRIVER_IE);
    254 	DF2S(SET_KEYS_AFTER_ASSOC);
    255 	DF2S(DFS_OFFLOAD);
    256 	DF2S(4WAY_HANDSHAKE_PSK);
    257 	DF2S(4WAY_HANDSHAKE_8021X);
    258 	DF2S(WIRED);
    259 	DF2S(SME);
    260 	DF2S(AP);
    261 	DF2S(SET_KEYS_AFTER_ASSOC_DONE);
    262 	DF2S(HT_2040_COEX);
    263 	DF2S(P2P_CONCURRENT);
    264 	DF2S(P2P_DEDICATED_INTERFACE);
    265 	DF2S(P2P_CAPABLE);
    266 	DF2S(AP_TEARDOWN_SUPPORT);
    267 	DF2S(P2P_MGMT_AND_NON_P2P);
    268 	DF2S(SANE_ERROR_CODES);
    269 	DF2S(OFFCHANNEL_TX);
    270 	DF2S(EAPOL_TX_STATUS);
    271 	DF2S(DEAUTH_TX_STATUS);
    272 	DF2S(BSS_SELECTION);
    273 	DF2S(TDLS_SUPPORT);
    274 	DF2S(TDLS_EXTERNAL_SETUP);
    275 	DF2S(PROBE_RESP_OFFLOAD);
    276 	DF2S(AP_UAPSD);
    277 	DF2S(INACTIVITY_TIMER);
    278 	DF2S(AP_MLME);
    279 	DF2S(SAE);
    280 	DF2S(OBSS_SCAN);
    281 	DF2S(IBSS);
    282 	DF2S(RADAR);
    283 	DF2S(DEDICATED_P2P_DEVICE);
    284 	DF2S(QOS_MAPPING);
    285 	DF2S(AP_CSA);
    286 	DF2S(MESH);
    287 	DF2S(ACS_OFFLOAD);
    288 	DF2S(KEY_MGMT_OFFLOAD);
    289 	DF2S(TDLS_CHANNEL_SWITCH);
    290 	DF2S(HT_IBSS);
    291 	DF2S(VHT_IBSS);
    292 	DF2S(SUPPORT_HW_MODE_ANY);
    293 	DF2S(OFFCHANNEL_SIMULTANEOUS);
    294 	DF2S(FULL_AP_CLIENT_STATE);
    295 	DF2S(P2P_LISTEN_OFFLOAD);
    296 	DF2S(SUPPORT_FILS);
    297 	DF2S(BEACON_RATE_LEGACY);
    298 	DF2S(BEACON_RATE_HT);
    299 	DF2S(BEACON_RATE_VHT);
    300 	DF2S(MGMT_TX_RANDOM_TA);
    301 	DF2S(MGMT_TX_RANDOM_TA_CONNECTED);
    302 	DF2S(SCHED_SCAN_RELATIVE_RSSI);
    303 	DF2S(HE_CAPABILITIES);
    304 	DF2S(FILS_SK_OFFLOAD);
    305 	DF2S(OCE_STA);
    306 	DF2S(OCE_AP);
    307 	DF2S(OCE_STA_CFON);
    308 	DF2S(MFP_OPTIONAL);
    309 	}
    310 	return "UNKNOWN";
    311 #undef DF2S
    312 }
    313