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