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  
wpa_scan_results_free(struct wpa_scan_results * res)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  
event_to_string(enum wpa_event_type event)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(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  	E2S(UNPROT_BEACON);
93  	E2S(TX_WAIT_EXPIRE);
94  	E2S(BSS_COLOR_COLLISION);
95  	E2S(CCA_STARTED_NOTIFY);
96  	E2S(CCA_ABORTED_NOTIFY);
97  	E2S(CCA_NOTIFY);
98  	E2S(PASN_AUTH);
99  	E2S(LINK_CH_SWITCH);
100  	E2S(LINK_CH_SWITCH_STARTED);
101  	E2S(TID_LINK_MAP);
102  	E2S(LINK_RECONFIG);
103  	E2S(MLD_INTERFACE_FREED);
104  	}
105  
106  	return "UNKNOWN";
107  #undef E2S
108  }
109  
110  
channel_width_to_string(enum chan_width width)111  const char * channel_width_to_string(enum chan_width width)
112  {
113  	switch (width) {
114  	case CHAN_WIDTH_20_NOHT:
115  		return "20 MHz (no HT)";
116  	case CHAN_WIDTH_20:
117  		return "20 MHz";
118  	case CHAN_WIDTH_40:
119  		return "40 MHz";
120  	case CHAN_WIDTH_80:
121  		return "80 MHz";
122  	case CHAN_WIDTH_80P80:
123  		return "80+80 MHz";
124  	case CHAN_WIDTH_160:
125  		return "160 MHz";
126  	case CHAN_WIDTH_320:
127  		return "320 MHz";
128  	default:
129  		return "unknown";
130  	}
131  }
132  
133  
channel_width_to_int(enum chan_width width)134  int channel_width_to_int(enum chan_width width)
135  {
136  	switch (width) {
137  	case CHAN_WIDTH_20_NOHT:
138  	case CHAN_WIDTH_20:
139  		return 20;
140  	case CHAN_WIDTH_40:
141  		return 40;
142  	case CHAN_WIDTH_80:
143  		return 80;
144  	case CHAN_WIDTH_80P80:
145  	case CHAN_WIDTH_160:
146  		return 160;
147  	case CHAN_WIDTH_320:
148  		return 320;
149  	default:
150  		return 0;
151  	}
152  }
153  
154  
ht_supported(const struct hostapd_hw_modes * mode)155  int ht_supported(const struct hostapd_hw_modes *mode)
156  {
157  	if (!(mode->flags & HOSTAPD_MODE_FLAG_HT_INFO_KNOWN)) {
158  		/*
159  		 * The driver did not indicate whether it supports HT. Assume
160  		 * it does to avoid connection issues.
161  		 */
162  		return 1;
163  	}
164  
165  	/*
166  	 * IEEE Std 802.11n-2009 20.1.1:
167  	 * An HT non-AP STA shall support all EQM rates for one spatial stream.
168  	 */
169  	return mode->mcs_set[0] == 0xff;
170  }
171  
172  
vht_supported(const struct hostapd_hw_modes * mode)173  int vht_supported(const struct hostapd_hw_modes *mode)
174  {
175  	if (!(mode->flags & HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN)) {
176  		/*
177  		 * The driver did not indicate whether it supports VHT. Assume
178  		 * it does to avoid connection issues.
179  		 */
180  		return 1;
181  	}
182  
183  	/*
184  	 * A VHT non-AP STA shall support MCS 0-7 for one spatial stream.
185  	 * TODO: Verify if this complies with the standard
186  	 */
187  	return (mode->vht_mcs_set[0] & 0x3) != 3;
188  }
189  
190  
he_supported(const struct hostapd_hw_modes * hw_mode,enum ieee80211_op_mode op_mode)191  bool he_supported(const struct hostapd_hw_modes *hw_mode,
192  		  enum ieee80211_op_mode op_mode)
193  {
194  	if (!(hw_mode->flags & HOSTAPD_MODE_FLAG_HE_INFO_KNOWN)) {
195  		/*
196  		 * The driver did not indicate whether it supports HE. Assume
197  		 * it does to avoid connection issues.
198  		 */
199  		return true;
200  	}
201  
202  	return hw_mode->he_capab[op_mode].he_supported;
203  }
204  
205  
wpa_check_wowlan_trigger(const char * start,const char * trigger,int capa_trigger,u8 * param_trigger)206  static int wpa_check_wowlan_trigger(const char *start, const char *trigger,
207  				    int capa_trigger, u8 *param_trigger)
208  {
209  	if (os_strcmp(start, trigger) != 0)
210  		return 0;
211  	if (!capa_trigger)
212  		return 0;
213  
214  	*param_trigger = 1;
215  	return 1;
216  }
217  
218  
219  struct wowlan_triggers *
wpa_get_wowlan_triggers(const char * wowlan_triggers,const struct wpa_driver_capa * capa)220  wpa_get_wowlan_triggers(const char *wowlan_triggers,
221  			const struct wpa_driver_capa *capa)
222  {
223  	struct wowlan_triggers *triggers;
224  	char *start, *end, *buf;
225  	int last;
226  
227  	if (!wowlan_triggers)
228  		return NULL;
229  
230  	buf = os_strdup(wowlan_triggers);
231  	if (buf == NULL)
232  		return NULL;
233  
234  	triggers = os_zalloc(sizeof(*triggers));
235  	if (triggers == NULL)
236  		goto out;
237  
238  #define CHECK_TRIGGER(trigger) \
239  	wpa_check_wowlan_trigger(start, #trigger,			\
240  				  capa->wowlan_triggers.trigger,	\
241  				  &triggers->trigger)
242  
243  	start = buf;
244  	while (*start != '\0') {
245  		while (isblank((unsigned char) *start))
246  			start++;
247  		if (*start == '\0')
248  			break;
249  		end = start;
250  		while (!isblank((unsigned char) *end) && *end != '\0')
251  			end++;
252  		last = *end == '\0';
253  		*end = '\0';
254  
255  		if (!CHECK_TRIGGER(any) &&
256  		    !CHECK_TRIGGER(disconnect) &&
257  		    !CHECK_TRIGGER(magic_pkt) &&
258  		    !CHECK_TRIGGER(gtk_rekey_failure) &&
259  		    !CHECK_TRIGGER(eap_identity_req) &&
260  		    !CHECK_TRIGGER(four_way_handshake) &&
261  		    !CHECK_TRIGGER(rfkill_release)) {
262  			wpa_printf(MSG_DEBUG,
263  				   "Unknown/unsupported wowlan trigger '%s'",
264  				   start);
265  			os_free(triggers);
266  			triggers = NULL;
267  			goto out;
268  		}
269  
270  		if (last)
271  			break;
272  		start = end + 1;
273  	}
274  #undef CHECK_TRIGGER
275  
276  out:
277  	os_free(buf);
278  	return triggers;
279  }
280  
281  
driver_flag_to_string(u64 flag)282  const char * driver_flag_to_string(u64 flag)
283  {
284  #define DF2S(x) case WPA_DRIVER_FLAGS_ ## x: return #x
285  	switch (flag) {
286  	DF2S(DRIVER_IE);
287  	DF2S(SET_KEYS_AFTER_ASSOC);
288  	DF2S(DFS_OFFLOAD);
289  	DF2S(4WAY_HANDSHAKE_PSK);
290  	DF2S(4WAY_HANDSHAKE_8021X);
291  	DF2S(WIRED);
292  	DF2S(SME);
293  	DF2S(AP);
294  	DF2S(SET_KEYS_AFTER_ASSOC_DONE);
295  	DF2S(HT_2040_COEX);
296  	DF2S(P2P_CONCURRENT);
297  	DF2S(P2P_DEDICATED_INTERFACE);
298  	DF2S(P2P_CAPABLE);
299  	DF2S(AP_TEARDOWN_SUPPORT);
300  	DF2S(P2P_MGMT_AND_NON_P2P);
301  	DF2S(VALID_ERROR_CODES);
302  	DF2S(OFFCHANNEL_TX);
303  	DF2S(EAPOL_TX_STATUS);
304  	DF2S(DEAUTH_TX_STATUS);
305  	DF2S(BSS_SELECTION);
306  	DF2S(TDLS_SUPPORT);
307  	DF2S(TDLS_EXTERNAL_SETUP);
308  	DF2S(PROBE_RESP_OFFLOAD);
309  	DF2S(AP_UAPSD);
310  	DF2S(INACTIVITY_TIMER);
311  	DF2S(AP_MLME);
312  	DF2S(SAE);
313  	DF2S(OBSS_SCAN);
314  	DF2S(IBSS);
315  	DF2S(RADAR);
316  	DF2S(DEDICATED_P2P_DEVICE);
317  	DF2S(QOS_MAPPING);
318  	DF2S(AP_CSA);
319  	DF2S(MESH);
320  	DF2S(ACS_OFFLOAD);
321  	DF2S(KEY_MGMT_OFFLOAD);
322  	DF2S(TDLS_CHANNEL_SWITCH);
323  	DF2S(HT_IBSS);
324  	DF2S(VHT_IBSS);
325  	DF2S(SUPPORT_HW_MODE_ANY);
326  	DF2S(OFFCHANNEL_SIMULTANEOUS);
327  	DF2S(FULL_AP_CLIENT_STATE);
328  	DF2S(P2P_LISTEN_OFFLOAD);
329  	DF2S(SUPPORT_FILS);
330  	DF2S(BEACON_RATE_LEGACY);
331  	DF2S(BEACON_RATE_HT);
332  	DF2S(BEACON_RATE_VHT);
333  	DF2S(MGMT_TX_RANDOM_TA);
334  	DF2S(MGMT_TX_RANDOM_TA_CONNECTED);
335  	DF2S(SCHED_SCAN_RELATIVE_RSSI);
336  	DF2S(HE_CAPABILITIES);
337  	DF2S(FILS_SK_OFFLOAD);
338  	DF2S(OCE_STA);
339  	DF2S(OCE_AP);
340  	DF2S(OCE_STA_CFON);
341  	DF2S(MFP_OPTIONAL);
342  	DF2S(SELF_MANAGED_REGULATORY);
343  	DF2S(FTM_RESPONDER);
344  	DF2S(CONTROL_PORT);
345  	DF2S(VLAN_OFFLOAD);
346  	DF2S(UPDATE_FT_IES);
347  	DF2S(SAFE_PTK0_REKEYS);
348  	DF2S(BEACON_PROTECTION);
349  	DF2S(EXTENDED_KEY_ID);
350  	}
351  	return "UNKNOWN";
352  #undef DF2S
353  }
354  
355  
driver_flag2_to_string(u64 flag2)356  const char * driver_flag2_to_string(u64 flag2)
357  {
358  #define DF2S(x) case WPA_DRIVER_FLAGS2_ ## x: return #x
359  	switch (flag2) {
360  	DF2S(CONTROL_PORT_RX);
361  	DF2S(CONTROL_PORT_TX_STATUS);
362  	DF2S(SEC_LTF_AP);
363  	DF2S(SEC_RTT_AP);
364  	DF2S(PROT_RANGE_NEG_AP);
365  	DF2S(BEACON_RATE_HE);
366  	DF2S(BEACON_PROTECTION_CLIENT);
367  	DF2S(OCV);
368  	DF2S(AP_SME);
369  	DF2S(SA_QUERY_OFFLOAD_AP);
370  	DF2S(RADAR_BACKGROUND);
371  	DF2S(SEC_LTF_STA);
372  	DF2S(SEC_RTT_STA);
373  	DF2S(PROT_RANGE_NEG_STA);
374  	DF2S(MLO);
375  	DF2S(SCAN_MIN_PREQ);
376  	DF2S(SAE_OFFLOAD_STA);
377  	DF2S(SPP_AMSDU);
378  	}
379  	return "UNKNOWN";
380  #undef DF2S
381  }
382