1e5b75505Sopenharmony_ci/*
2e5b75505Sopenharmony_ci * Common driver-related functions
3e5b75505Sopenharmony_ci * Copyright (c) 2003-2017, Jouni Malinen <j@w1.fi>
4e5b75505Sopenharmony_ci *
5e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license.
6e5b75505Sopenharmony_ci * See README for more details.
7e5b75505Sopenharmony_ci */
8e5b75505Sopenharmony_ci
9e5b75505Sopenharmony_ci#include "includes.h"
10e5b75505Sopenharmony_ci#include "utils/common.h"
11e5b75505Sopenharmony_ci#include "driver.h"
12e5b75505Sopenharmony_ci
13e5b75505Sopenharmony_civoid wpa_scan_results_free(struct wpa_scan_results *res)
14e5b75505Sopenharmony_ci{
15e5b75505Sopenharmony_ci	size_t i;
16e5b75505Sopenharmony_ci
17e5b75505Sopenharmony_ci	if (res == NULL)
18e5b75505Sopenharmony_ci		return;
19e5b75505Sopenharmony_ci
20e5b75505Sopenharmony_ci	for (i = 0; i < res->num; i++)
21e5b75505Sopenharmony_ci		os_free(res->res[i]);
22e5b75505Sopenharmony_ci	os_free(res->res);
23e5b75505Sopenharmony_ci	os_free(res);
24e5b75505Sopenharmony_ci}
25e5b75505Sopenharmony_ci
26e5b75505Sopenharmony_ci
27e5b75505Sopenharmony_ciconst char * event_to_string(enum wpa_event_type event)
28e5b75505Sopenharmony_ci{
29e5b75505Sopenharmony_ci#define E2S(n) case EVENT_ ## n: return #n
30e5b75505Sopenharmony_ci	switch (event) {
31e5b75505Sopenharmony_ci	E2S(ASSOC);
32e5b75505Sopenharmony_ci	E2S(DISASSOC);
33e5b75505Sopenharmony_ci	E2S(MICHAEL_MIC_FAILURE);
34e5b75505Sopenharmony_ci	E2S(SCAN_RESULTS);
35e5b75505Sopenharmony_ci	E2S(ASSOCINFO);
36e5b75505Sopenharmony_ci	E2S(INTERFACE_STATUS);
37e5b75505Sopenharmony_ci	E2S(PMKID_CANDIDATE);
38e5b75505Sopenharmony_ci	E2S(TDLS);
39e5b75505Sopenharmony_ci	E2S(FT_RESPONSE);
40e5b75505Sopenharmony_ci	E2S(IBSS_RSN_START);
41e5b75505Sopenharmony_ci	E2S(AUTH);
42e5b75505Sopenharmony_ci	E2S(DEAUTH);
43e5b75505Sopenharmony_ci	E2S(ASSOC_REJECT);
44e5b75505Sopenharmony_ci	E2S(AUTH_TIMED_OUT);
45e5b75505Sopenharmony_ci	E2S(ASSOC_TIMED_OUT);
46e5b75505Sopenharmony_ci	E2S(WPS_BUTTON_PUSHED);
47e5b75505Sopenharmony_ci	E2S(TX_STATUS);
48e5b75505Sopenharmony_ci	E2S(RX_FROM_UNKNOWN);
49e5b75505Sopenharmony_ci	E2S(RX_MGMT);
50e5b75505Sopenharmony_ci	E2S(REMAIN_ON_CHANNEL);
51e5b75505Sopenharmony_ci	E2S(CANCEL_REMAIN_ON_CHANNEL);
52e5b75505Sopenharmony_ci	E2S(RX_PROBE_REQ);
53e5b75505Sopenharmony_ci	E2S(NEW_STA);
54e5b75505Sopenharmony_ci	E2S(EAPOL_RX);
55e5b75505Sopenharmony_ci	E2S(SIGNAL_CHANGE);
56e5b75505Sopenharmony_ci	E2S(INTERFACE_ENABLED);
57e5b75505Sopenharmony_ci	E2S(INTERFACE_DISABLED);
58e5b75505Sopenharmony_ci	E2S(CHANNEL_LIST_CHANGED);
59e5b75505Sopenharmony_ci	E2S(INTERFACE_UNAVAILABLE);
60e5b75505Sopenharmony_ci	E2S(BEST_CHANNEL);
61e5b75505Sopenharmony_ci	E2S(UNPROT_DEAUTH);
62e5b75505Sopenharmony_ci	E2S(UNPROT_DISASSOC);
63e5b75505Sopenharmony_ci	E2S(STATION_LOW_ACK);
64e5b75505Sopenharmony_ci	E2S(IBSS_PEER_LOST);
65e5b75505Sopenharmony_ci	E2S(DRIVER_GTK_REKEY);
66e5b75505Sopenharmony_ci	E2S(SCHED_SCAN_STOPPED);
67e5b75505Sopenharmony_ci	E2S(DRIVER_CLIENT_POLL_OK);
68e5b75505Sopenharmony_ci	E2S(EAPOL_TX_STATUS);
69e5b75505Sopenharmony_ci	E2S(CH_SWITCH);
70e5b75505Sopenharmony_ci	E2S(CH_SWITCH_STARTED);
71e5b75505Sopenharmony_ci	E2S(WNM);
72e5b75505Sopenharmony_ci	E2S(CONNECT_FAILED_REASON);
73e5b75505Sopenharmony_ci	E2S(DFS_RADAR_DETECTED);
74e5b75505Sopenharmony_ci	E2S(DFS_CAC_FINISHED);
75e5b75505Sopenharmony_ci	E2S(DFS_CAC_ABORTED);
76e5b75505Sopenharmony_ci	E2S(DFS_NOP_FINISHED);
77e5b75505Sopenharmony_ci	E2S(SURVEY);
78e5b75505Sopenharmony_ci	E2S(SCAN_STARTED);
79e5b75505Sopenharmony_ci	E2S(AVOID_FREQUENCIES);
80e5b75505Sopenharmony_ci	E2S(NEW_PEER_CANDIDATE);
81e5b75505Sopenharmony_ci	E2S(ACS_CHANNEL_SELECTED);
82e5b75505Sopenharmony_ci	E2S(DFS_CAC_STARTED);
83e5b75505Sopenharmony_ci	E2S(P2P_LO_STOP);
84e5b75505Sopenharmony_ci	E2S(BEACON_LOSS);
85e5b75505Sopenharmony_ci	E2S(DFS_PRE_CAC_EXPIRED);
86e5b75505Sopenharmony_ci	E2S(EXTERNAL_AUTH);
87e5b75505Sopenharmony_ci	E2S(PORT_AUTHORIZED);
88e5b75505Sopenharmony_ci	E2S(STATION_OPMODE_CHANGED);
89e5b75505Sopenharmony_ci	E2S(INTERFACE_MAC_CHANGED);
90e5b75505Sopenharmony_ci	E2S(WDS_STA_INTERFACE_STATUS);
91e5b75505Sopenharmony_ci	E2S(UPDATE_DH);
92e5b75505Sopenharmony_ci	}
93e5b75505Sopenharmony_ci
94e5b75505Sopenharmony_ci	return "UNKNOWN";
95e5b75505Sopenharmony_ci#undef E2S
96e5b75505Sopenharmony_ci}
97e5b75505Sopenharmony_ci
98e5b75505Sopenharmony_ci
99e5b75505Sopenharmony_ciconst char * channel_width_to_string(enum chan_width width)
100e5b75505Sopenharmony_ci{
101e5b75505Sopenharmony_ci	switch (width) {
102e5b75505Sopenharmony_ci	case CHAN_WIDTH_20_NOHT:
103e5b75505Sopenharmony_ci		return "20 MHz (no HT)";
104e5b75505Sopenharmony_ci	case CHAN_WIDTH_20:
105e5b75505Sopenharmony_ci		return "20 MHz";
106e5b75505Sopenharmony_ci	case CHAN_WIDTH_40:
107e5b75505Sopenharmony_ci		return "40 MHz";
108e5b75505Sopenharmony_ci	case CHAN_WIDTH_80:
109e5b75505Sopenharmony_ci		return "80 MHz";
110e5b75505Sopenharmony_ci	case CHAN_WIDTH_80P80:
111e5b75505Sopenharmony_ci		return "80+80 MHz";
112e5b75505Sopenharmony_ci	case CHAN_WIDTH_160:
113e5b75505Sopenharmony_ci		return "160 MHz";
114e5b75505Sopenharmony_ci	default:
115e5b75505Sopenharmony_ci		return "unknown";
116e5b75505Sopenharmony_ci	}
117e5b75505Sopenharmony_ci}
118e5b75505Sopenharmony_ci
119e5b75505Sopenharmony_ci
120e5b75505Sopenharmony_ciint channel_width_to_int(enum chan_width width)
121e5b75505Sopenharmony_ci{
122e5b75505Sopenharmony_ci	switch (width) {
123e5b75505Sopenharmony_ci	case CHAN_WIDTH_20_NOHT:
124e5b75505Sopenharmony_ci	case CHAN_WIDTH_20:
125e5b75505Sopenharmony_ci		return 20;
126e5b75505Sopenharmony_ci	case CHAN_WIDTH_40:
127e5b75505Sopenharmony_ci		return 40;
128e5b75505Sopenharmony_ci	case CHAN_WIDTH_80:
129e5b75505Sopenharmony_ci		return 80;
130e5b75505Sopenharmony_ci	case CHAN_WIDTH_80P80:
131e5b75505Sopenharmony_ci	case CHAN_WIDTH_160:
132e5b75505Sopenharmony_ci		return 160;
133e5b75505Sopenharmony_ci	default:
134e5b75505Sopenharmony_ci		return 0;
135e5b75505Sopenharmony_ci	}
136e5b75505Sopenharmony_ci}
137e5b75505Sopenharmony_ci
138e5b75505Sopenharmony_ci
139e5b75505Sopenharmony_ciint ht_supported(const struct hostapd_hw_modes *mode)
140e5b75505Sopenharmony_ci{
141e5b75505Sopenharmony_ci	if (!(mode->flags & HOSTAPD_MODE_FLAG_HT_INFO_KNOWN)) {
142e5b75505Sopenharmony_ci		/*
143e5b75505Sopenharmony_ci		 * The driver did not indicate whether it supports HT. Assume
144e5b75505Sopenharmony_ci		 * it does to avoid connection issues.
145e5b75505Sopenharmony_ci		 */
146e5b75505Sopenharmony_ci		return 1;
147e5b75505Sopenharmony_ci	}
148e5b75505Sopenharmony_ci
149e5b75505Sopenharmony_ci	/*
150e5b75505Sopenharmony_ci	 * IEEE Std 802.11n-2009 20.1.1:
151e5b75505Sopenharmony_ci	 * An HT non-AP STA shall support all EQM rates for one spatial stream.
152e5b75505Sopenharmony_ci	 */
153e5b75505Sopenharmony_ci	return mode->mcs_set[0] == 0xff;
154e5b75505Sopenharmony_ci}
155e5b75505Sopenharmony_ci
156e5b75505Sopenharmony_ci
157e5b75505Sopenharmony_ciint vht_supported(const struct hostapd_hw_modes *mode)
158e5b75505Sopenharmony_ci{
159e5b75505Sopenharmony_ci	if (!(mode->flags & HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN)) {
160e5b75505Sopenharmony_ci		/*
161e5b75505Sopenharmony_ci		 * The driver did not indicate whether it supports VHT. Assume
162e5b75505Sopenharmony_ci		 * it does to avoid connection issues.
163e5b75505Sopenharmony_ci		 */
164e5b75505Sopenharmony_ci		return 1;
165e5b75505Sopenharmony_ci	}
166e5b75505Sopenharmony_ci
167e5b75505Sopenharmony_ci	/*
168e5b75505Sopenharmony_ci	 * A VHT non-AP STA shall support MCS 0-7 for one spatial stream.
169e5b75505Sopenharmony_ci	 * TODO: Verify if this complies with the standard
170e5b75505Sopenharmony_ci	 */
171e5b75505Sopenharmony_ci	return (mode->vht_mcs_set[0] & 0x3) != 3;
172e5b75505Sopenharmony_ci}
173e5b75505Sopenharmony_ci
174e5b75505Sopenharmony_ci
175e5b75505Sopenharmony_cistatic int wpa_check_wowlan_trigger(const char *start, const char *trigger,
176e5b75505Sopenharmony_ci				    int capa_trigger, u8 *param_trigger)
177e5b75505Sopenharmony_ci{
178e5b75505Sopenharmony_ci	if (os_strcmp(start, trigger) != 0)
179e5b75505Sopenharmony_ci		return 0;
180e5b75505Sopenharmony_ci	if (!capa_trigger)
181e5b75505Sopenharmony_ci		return 0;
182e5b75505Sopenharmony_ci
183e5b75505Sopenharmony_ci	*param_trigger = 1;
184e5b75505Sopenharmony_ci	return 1;
185e5b75505Sopenharmony_ci}
186e5b75505Sopenharmony_ci
187e5b75505Sopenharmony_ci
188e5b75505Sopenharmony_cistruct wowlan_triggers *
189e5b75505Sopenharmony_ciwpa_get_wowlan_triggers(const char *wowlan_triggers,
190e5b75505Sopenharmony_ci			const struct wpa_driver_capa *capa)
191e5b75505Sopenharmony_ci{
192e5b75505Sopenharmony_ci	struct wowlan_triggers *triggers;
193e5b75505Sopenharmony_ci	char *start, *end, *buf;
194e5b75505Sopenharmony_ci	int last;
195e5b75505Sopenharmony_ci
196e5b75505Sopenharmony_ci	if (!wowlan_triggers)
197e5b75505Sopenharmony_ci		return NULL;
198e5b75505Sopenharmony_ci
199e5b75505Sopenharmony_ci	buf = os_strdup(wowlan_triggers);
200e5b75505Sopenharmony_ci	if (buf == NULL)
201e5b75505Sopenharmony_ci		return NULL;
202e5b75505Sopenharmony_ci
203e5b75505Sopenharmony_ci	triggers = os_zalloc(sizeof(*triggers));
204e5b75505Sopenharmony_ci	if (triggers == NULL)
205e5b75505Sopenharmony_ci		goto out;
206e5b75505Sopenharmony_ci
207e5b75505Sopenharmony_ci#define CHECK_TRIGGER(trigger) \
208e5b75505Sopenharmony_ci	wpa_check_wowlan_trigger(start, #trigger,			\
209e5b75505Sopenharmony_ci				  capa->wowlan_triggers.trigger,	\
210e5b75505Sopenharmony_ci				  &triggers->trigger)
211e5b75505Sopenharmony_ci
212e5b75505Sopenharmony_ci	start = buf;
213e5b75505Sopenharmony_ci	while (*start != '\0') {
214e5b75505Sopenharmony_ci		while (isblank((unsigned char) *start))
215e5b75505Sopenharmony_ci			start++;
216e5b75505Sopenharmony_ci		if (*start == '\0')
217e5b75505Sopenharmony_ci			break;
218e5b75505Sopenharmony_ci		end = start;
219e5b75505Sopenharmony_ci		while (!isblank((unsigned char) *end) && *end != '\0')
220e5b75505Sopenharmony_ci			end++;
221e5b75505Sopenharmony_ci		last = *end == '\0';
222e5b75505Sopenharmony_ci		*end = '\0';
223e5b75505Sopenharmony_ci
224e5b75505Sopenharmony_ci		if (!CHECK_TRIGGER(any) &&
225e5b75505Sopenharmony_ci		    !CHECK_TRIGGER(disconnect) &&
226e5b75505Sopenharmony_ci		    !CHECK_TRIGGER(magic_pkt) &&
227e5b75505Sopenharmony_ci		    !CHECK_TRIGGER(gtk_rekey_failure) &&
228e5b75505Sopenharmony_ci		    !CHECK_TRIGGER(eap_identity_req) &&
229e5b75505Sopenharmony_ci		    !CHECK_TRIGGER(four_way_handshake) &&
230e5b75505Sopenharmony_ci		    !CHECK_TRIGGER(rfkill_release)) {
231e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
232e5b75505Sopenharmony_ci				   "Unknown/unsupported wowlan trigger '%s'",
233e5b75505Sopenharmony_ci				   start);
234e5b75505Sopenharmony_ci			os_free(triggers);
235e5b75505Sopenharmony_ci			triggers = NULL;
236e5b75505Sopenharmony_ci			goto out;
237e5b75505Sopenharmony_ci		}
238e5b75505Sopenharmony_ci
239e5b75505Sopenharmony_ci		if (last)
240e5b75505Sopenharmony_ci			break;
241e5b75505Sopenharmony_ci		start = end + 1;
242e5b75505Sopenharmony_ci	}
243e5b75505Sopenharmony_ci#undef CHECK_TRIGGER
244e5b75505Sopenharmony_ci
245e5b75505Sopenharmony_ciout:
246e5b75505Sopenharmony_ci	os_free(buf);
247e5b75505Sopenharmony_ci	return triggers;
248e5b75505Sopenharmony_ci}
249e5b75505Sopenharmony_ci
250e5b75505Sopenharmony_ci
251e5b75505Sopenharmony_ciconst char * driver_flag_to_string(u64 flag)
252e5b75505Sopenharmony_ci{
253e5b75505Sopenharmony_ci#define DF2S(x) case WPA_DRIVER_FLAGS_ ## x: return #x
254e5b75505Sopenharmony_ci	switch (flag) {
255e5b75505Sopenharmony_ci	DF2S(DRIVER_IE);
256e5b75505Sopenharmony_ci	DF2S(SET_KEYS_AFTER_ASSOC);
257e5b75505Sopenharmony_ci	DF2S(DFS_OFFLOAD);
258e5b75505Sopenharmony_ci	DF2S(4WAY_HANDSHAKE_PSK);
259e5b75505Sopenharmony_ci	DF2S(4WAY_HANDSHAKE_8021X);
260e5b75505Sopenharmony_ci	DF2S(WIRED);
261e5b75505Sopenharmony_ci	DF2S(SME);
262e5b75505Sopenharmony_ci	DF2S(AP);
263e5b75505Sopenharmony_ci	DF2S(SET_KEYS_AFTER_ASSOC_DONE);
264e5b75505Sopenharmony_ci	DF2S(HT_2040_COEX);
265e5b75505Sopenharmony_ci	DF2S(P2P_CONCURRENT);
266e5b75505Sopenharmony_ci	DF2S(P2P_DEDICATED_INTERFACE);
267e5b75505Sopenharmony_ci	DF2S(P2P_CAPABLE);
268e5b75505Sopenharmony_ci	DF2S(AP_TEARDOWN_SUPPORT);
269e5b75505Sopenharmony_ci	DF2S(P2P_MGMT_AND_NON_P2P);
270e5b75505Sopenharmony_ci	DF2S(SANE_ERROR_CODES);
271e5b75505Sopenharmony_ci	DF2S(OFFCHANNEL_TX);
272e5b75505Sopenharmony_ci	DF2S(EAPOL_TX_STATUS);
273e5b75505Sopenharmony_ci	DF2S(DEAUTH_TX_STATUS);
274e5b75505Sopenharmony_ci	DF2S(BSS_SELECTION);
275e5b75505Sopenharmony_ci	DF2S(TDLS_SUPPORT);
276e5b75505Sopenharmony_ci	DF2S(TDLS_EXTERNAL_SETUP);
277e5b75505Sopenharmony_ci	DF2S(PROBE_RESP_OFFLOAD);
278e5b75505Sopenharmony_ci	DF2S(AP_UAPSD);
279e5b75505Sopenharmony_ci	DF2S(INACTIVITY_TIMER);
280e5b75505Sopenharmony_ci	DF2S(AP_MLME);
281e5b75505Sopenharmony_ci	DF2S(SAE);
282e5b75505Sopenharmony_ci	DF2S(OBSS_SCAN);
283e5b75505Sopenharmony_ci	DF2S(IBSS);
284e5b75505Sopenharmony_ci	DF2S(RADAR);
285e5b75505Sopenharmony_ci	DF2S(DEDICATED_P2P_DEVICE);
286e5b75505Sopenharmony_ci	DF2S(QOS_MAPPING);
287e5b75505Sopenharmony_ci	DF2S(AP_CSA);
288e5b75505Sopenharmony_ci	DF2S(MESH);
289e5b75505Sopenharmony_ci	DF2S(ACS_OFFLOAD);
290e5b75505Sopenharmony_ci	DF2S(KEY_MGMT_OFFLOAD);
291e5b75505Sopenharmony_ci	DF2S(TDLS_CHANNEL_SWITCH);
292e5b75505Sopenharmony_ci	DF2S(HT_IBSS);
293e5b75505Sopenharmony_ci	DF2S(VHT_IBSS);
294e5b75505Sopenharmony_ci	DF2S(SUPPORT_HW_MODE_ANY);
295e5b75505Sopenharmony_ci	DF2S(OFFCHANNEL_SIMULTANEOUS);
296e5b75505Sopenharmony_ci	DF2S(FULL_AP_CLIENT_STATE);
297e5b75505Sopenharmony_ci	DF2S(P2P_LISTEN_OFFLOAD);
298e5b75505Sopenharmony_ci	DF2S(SUPPORT_FILS);
299e5b75505Sopenharmony_ci	DF2S(BEACON_RATE_LEGACY);
300e5b75505Sopenharmony_ci	DF2S(BEACON_RATE_HT);
301e5b75505Sopenharmony_ci	DF2S(BEACON_RATE_VHT);
302e5b75505Sopenharmony_ci	DF2S(MGMT_TX_RANDOM_TA);
303e5b75505Sopenharmony_ci	DF2S(MGMT_TX_RANDOM_TA_CONNECTED);
304e5b75505Sopenharmony_ci	DF2S(SCHED_SCAN_RELATIVE_RSSI);
305e5b75505Sopenharmony_ci	DF2S(HE_CAPABILITIES);
306e5b75505Sopenharmony_ci	DF2S(FILS_SK_OFFLOAD);
307e5b75505Sopenharmony_ci	DF2S(OCE_STA);
308e5b75505Sopenharmony_ci	DF2S(OCE_AP);
309e5b75505Sopenharmony_ci	DF2S(OCE_STA_CFON);
310e5b75505Sopenharmony_ci	DF2S(MFP_OPTIONAL);
311e5b75505Sopenharmony_ci	}
312e5b75505Sopenharmony_ci	return "UNKNOWN";
313e5b75505Sopenharmony_ci#undef DF2S
314e5b75505Sopenharmony_ci}
315