xref: /freebsd/contrib/wpa/src/ap/ctrl_iface_ap.c (revision 71e72c9e91c4b8007a4292e09669e8b549c29e97)
1 /*
2  * Control interface for shared AP commands
3  * Copyright (c) 2004-2019, 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 "utils/includes.h"
10 
11 #include "utils/common.h"
12 #include "common/ieee802_11_defs.h"
13 #include "common/sae.h"
14 #include "common/hw_features_common.h"
15 #include "eapol_auth/eapol_auth_sm.h"
16 #include "fst/fst_ctrl_iface.h"
17 #include "hostapd.h"
18 #include "ieee802_1x.h"
19 #include "wpa_auth.h"
20 #include "ieee802_11.h"
21 #include "sta_info.h"
22 #include "wps_hostapd.h"
23 #include "p2p_hostapd.h"
24 #include "ctrl_iface_ap.h"
25 #include "ap_drv_ops.h"
26 #include "mbo_ap.h"
27 #include "taxonomy.h"
28 #include "wnm_ap.h"
29 
30 
hostapd_write_ht_mcs_bitmask(char * buf,size_t buflen,size_t curr_len,const u8 * mcs_set)31 static size_t hostapd_write_ht_mcs_bitmask(char *buf, size_t buflen,
32 					   size_t curr_len, const u8 *mcs_set)
33 {
34 	int ret;
35 	size_t len = curr_len;
36 
37 	ret = os_snprintf(buf + len, buflen - len,
38 			  "ht_mcs_bitmask=");
39 	if (os_snprintf_error(buflen - len, ret))
40 		return len;
41 	len += ret;
42 
43 	/* 77 first bits (+ 3 reserved bits) */
44 	len += wpa_snprintf_hex(buf + len, buflen - len, mcs_set, 10);
45 
46 	ret = os_snprintf(buf + len, buflen - len, "\n");
47 	if (os_snprintf_error(buflen - len, ret))
48 		return curr_len;
49 	len += ret;
50 
51 	return len;
52 }
53 
54 
hostapd_get_sta_conn_time(struct sta_info * sta,struct hostap_sta_driver_data * data,char * buf,size_t buflen)55 static int hostapd_get_sta_conn_time(struct sta_info *sta,
56 				     struct hostap_sta_driver_data *data,
57 				     char *buf, size_t buflen)
58 {
59 	struct os_reltime age;
60 	unsigned long secs;
61 	int ret;
62 
63 	if (sta->connected_time.sec) {
64 		/* Locally maintained time in AP mode */
65 		os_reltime_age(&sta->connected_time, &age);
66 		secs = (unsigned long) age.sec;
67 	} else if (data->flags & STA_DRV_DATA_CONN_TIME) {
68 		/* Time from the driver in mesh mode */
69 		secs = data->connected_sec;
70 	} else {
71 		return 0;
72 	}
73 
74 	ret = os_snprintf(buf, buflen, "connected_time=%lu\n", secs);
75 	if (os_snprintf_error(buflen, ret))
76 		return 0;
77 	return ret;
78 }
79 
80 
hostapd_get_sta_info(struct hostapd_data * hapd,struct sta_info * sta,char * buf,size_t buflen)81 static int hostapd_get_sta_info(struct hostapd_data *hapd,
82 				struct sta_info *sta,
83 				char *buf, size_t buflen)
84 {
85 	struct hostap_sta_driver_data data;
86 	int ret;
87 	int len = 0;
88 
89 	if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
90 		return 0;
91 
92 	ret = os_snprintf(buf, buflen, "rx_packets=%lu\ntx_packets=%lu\n"
93 			  "rx_bytes=%llu\ntx_bytes=%llu\ninactive_msec=%lu\n"
94 			  "signal=%d\n",
95 			  data.rx_packets, data.tx_packets,
96 			  data.rx_bytes, data.tx_bytes, data.inactive_msec,
97 			  data.signal);
98 	if (os_snprintf_error(buflen, ret))
99 		return 0;
100 	len += ret;
101 
102 	ret = os_snprintf(buf + len, buflen - len, "rx_rate_info=%lu",
103 			  data.current_rx_rate / 100);
104 	if (os_snprintf_error(buflen - len, ret))
105 		return len;
106 	len += ret;
107 	if (data.flags & STA_DRV_DATA_RX_MCS) {
108 		ret = os_snprintf(buf + len, buflen - len, " mcs %u",
109 				  data.rx_mcs);
110 		if (!os_snprintf_error(buflen - len, ret))
111 			len += ret;
112 	}
113 	if (data.flags & STA_DRV_DATA_RX_VHT_MCS) {
114 		ret = os_snprintf(buf + len, buflen - len, " vhtmcs %u",
115 				  data.rx_vhtmcs);
116 		if (!os_snprintf_error(buflen - len, ret))
117 			len += ret;
118 	}
119 	if (data.flags & STA_DRV_DATA_RX_VHT_NSS) {
120 		ret = os_snprintf(buf + len, buflen - len, " vhtnss %u",
121 				  data.rx_vht_nss);
122 		if (!os_snprintf_error(buflen - len, ret))
123 			len += ret;
124 	}
125 	if (data.flags & STA_DRV_DATA_RX_SHORT_GI) {
126 		ret = os_snprintf(buf + len, buflen - len, " shortGI");
127 		if (!os_snprintf_error(buflen - len, ret))
128 			len += ret;
129 	}
130 	ret = os_snprintf(buf + len, buflen - len, "\n");
131 	if (!os_snprintf_error(buflen - len, ret))
132 		len += ret;
133 
134 	ret = os_snprintf(buf + len, buflen - len, "tx_rate_info=%lu",
135 			  data.current_tx_rate / 100);
136 	if (os_snprintf_error(buflen - len, ret))
137 		return len;
138 	len += ret;
139 	if (data.flags & STA_DRV_DATA_TX_MCS) {
140 		ret = os_snprintf(buf + len, buflen - len, " mcs %u",
141 				  data.tx_mcs);
142 		if (!os_snprintf_error(buflen - len, ret))
143 			len += ret;
144 	}
145 	if (data.flags & STA_DRV_DATA_TX_VHT_MCS) {
146 		ret = os_snprintf(buf + len, buflen - len, " vhtmcs %u",
147 				  data.tx_vhtmcs);
148 		if (!os_snprintf_error(buflen - len, ret))
149 			len += ret;
150 	}
151 	if (data.flags & STA_DRV_DATA_TX_VHT_NSS) {
152 		ret = os_snprintf(buf + len, buflen - len, " vhtnss %u",
153 				  data.tx_vht_nss);
154 		if (!os_snprintf_error(buflen - len, ret))
155 			len += ret;
156 	}
157 	if (data.flags & STA_DRV_DATA_TX_SHORT_GI) {
158 		ret = os_snprintf(buf + len, buflen - len, " shortGI");
159 		if (!os_snprintf_error(buflen - len, ret))
160 			len += ret;
161 	}
162 	ret = os_snprintf(buf + len, buflen - len, "\n");
163 	if (!os_snprintf_error(buflen - len, ret))
164 		len += ret;
165 
166 	if ((sta->flags & WLAN_STA_VHT) && sta->vht_capabilities) {
167 		ret = os_snprintf(buf + len, buflen - len,
168 				  "rx_vht_mcs_map=%04x\n"
169 				  "tx_vht_mcs_map=%04x\n",
170 				  le_to_host16(sta->vht_capabilities->
171 					       vht_supported_mcs_set.rx_map),
172 				  le_to_host16(sta->vht_capabilities->
173 					       vht_supported_mcs_set.tx_map));
174 		if (!os_snprintf_error(buflen - len, ret))
175 			len += ret;
176 	}
177 
178 	if ((sta->flags & WLAN_STA_HT) && sta->ht_capabilities) {
179 		len = hostapd_write_ht_mcs_bitmask(buf, buflen, len,
180 						   sta->ht_capabilities->
181 						   supported_mcs_set);
182 	}
183 
184 	if (data.flags & STA_DRV_DATA_LAST_ACK_RSSI) {
185 		ret = os_snprintf(buf + len, buflen - len,
186 				  "last_ack_signal=%d\n", data.last_ack_rssi);
187 		if (!os_snprintf_error(buflen - len, ret))
188 			len += ret;
189 	}
190 
191 	len += hostapd_get_sta_conn_time(sta, &data, buf + len, buflen - len);
192 
193 	return len;
194 }
195 
196 
timeout_next_str(int val)197 static const char * timeout_next_str(int val)
198 {
199 	switch (val) {
200 	case STA_NULLFUNC:
201 		return "NULLFUNC POLL";
202 	case STA_DISASSOC:
203 		return "DISASSOC";
204 	case STA_DEAUTH:
205 		return "DEAUTH";
206 	case STA_REMOVE:
207 		return "REMOVE";
208 	case STA_DISASSOC_FROM_CLI:
209 		return "DISASSOC_FROM_CLI";
210 	default:
211 		return "?";
212 	}
213 }
214 
215 
hw_mode_str(enum hostapd_hw_mode mode)216 static const char * hw_mode_str(enum hostapd_hw_mode mode)
217 {
218 	switch (mode) {
219 	case HOSTAPD_MODE_IEEE80211B:
220 		return "b";
221 	case HOSTAPD_MODE_IEEE80211G:
222 		return "g";
223 	case HOSTAPD_MODE_IEEE80211A:
224 		return "a";
225 	case HOSTAPD_MODE_IEEE80211AD:
226 		return "ad";
227 	case HOSTAPD_MODE_IEEE80211ANY:
228 		return "any";
229 	case NUM_HOSTAPD_MODES:
230 		return "invalid";
231 	}
232 	return "unknown";
233 }
234 
235 
hostapd_ctrl_iface_sta_mib(struct hostapd_data * hapd,struct sta_info * sta,char * buf,size_t buflen)236 static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
237 				      struct sta_info *sta,
238 				      char *buf, size_t buflen)
239 {
240 	int len, res, ret, i;
241 	const char *keyid;
242 	const u8 *dpp_pkhash;
243 
244 	if (!sta)
245 		return 0;
246 
247 	len = 0;
248 	ret = os_snprintf(buf + len, buflen - len, MACSTR "\nflags=",
249 			  MAC2STR(sta->addr));
250 	if (os_snprintf_error(buflen - len, ret))
251 		return len;
252 	len += ret;
253 
254 	ret = ap_sta_flags_txt(sta->flags, buf + len, buflen - len);
255 	if (ret < 0)
256 		return len;
257 	len += ret;
258 
259 	ret = os_snprintf(buf + len, buflen - len, "\naid=%d\ncapability=0x%x\n"
260 			  "listen_interval=%d\nsupported_rates=",
261 			  sta->aid, sta->capability, sta->listen_interval);
262 	if (os_snprintf_error(buflen - len, ret))
263 		return len;
264 	len += ret;
265 
266 	for (i = 0; i < sta->supported_rates_len; i++) {
267 		ret = os_snprintf(buf + len, buflen - len, "%02x%s",
268 				  sta->supported_rates[i],
269 				  i + 1 < sta->supported_rates_len ? " " : "");
270 		if (os_snprintf_error(buflen - len, ret))
271 			return len;
272 		len += ret;
273 	}
274 
275 	ret = os_snprintf(buf + len, buflen - len, "\ntimeout_next=%s\n",
276 			  timeout_next_str(sta->timeout_next));
277 	if (os_snprintf_error(buflen - len, ret))
278 		return len;
279 	len += ret;
280 
281 	if (sta->max_idle_period) {
282 		ret = os_snprintf(buf + len, buflen - len,
283 				  "max_idle_period=%d\n", sta->max_idle_period);
284 		if (os_snprintf_error(buflen - len, ret))
285 			return len;
286 		len += ret;
287 	}
288 
289 	res = ieee802_11_get_mib_sta(hapd, sta, buf + len, buflen - len);
290 	if (res >= 0)
291 		len += res;
292 	res = wpa_get_mib_sta(sta->wpa_sm, buf + len, buflen - len);
293 	if (res >= 0)
294 		len += res;
295 	res = ieee802_1x_get_mib_sta(hapd, sta, buf + len, buflen - len);
296 	if (res >= 0)
297 		len += res;
298 	res = hostapd_wps_get_mib_sta(hapd, sta->addr, buf + len,
299 				      buflen - len);
300 	if (res >= 0)
301 		len += res;
302 	res = hostapd_p2p_get_mib_sta(hapd, sta, buf + len, buflen - len);
303 	if (res >= 0)
304 		len += res;
305 
306 	len += hostapd_get_sta_info(hapd, sta, buf + len, buflen - len);
307 
308 #ifdef CONFIG_SAE
309 	if (sta->sae && sta->sae->state == SAE_ACCEPTED) {
310 		res = os_snprintf(buf + len, buflen - len, "sae_group=%d\n",
311 				  sta->sae->group);
312 		if (!os_snprintf_error(buflen - len, res))
313 			len += res;
314 	}
315 
316 	if (sta->sae && sta->sae->tmp) {
317 		const u8 *pos;
318 		unsigned int j, count;
319 		struct wpabuf *groups = sta->sae->tmp->peer_rejected_groups;
320 
321 		res = os_snprintf(buf + len, buflen - len,
322 				  "sae_rejected_groups=");
323 		if (!os_snprintf_error(buflen - len, res))
324 			len += res;
325 
326 		if (groups) {
327 			pos = wpabuf_head(groups);
328 			count = wpabuf_len(groups) / 2;
329 		} else {
330 			pos = NULL;
331 			count = 0;
332 		}
333 		for (j = 0; pos && j < count; j++) {
334 			res = os_snprintf(buf + len, buflen - len, "%s%d",
335 					  j == 0 ? "" : " ", WPA_GET_LE16(pos));
336 			if (!os_snprintf_error(buflen - len, res))
337 				len += res;
338 			pos += 2;
339 		}
340 
341 		res = os_snprintf(buf + len, buflen - len, "\n");
342 		if (!os_snprintf_error(buflen - len, res))
343 			len += res;
344 	}
345 #endif /* CONFIG_SAE */
346 
347 	if (sta->vlan_id > 0) {
348 		res = os_snprintf(buf + len, buflen - len, "vlan_id=%d\n",
349 				  sta->vlan_id);
350 		if (!os_snprintf_error(buflen - len, res))
351 			len += res;
352 	}
353 
354 	res = mbo_ap_get_info(sta, buf + len, buflen - len);
355 	if (res >= 0)
356 		len += res;
357 
358 	if (sta->supp_op_classes &&
359 	    buflen - len > (unsigned) (17 + 2 * sta->supp_op_classes[0])) {
360 		res = os_snprintf(buf + len, buflen - len, "supp_op_classes=");
361 		if (!os_snprintf_error(buflen - len, res))
362 			len += res;
363 		len += wpa_snprintf_hex(buf + len, buflen - len,
364 					sta->supp_op_classes + 1,
365 					sta->supp_op_classes[0]);
366 		res = os_snprintf(buf + len, buflen - len, "\n");
367 		if (!os_snprintf_error(buflen - len, res))
368 			len += res;
369 	}
370 
371 	if (sta->power_capab) {
372 		ret = os_snprintf(buf + len, buflen - len,
373 				  "min_txpower=%d\n"
374 				  "max_txpower=%d\n",
375 				  sta->min_tx_power, sta->max_tx_power);
376 		if (!os_snprintf_error(buflen - len, ret))
377 			len += ret;
378 	}
379 
380 #ifdef CONFIG_IEEE80211AX
381 	if ((sta->flags & WLAN_STA_HE) && sta->he_capab) {
382 		res = os_snprintf(buf + len, buflen - len, "he_capab=");
383 		if (!os_snprintf_error(buflen - len, res))
384 			len += res;
385 		len += wpa_snprintf_hex(buf + len, buflen - len,
386 					(const u8 *) sta->he_capab,
387 					sta->he_capab_len);
388 		res = os_snprintf(buf + len, buflen - len, "\n");
389 		if (!os_snprintf_error(buflen - len, res))
390 			len += res;
391 	}
392 #endif /* CONFIG_IEEE80211AX */
393 
394 #ifdef CONFIG_IEEE80211BE
395 	if ((sta->flags & WLAN_STA_EHT) && sta->eht_capab) {
396 		res = os_snprintf(buf + len, buflen - len, "eht_capab=");
397 		if (!os_snprintf_error(buflen - len, res))
398 			len += res;
399 		len += wpa_snprintf_hex(buf + len, buflen - len,
400 					(const u8 *) sta->eht_capab,
401 					sta->eht_capab_len);
402 		res = os_snprintf(buf + len, buflen - len, "\n");
403 		if (!os_snprintf_error(buflen - len, res))
404 			len += res;
405 	}
406 #endif /* CONFIG_IEEE80211BE */
407 
408 #ifdef CONFIG_IEEE80211AC
409 	if ((sta->flags & WLAN_STA_VHT) && sta->vht_capabilities) {
410 		res = os_snprintf(buf + len, buflen - len,
411 				  "vht_caps_info=0x%08x\n",
412 				  le_to_host32(sta->vht_capabilities->
413 					       vht_capabilities_info));
414 		if (!os_snprintf_error(buflen - len, res))
415 			len += res;
416 
417 		res = os_snprintf(buf + len, buflen - len, "vht_capab=");
418 		if (!os_snprintf_error(buflen - len, res))
419 			len += res;
420 		len += wpa_snprintf_hex(buf + len, buflen - len,
421 					(const u8 *) sta->vht_capabilities,
422 					sizeof(*sta->vht_capabilities));
423 		res = os_snprintf(buf + len, buflen - len, "\n");
424 		if (!os_snprintf_error(buflen - len, res))
425 			len += res;
426 	}
427 #endif /* CONFIG_IEEE80211AC */
428 
429 	if ((sta->flags & WLAN_STA_HT) && sta->ht_capabilities) {
430 		res = os_snprintf(buf + len, buflen - len,
431 				  "ht_caps_info=0x%04x\n",
432 				  le_to_host16(sta->ht_capabilities->
433 					       ht_capabilities_info));
434 		if (!os_snprintf_error(buflen - len, res))
435 			len += res;
436 	}
437 
438 	if (sta->ext_capability &&
439 	    buflen - len > (unsigned) (11 + 2 * sta->ext_capability[0])) {
440 		res = os_snprintf(buf + len, buflen - len, "ext_capab=");
441 		if (!os_snprintf_error(buflen - len, res))
442 			len += res;
443 		len += wpa_snprintf_hex(buf + len, buflen - len,
444 					sta->ext_capability + 1,
445 					sta->ext_capability[0]);
446 		res = os_snprintf(buf + len, buflen - len, "\n");
447 		if (!os_snprintf_error(buflen - len, res))
448 			len += res;
449 	}
450 
451 	if (sta->flags & WLAN_STA_WDS && sta->ifname_wds) {
452 		ret = os_snprintf(buf + len, buflen - len,
453 				  "wds_sta_ifname=%s\n", sta->ifname_wds);
454 		if (!os_snprintf_error(buflen - len, ret))
455 			len += ret;
456 	}
457 
458 	keyid = ap_sta_wpa_get_keyid(hapd, sta);
459 	if (keyid) {
460 		ret = os_snprintf(buf + len, buflen - len, "keyid=%s\n", keyid);
461 		if (!os_snprintf_error(buflen - len, ret))
462 			len += ret;
463 	}
464 
465 	dpp_pkhash = ap_sta_wpa_get_dpp_pkhash(hapd, sta);
466 	if (dpp_pkhash) {
467 		ret = os_snprintf(buf + len, buflen - len, "dpp_pkhash=");
468 		if (!os_snprintf_error(buflen - len, ret))
469 			len += ret;
470 		len += wpa_snprintf_hex(buf + len, buflen - len, dpp_pkhash,
471 					SHA256_MAC_LEN);
472 		ret = os_snprintf(buf + len, buflen - len, "\n");
473 		if (!os_snprintf_error(buflen - len, ret))
474 			len += ret;
475 	}
476 
477 #ifdef CONFIG_IEEE80211BE
478 	if (sta->mld_info.mld_sta) {
479 		u16 mld_sta_capa = sta->mld_info.common_info.mld_capa;
480 		u8 max_simul_links = mld_sta_capa &
481 			EHT_ML_MLD_CAPA_MAX_NUM_SIM_LINKS_MASK;
482 
483 		for (i = 0; i < MAX_NUM_MLD_LINKS; ++i) {
484 			if (!sta->mld_info.links[i].valid)
485 				continue;
486 			ret = os_snprintf(
487 				buf + len, buflen - len,
488 				"peer_addr[%d]=" MACSTR "\n",
489 				i, MAC2STR(sta->mld_info.links[i].peer_addr));
490 			if (!os_snprintf_error(buflen - len, ret))
491 				len += ret;
492 		}
493 
494 		ret = os_snprintf(buf + len, buflen - len,
495 				  "max_simul_links=%d\n", max_simul_links);
496 		if (!os_snprintf_error(buflen - len, ret))
497 			len += ret;
498 	}
499 #endif /* CONFIG_IEEE80211BE */
500 
501 	return len;
502 }
503 
504 
hostapd_ctrl_iface_sta_first(struct hostapd_data * hapd,char * buf,size_t buflen)505 int hostapd_ctrl_iface_sta_first(struct hostapd_data *hapd,
506 				 char *buf, size_t buflen)
507 {
508 	return hostapd_ctrl_iface_sta_mib(hapd, hapd->sta_list, buf, buflen);
509 }
510 
511 
hostapd_ctrl_iface_sta(struct hostapd_data * hapd,const char * txtaddr,char * buf,size_t buflen)512 int hostapd_ctrl_iface_sta(struct hostapd_data *hapd, const char *txtaddr,
513 			   char *buf, size_t buflen)
514 {
515 	u8 addr[ETH_ALEN];
516 	int ret;
517 	const char *pos;
518 	struct sta_info *sta;
519 
520 	if (hwaddr_aton(txtaddr, addr)) {
521 		ret = os_snprintf(buf, buflen, "FAIL\n");
522 		if (os_snprintf_error(buflen, ret))
523 			return 0;
524 		return ret;
525 	}
526 
527 	sta = ap_get_sta(hapd, addr);
528 	if (sta == NULL)
529 		return -1;
530 
531 	pos = os_strchr(txtaddr, ' ');
532 	if (pos) {
533 		pos++;
534 
535 #ifdef HOSTAPD_DUMP_STATE
536 		if (os_strcmp(pos, "eapol") == 0) {
537 			if (sta->eapol_sm == NULL)
538 				return -1;
539 			return eapol_auth_dump_state(sta->eapol_sm, buf,
540 						     buflen);
541 		}
542 #endif /* HOSTAPD_DUMP_STATE */
543 
544 		return -1;
545 	}
546 
547 	ret = hostapd_ctrl_iface_sta_mib(hapd, sta, buf, buflen);
548 	ret += fst_ctrl_iface_mb_info(addr, buf + ret, buflen - ret);
549 
550 	return ret;
551 }
552 
553 
hostapd_ctrl_iface_sta_next(struct hostapd_data * hapd,const char * txtaddr,char * buf,size_t buflen)554 int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr,
555 				char *buf, size_t buflen)
556 {
557 	u8 addr[ETH_ALEN];
558 	struct sta_info *sta;
559 	int ret;
560 
561 	if (hwaddr_aton(txtaddr, addr) ||
562 	    (sta = ap_get_sta(hapd, addr)) == NULL) {
563 		ret = os_snprintf(buf, buflen, "FAIL\n");
564 		if (os_snprintf_error(buflen, ret))
565 			return 0;
566 		return ret;
567 	}
568 
569 	if (!sta->next)
570 		return 0;
571 
572 	return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen);
573 }
574 
575 
576 #ifdef CONFIG_P2P_MANAGER
p2p_manager_disconnect(struct hostapd_data * hapd,u16 stype,u8 minor_reason_code,const u8 * addr)577 static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype,
578 				  u8 minor_reason_code, const u8 *addr)
579 {
580 	struct ieee80211_mgmt *mgmt;
581 	int ret;
582 	u8 *pos;
583 
584 	mgmt = os_zalloc(sizeof(*mgmt) + 100);
585 	if (mgmt == NULL)
586 		return -1;
587 
588 	mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype);
589 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "P2P: Disconnect STA " MACSTR
590 		" with minor reason code %u (stype=%u (%s))",
591 		MAC2STR(addr), minor_reason_code, stype,
592 		fc2str(le_to_host16(mgmt->frame_control)));
593 
594 	os_memcpy(mgmt->da, addr, ETH_ALEN);
595 	os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
596 	os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
597 	if (stype == WLAN_FC_STYPE_DEAUTH) {
598 		mgmt->u.deauth.reason_code =
599 			host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
600 		pos = mgmt->u.deauth.variable;
601 	} else {
602 		mgmt->u.disassoc.reason_code =
603 			host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
604 		pos = mgmt->u.disassoc.variable;
605 	}
606 
607 	*pos++ = WLAN_EID_VENDOR_SPECIFIC;
608 	*pos++ = 4 + 3 + 1;
609 	WPA_PUT_BE32(pos, P2P_IE_VENDOR_TYPE);
610 	pos += 4;
611 
612 	*pos++ = P2P_ATTR_MINOR_REASON_CODE;
613 	WPA_PUT_LE16(pos, 1);
614 	pos += 2;
615 	*pos++ = minor_reason_code;
616 
617 	ret = hostapd_drv_send_mlme(hapd, mgmt, pos - (u8 *) mgmt, 0, NULL, 0,
618 				    0);
619 	os_free(mgmt);
620 
621 	return ret < 0 ? -1 : 0;
622 }
623 #endif /* CONFIG_P2P_MANAGER */
624 
625 
hostapd_ctrl_iface_deauthenticate(struct hostapd_data * hapd,const char * txtaddr)626 int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
627 				      const char *txtaddr)
628 {
629 	u8 addr[ETH_ALEN];
630 	struct sta_info *sta;
631 	const char *pos;
632 	u16 reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
633 
634 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DEAUTHENTICATE %s",
635 		txtaddr);
636 
637 	if (hwaddr_aton(txtaddr, addr))
638 		return -1;
639 
640 	pos = os_strstr(txtaddr, " reason=");
641 	if (pos)
642 		reason = atoi(pos + 8);
643 
644 	pos = os_strstr(txtaddr, " test=");
645 	if (pos) {
646 		struct ieee80211_mgmt mgmt;
647 		int encrypt;
648 
649 		pos += 6;
650 		encrypt = atoi(pos);
651 		os_memset(&mgmt, 0, sizeof(mgmt));
652 		mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
653 						  WLAN_FC_STYPE_DEAUTH);
654 		os_memcpy(mgmt.da, addr, ETH_ALEN);
655 		os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
656 		os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
657 		mgmt.u.deauth.reason_code = host_to_le16(reason);
658 		if (hostapd_drv_send_mlme(hapd, (u8 *) &mgmt,
659 					  IEEE80211_HDRLEN +
660 					  sizeof(mgmt.u.deauth),
661 					  0, NULL, 0, !encrypt) < 0)
662 			return -1;
663 		return 0;
664 	}
665 
666 #ifdef CONFIG_P2P_MANAGER
667 	pos = os_strstr(txtaddr, " p2p=");
668 	if (pos) {
669 		return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DEAUTH,
670 					      atoi(pos + 5), addr);
671 	}
672 #endif /* CONFIG_P2P_MANAGER */
673 
674 	sta = ap_get_sta(hapd, addr);
675 	if (os_strstr(txtaddr, " tx=0")) {
676 		hostapd_drv_sta_remove(hapd, addr);
677 		if (sta)
678 			ap_free_sta(hapd, sta);
679 	} else {
680 		hostapd_drv_sta_deauth(hapd, addr, reason);
681 		if (sta)
682 			ap_sta_deauthenticate(hapd, sta, reason);
683 		else if (addr[0] == 0xff)
684 			hostapd_free_stas(hapd);
685 	}
686 
687 	return 0;
688 }
689 
690 
hostapd_ctrl_iface_disassociate(struct hostapd_data * hapd,const char * txtaddr)691 int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
692 				    const char *txtaddr)
693 {
694 	u8 addr[ETH_ALEN];
695 	struct sta_info *sta;
696 	const char *pos;
697 	u16 reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
698 
699 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s",
700 		txtaddr);
701 
702 	if (hwaddr_aton(txtaddr, addr))
703 		return -1;
704 
705 	pos = os_strstr(txtaddr, " reason=");
706 	if (pos)
707 		reason = atoi(pos + 8);
708 
709 	pos = os_strstr(txtaddr, " test=");
710 	if (pos) {
711 		struct ieee80211_mgmt mgmt;
712 		int encrypt;
713 
714 		pos += 6;
715 		encrypt = atoi(pos);
716 		os_memset(&mgmt, 0, sizeof(mgmt));
717 		mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
718 						  WLAN_FC_STYPE_DISASSOC);
719 		os_memcpy(mgmt.da, addr, ETH_ALEN);
720 		os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
721 		os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
722 		mgmt.u.disassoc.reason_code = host_to_le16(reason);
723 		if (hostapd_drv_send_mlme(hapd, (u8 *) &mgmt,
724 					  IEEE80211_HDRLEN +
725 					  sizeof(mgmt.u.deauth),
726 					  0, NULL, 0, !encrypt) < 0)
727 			return -1;
728 		return 0;
729 	}
730 
731 #ifdef CONFIG_P2P_MANAGER
732 	pos = os_strstr(txtaddr, " p2p=");
733 	if (pos) {
734 		return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DISASSOC,
735 					      atoi(pos + 5), addr);
736 	}
737 #endif /* CONFIG_P2P_MANAGER */
738 
739 	sta = ap_get_sta(hapd, addr);
740 	if (os_strstr(txtaddr, " tx=0")) {
741 		hostapd_drv_sta_remove(hapd, addr);
742 		if (sta)
743 			ap_free_sta(hapd, sta);
744 	} else {
745 		hostapd_drv_sta_disassoc(hapd, addr, reason);
746 		if (sta)
747 			ap_sta_disassociate(hapd, sta, reason);
748 		else if (addr[0] == 0xff)
749 			hostapd_free_stas(hapd);
750 	}
751 
752 	return 0;
753 }
754 
755 
756 #ifdef CONFIG_TAXONOMY
hostapd_ctrl_iface_signature(struct hostapd_data * hapd,const char * txtaddr,char * buf,size_t buflen)757 int hostapd_ctrl_iface_signature(struct hostapd_data *hapd,
758 				 const char *txtaddr,
759 				 char *buf, size_t buflen)
760 {
761 	u8 addr[ETH_ALEN];
762 	struct sta_info *sta;
763 
764 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE SIGNATURE %s", txtaddr);
765 
766 	if (hwaddr_aton(txtaddr, addr))
767 		return -1;
768 
769 	sta = ap_get_sta(hapd, addr);
770 	if (!sta)
771 		return -1;
772 
773 	return retrieve_sta_taxonomy(hapd, sta, buf, buflen);
774 }
775 #endif /* CONFIG_TAXONOMY */
776 
777 
hostapd_ctrl_iface_poll_sta(struct hostapd_data * hapd,const char * txtaddr)778 int hostapd_ctrl_iface_poll_sta(struct hostapd_data *hapd,
779 				const char *txtaddr)
780 {
781 	u8 addr[ETH_ALEN];
782 	struct sta_info *sta;
783 
784 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE POLL_STA %s", txtaddr);
785 
786 	if (hwaddr_aton(txtaddr, addr))
787 		return -1;
788 
789 	sta = ap_get_sta(hapd, addr);
790 	if (!sta)
791 		return -1;
792 
793 	hostapd_drv_poll_client(hapd, hapd->own_addr, addr,
794 				sta->flags & WLAN_STA_WMM);
795 	return 0;
796 }
797 
798 
hostapd_ctrl_iface_status(struct hostapd_data * hapd,char * buf,size_t buflen)799 int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
800 			      size_t buflen)
801 {
802 	struct hostapd_iface *iface = hapd->iface;
803 	struct hostapd_hw_modes *mode = iface->current_mode;
804 	struct hostapd_config *iconf = hapd->iconf;
805 	int len = 0, ret, j;
806 	size_t i;
807 
808 	ret = os_snprintf(buf + len, buflen - len,
809 			  "state=%s\n"
810 			  "phy=%s\n"
811 			  "freq=%d\n"
812 			  "num_sta_non_erp=%d\n"
813 			  "num_sta_no_short_slot_time=%d\n"
814 			  "num_sta_no_short_preamble=%d\n"
815 			  "olbc=%d\n"
816 			  "num_sta_ht_no_gf=%d\n"
817 			  "num_sta_no_ht=%d\n"
818 			  "num_sta_ht_20_mhz=%d\n"
819 			  "num_sta_ht40_intolerant=%d\n"
820 			  "olbc_ht=%d\n"
821 			  "ht_op_mode=0x%x\n",
822 			  hostapd_state_text(iface->state),
823 			  iface->phy,
824 			  iface->freq,
825 			  iface->num_sta_non_erp,
826 			  iface->num_sta_no_short_slot_time,
827 			  iface->num_sta_no_short_preamble,
828 			  iface->olbc,
829 			  iface->num_sta_ht_no_gf,
830 			  iface->num_sta_no_ht,
831 			  iface->num_sta_ht_20mhz,
832 			  iface->num_sta_ht40_intolerant,
833 			  iface->olbc_ht,
834 			  iface->ht_op_mode);
835 	if (os_snprintf_error(buflen - len, ret))
836 		return len;
837 	len += ret;
838 
839 	if (mode) {
840 		ret = os_snprintf(buf + len, buflen - len, "hw_mode=%s\n",
841 				  hw_mode_str(mode->mode));
842 		if (os_snprintf_error(buflen - len, ret))
843 			return len;
844 		len += ret;
845 	}
846 
847 	if (iconf->country[0] && iconf->country[1]) {
848 		ret = os_snprintf(buf + len, buflen - len,
849 				  "country_code=%c%c\ncountry3=0x%X\n",
850 				  iconf->country[0], iconf->country[1],
851 				  iconf->country[2]);
852 		if (os_snprintf_error(buflen - len, ret))
853 			return len;
854 		len += ret;
855 	}
856 
857 	if (!iface->cac_started || !iface->dfs_cac_ms) {
858 		ret = os_snprintf(buf + len, buflen - len,
859 				  "cac_time_seconds=%d\n"
860 				  "cac_time_left_seconds=N/A\n",
861 				  iface->dfs_cac_ms / 1000);
862 	} else {
863 		/* CAC started and CAC time set - calculate remaining time */
864 		struct os_reltime now;
865 		long left_time;
866 
867 		os_reltime_age(&iface->dfs_cac_start, &now);
868 		left_time = (long) iface->dfs_cac_ms / 1000 - now.sec;
869 		ret = os_snprintf(buf + len, buflen - len,
870 				  "cac_time_seconds=%u\n"
871 				  "cac_time_left_seconds=%lu\n",
872 				  iface->dfs_cac_ms / 1000,
873 				  left_time > 0 ? left_time : 0);
874 	}
875 	if (os_snprintf_error(buflen - len, ret))
876 		return len;
877 	len += ret;
878 
879 	ret = os_snprintf(buf + len, buflen - len,
880 			  "channel=%u\n"
881 			  "edmg_enable=%d\n"
882 			  "edmg_channel=%d\n"
883 			  "secondary_channel=%d\n"
884 			  "ieee80211n=%d\n"
885 			  "ieee80211ac=%d\n"
886 			  "ieee80211ax=%d\n"
887 			  "ieee80211be=%d\n"
888 			  "beacon_int=%u\n"
889 			  "dtim_period=%d\n",
890 			  iface->conf->channel,
891 			  iface->conf->enable_edmg,
892 			  iface->conf->edmg_channel,
893 			  hostapd_is_ht_enabled(hapd) ?
894 			  iface->conf->secondary_channel : 0,
895 			  hostapd_is_ht_enabled(hapd),
896 			  hostapd_is_vht_enabled(hapd),
897 			  hostapd_is_he_enabled(hapd),
898 			  hostapd_is_eht_enabled(hapd),
899 			  iface->conf->beacon_int,
900 			  hapd->conf->dtim_period);
901 	if (os_snprintf_error(buflen - len, ret))
902 		return len;
903 	len += ret;
904 
905 #ifdef CONFIG_IEEE80211BE
906 	if (hostapd_is_eht_enabled(hapd)) {
907 		ret = os_snprintf(buf + len, buflen - len,
908 				  "eht_oper_chwidth=%d\n"
909 				  "eht_oper_centr_freq_seg0_idx=%d\n",
910 				  iface->conf->eht_oper_chwidth,
911 				  iface->conf->eht_oper_centr_freq_seg0_idx);
912 		if (os_snprintf_error(buflen - len, ret))
913 			return len;
914 		len += ret;
915 
916 		if (is_6ghz_op_class(iface->conf->op_class) &&
917 		    hostapd_get_oper_chwidth(iface->conf) ==
918 		    CONF_OPER_CHWIDTH_320MHZ) {
919 			ret = os_snprintf(buf + len, buflen - len,
920 					  "eht_bw320_offset=%d\n",
921 					  iface->conf->eht_bw320_offset);
922 			if (os_snprintf_error(buflen - len, ret))
923 				return len;
924 			len += ret;
925 		}
926 
927 		if (hapd->iconf->punct_bitmap) {
928 			ret = os_snprintf(buf + len, buflen - len,
929 					  "punct_bitmap=0x%x\n",
930 					  hapd->iconf->punct_bitmap);
931 			if (os_snprintf_error(buflen - len, ret))
932 				return len;
933 			len += ret;
934 		}
935 
936 		if (hapd->conf->mld_ap) {
937 			struct hostapd_data *link_bss;
938 
939 			ret = os_snprintf(buf + len, buflen - len,
940 					  "num_links=%d\n",
941 					  hapd->mld->num_links);
942 			if (os_snprintf_error(buflen - len, ret))
943 				return len;
944 			len += ret;
945 
946 			/* Self BSS */
947 			ret = os_snprintf(buf + len, buflen - len,
948 					  "link_id=%d\n"
949 					  "link_addr=" MACSTR "\n",
950 					  hapd->mld_link_id,
951 					  MAC2STR(hapd->own_addr));
952 			if (os_snprintf_error(buflen - len, ret))
953 				return len;
954 			len += ret;
955 
956 			/* Partner BSSs */
957 			for_each_mld_link(link_bss, hapd) {
958 				if (link_bss == hapd)
959 					continue;
960 
961 				ret = os_snprintf(buf + len, buflen - len,
962 						  "partner_link[%d]=" MACSTR
963 						  "\n",
964 						  link_bss->mld_link_id,
965 						  MAC2STR(link_bss->own_addr));
966 				if (os_snprintf_error(buflen - len, ret))
967 					return len;
968 				len += ret;
969 			}
970 
971 			ret = os_snprintf(buf + len, buflen - len,
972 					  "ap_mld_type=%s\n",
973 					  (hapd->iface->mld_mld_capa &
974 					   EHT_ML_MLD_CAPA_AP_MLD_TYPE_IND_MASK)
975 					  ? "NSTR" : "STR");
976 			if (os_snprintf_error(buflen - len, ret))
977 				return len;
978 			len += ret;
979 		}
980 	}
981 #endif /* CONFIG_IEEE80211BE */
982 
983 #ifdef CONFIG_IEEE80211AX
984 	if (hostapd_is_he_enabled(hapd)) {
985 		ret = os_snprintf(buf + len, buflen - len,
986 				  "he_oper_chwidth=%d\n"
987 				  "he_oper_centr_freq_seg0_idx=%d\n"
988 				  "he_oper_centr_freq_seg1_idx=%d\n",
989 				  iface->conf->he_oper_chwidth,
990 				  iface->conf->he_oper_centr_freq_seg0_idx,
991 				  iface->conf->he_oper_centr_freq_seg1_idx);
992 		if (os_snprintf_error(buflen - len, ret))
993 			return len;
994 		len += ret;
995 
996 		if (!iconf->he_op.he_bss_color_disabled &&
997 		    iconf->he_op.he_bss_color) {
998 			ret = os_snprintf(buf + len, buflen - len,
999 					  "he_bss_color=%d\n",
1000 					  iconf->he_op.he_bss_color);
1001 			if (os_snprintf_error(buflen - len, ret))
1002 				return len;
1003 			len += ret;
1004 		}
1005 	}
1006 #endif /* CONFIG_IEEE80211AX */
1007 
1008 	if (hostapd_is_vht_enabled(hapd)) {
1009 		ret = os_snprintf(buf + len, buflen - len,
1010 				  "vht_oper_chwidth=%d\n"
1011 				  "vht_oper_centr_freq_seg0_idx=%d\n"
1012 				  "vht_oper_centr_freq_seg1_idx=%d\n"
1013 				  "vht_caps_info=%08x\n",
1014 				  iface->conf->vht_oper_chwidth,
1015 				  iface->conf->vht_oper_centr_freq_seg0_idx,
1016 				  iface->conf->vht_oper_centr_freq_seg1_idx,
1017 				  iface->conf->vht_capab);
1018 		if (os_snprintf_error(buflen - len, ret))
1019 			return len;
1020 		len += ret;
1021 	}
1022 
1023 	if (hostapd_is_vht_enabled(hapd) && mode) {
1024 		u16 rxmap = WPA_GET_LE16(&mode->vht_mcs_set[0]);
1025 		u16 txmap = WPA_GET_LE16(&mode->vht_mcs_set[4]);
1026 
1027 		ret = os_snprintf(buf + len, buflen - len,
1028 				  "rx_vht_mcs_map=%04x\n"
1029 				  "tx_vht_mcs_map=%04x\n",
1030 				  rxmap, txmap);
1031 		if (os_snprintf_error(buflen - len, ret))
1032 			return len;
1033 		len += ret;
1034 	}
1035 
1036 	if (hostapd_is_ht_enabled(hapd)) {
1037 		ret = os_snprintf(buf + len, buflen - len,
1038 				  "ht_caps_info=%04x\n",
1039 				  hapd->iconf->ht_capab);
1040 		if (os_snprintf_error(buflen - len, ret))
1041 			return len;
1042 		len += ret;
1043 	}
1044 
1045 	if (hostapd_is_ht_enabled(hapd) && mode) {
1046 		len = hostapd_write_ht_mcs_bitmask(buf, buflen, len,
1047 						   mode->mcs_set);
1048 	}
1049 
1050 	if (hapd->current_rates && hapd->num_rates) {
1051 		ret = os_snprintf(buf + len, buflen - len, "supported_rates=");
1052 		if (os_snprintf_error(buflen - len, ret))
1053 			return len;
1054 		len += ret;
1055 
1056 		for (j = 0; j < hapd->num_rates; j++) {
1057 			ret = os_snprintf(buf + len, buflen - len, "%s%02x",
1058 					  j > 0 ? " " : "",
1059 					  hapd->current_rates[j].rate / 5);
1060 			if (os_snprintf_error(buflen - len, ret))
1061 				return len;
1062 			len += ret;
1063 		}
1064 		ret = os_snprintf(buf + len, buflen - len, "\n");
1065 		if (os_snprintf_error(buflen - len, ret))
1066 			return len;
1067 		len += ret;
1068 	}
1069 
1070 	for (j = 0; mode && j < mode->num_channels; j++) {
1071 		if (mode->channels[j].freq == iface->freq) {
1072 			ret = os_snprintf(buf + len, buflen - len,
1073 					  "max_txpower=%u\n",
1074 					  mode->channels[j].max_tx_power);
1075 			if (os_snprintf_error(buflen - len, ret))
1076 				return len;
1077 			len += ret;
1078 			break;
1079 		}
1080 	}
1081 
1082 	for (i = 0; i < iface->num_bss; i++) {
1083 		struct hostapd_data *bss = iface->bss[i];
1084 		ret = os_snprintf(buf + len, buflen - len,
1085 				  "bss[%d]=%s\n"
1086 				  "bssid[%d]=" MACSTR "\n"
1087 				  "ssid[%d]=%s\n"
1088 				  "num_sta[%d]=%d\n",
1089 				  (int) i, bss->conf->iface,
1090 				  (int) i, MAC2STR(bss->own_addr),
1091 				  (int) i,
1092 				  wpa_ssid_txt(bss->conf->ssid.ssid,
1093 					       bss->conf->ssid.ssid_len),
1094 				  (int) i, bss->num_sta);
1095 		if (os_snprintf_error(buflen - len, ret))
1096 			return len;
1097 		len += ret;
1098 
1099 #ifdef CONFIG_IEEE80211BE
1100 		if (bss->conf->mld_ap) {
1101 			ret = os_snprintf(buf + len, buflen - len,
1102 					  "mld_addr[%d]=" MACSTR "\n"
1103 					  "mld_id[%d]=%d\n"
1104 					  "mld_link_id[%d]=%d\n",
1105 					  (int) i, MAC2STR(bss->mld->mld_addr),
1106 					  (int) i, hostapd_get_mld_id(bss),
1107 					  (int) i, bss->mld_link_id);
1108 			if (os_snprintf_error(buflen - len, ret))
1109 				return len;
1110 			len += ret;
1111 		}
1112 #endif /* CONFIG_IEEE80211BE */
1113 	}
1114 
1115 	if (hapd->conf->chan_util_avg_period) {
1116 		ret = os_snprintf(buf + len, buflen - len,
1117 				  "chan_util_avg=%u\n",
1118 				  iface->chan_util_average);
1119 		if (os_snprintf_error(buflen - len, ret))
1120 			return len;
1121 		len += ret;
1122 	}
1123 
1124 	return len;
1125 }
1126 
1127 
hostapd_parse_freq_params(const char * pos,struct hostapd_freq_params * params,unsigned int freq)1128 int hostapd_parse_freq_params(const char *pos,
1129 			      struct hostapd_freq_params *params,
1130 			      unsigned int freq)
1131 {
1132 	os_memset(params, 0, sizeof(*params));
1133 
1134 	if (freq)
1135 		params->freq = freq;
1136 	else
1137 		params->freq = atoi(pos);
1138 
1139 	if (params->freq == 0) {
1140 		wpa_printf(MSG_ERROR, "freq_params: invalid freq provided");
1141 		return -1;
1142 	}
1143 
1144 #define SET_FREQ_PARAM(str) \
1145 	do { \
1146 		const char *pos2 = os_strstr(pos, " " #str "="); \
1147 		if (pos2) { \
1148 			pos2 += sizeof(" " #str "=") - 1; \
1149 			params->str = atoi(pos2); \
1150 		} \
1151 	} while (0)
1152 
1153 	SET_FREQ_PARAM(center_freq1);
1154 	SET_FREQ_PARAM(center_freq2);
1155 	SET_FREQ_PARAM(bandwidth);
1156 	SET_FREQ_PARAM(sec_channel_offset);
1157 	SET_FREQ_PARAM(punct_bitmap);
1158 	params->ht_enabled = !!os_strstr(pos, " ht");
1159 	params->vht_enabled = !!os_strstr(pos, " vht");
1160 	params->eht_enabled = !!os_strstr(pos, " eht");
1161 	params->he_enabled = !!os_strstr(pos, " he") ||
1162 		params->eht_enabled;
1163 #undef SET_FREQ_PARAM
1164 
1165 	return 0;
1166 }
1167 
1168 
get_target_hw_mode(struct hostapd_iface * iface,int freq)1169 static struct hostapd_hw_modes * get_target_hw_mode(struct hostapd_iface *iface,
1170 						    int freq)
1171 {
1172 	int i;
1173 	enum hostapd_hw_mode target_mode;
1174 	bool is_6ghz = is_6ghz_freq(freq);
1175 
1176 	if (freq < 4000)
1177 		target_mode = HOSTAPD_MODE_IEEE80211G;
1178 	else if (freq > 50000)
1179 		target_mode = HOSTAPD_MODE_IEEE80211AD;
1180 	else
1181 		target_mode = HOSTAPD_MODE_IEEE80211A;
1182 
1183 	for (i = 0; i < iface->num_hw_features; i++) {
1184 		struct hostapd_hw_modes *mode;
1185 
1186 		mode = &iface->hw_features[i];
1187 		if (mode->mode == target_mode && mode->is_6ghz == is_6ghz)
1188 			return mode;
1189 	}
1190 
1191 	return NULL;
1192 }
1193 
1194 
1195 static bool
hostapd_ctrl_is_freq_in_mode(struct hostapd_hw_modes * mode,struct hostapd_multi_hw_info * current_hw_info,int freq)1196 hostapd_ctrl_is_freq_in_mode(struct hostapd_hw_modes *mode,
1197 			     struct hostapd_multi_hw_info *current_hw_info,
1198 			     int freq)
1199 {
1200 	struct hostapd_channel_data *chan;
1201 	int i;
1202 
1203 	for (i = 0; i < mode->num_channels; i++) {
1204 		chan = &mode->channels[i];
1205 
1206 		if (chan->flag & HOSTAPD_CHAN_DISABLED)
1207 			continue;
1208 
1209 		if (!chan_in_current_hw_info(current_hw_info, chan))
1210 			continue;
1211 
1212 		if (chan->freq == freq)
1213 			return true;
1214 	}
1215 	return false;
1216 }
1217 
1218 
hostapd_ctrl_check_freq_params(struct hostapd_freq_params * params,u16 punct_bitmap)1219 static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params,
1220 					  u16 punct_bitmap)
1221 {
1222 	u32 start_freq;
1223 	bool is_6g = is_6ghz_freq(params->freq);
1224 
1225 	if (is_6g) {
1226 		const int bw_idx[] = { 20, 40, 80, 160, 320 };
1227 		int idx, bw;
1228 
1229 		/* The 6 GHz band requires HE to be enabled. */
1230 		params->he_enabled = 1;
1231 
1232 		if (params->center_freq1) {
1233 			if (params->freq == 5935)
1234 				idx = (params->center_freq1 - 5925) / 5;
1235 			else
1236 				idx = (params->center_freq1 - 5950) / 5;
1237 
1238 			bw = center_idx_to_bw_6ghz(idx);
1239 			if (bw < 0 || bw >= (int) ARRAY_SIZE(bw_idx) ||
1240 			    bw_idx[bw] != params->bandwidth)
1241 				return -1;
1242 		}
1243 	} else { /* Non-6 GHz channel */
1244 		/* An EHT STA is also an HE STA as defined in
1245 		 * IEEE Std 802.11be-2024, 4.3.16a (Extremely high throughput
1246 		 * (EHT) STA). */
1247 		if (params->he_enabled || params->eht_enabled) {
1248 			params->he_enabled = 1;
1249 			/* An HE STA is also a VHT STA if operating in the 5 GHz
1250 			 * band and an HE STA is also an HT STA in the 2.4 GHz
1251 			 * band as defined in IEEE Std 802.11ax-2021, 4.3.15a.
1252 			 * A VHT STA is an HT STA as defined in IEEE
1253 			 * Std 802.11, 4.3.15. */
1254 			if (IS_5GHZ(params->freq))
1255 				params->vht_enabled = 1;
1256 
1257 			params->ht_enabled = 1;
1258 		}
1259 	}
1260 
1261 	switch (params->bandwidth) {
1262 	case 0:
1263 		/* bandwidth not specified: use 20 MHz by default */
1264 		/* fall-through */
1265 	case 20:
1266 		if (params->center_freq1 &&
1267 		    params->center_freq1 != params->freq)
1268 			return -1;
1269 
1270 		if (params->center_freq2 || params->sec_channel_offset)
1271 			return -1;
1272 
1273 		if (punct_bitmap)
1274 			return -1;
1275 		break;
1276 	case 40:
1277 		if (params->center_freq2 ||
1278 		    (!is_6g && !params->sec_channel_offset))
1279 			return -1;
1280 
1281 		if (punct_bitmap)
1282 			return -1;
1283 
1284 		if (!params->center_freq1)
1285 			break;
1286 		switch (params->sec_channel_offset) {
1287 		case 1:
1288 			if (params->freq + 10 != params->center_freq1)
1289 				return -1;
1290 			break;
1291 		case -1:
1292 			if (params->freq - 10 != params->center_freq1)
1293 				return -1;
1294 			break;
1295 		case 0:
1296 			if (!is_6g)
1297 				return -1;
1298 			break;
1299 		default:
1300 			return -1;
1301 		}
1302 		break;
1303 	case 80:
1304 		if (!params->center_freq1 ||
1305 		    (!is_6g && !params->sec_channel_offset))
1306 			return 1;
1307 
1308 		switch (params->sec_channel_offset) {
1309 		case 1:
1310 			if (params->freq - 10 != params->center_freq1 &&
1311 			    params->freq + 30 != params->center_freq1)
1312 				return 1;
1313 			break;
1314 		case -1:
1315 			if (params->freq + 10 != params->center_freq1 &&
1316 			    params->freq - 30 != params->center_freq1)
1317 				return -1;
1318 			break;
1319 		case 0:
1320 			if (!is_6g)
1321 				return -1;
1322 			break;
1323 		default:
1324 			return -1;
1325 		}
1326 
1327 		if (params->center_freq2 && punct_bitmap)
1328 			return -1;
1329 
1330 		/* Adjacent and overlapped are not allowed for 80+80 */
1331 		if (params->center_freq2 &&
1332 		    params->center_freq1 - params->center_freq2 <= 80 &&
1333 		    params->center_freq2 - params->center_freq1 <= 80)
1334 			return 1;
1335 		break;
1336 	case 160:
1337 		if (!params->center_freq1 || params->center_freq2 ||
1338 		    (!is_6g && !params->sec_channel_offset))
1339 			return -1;
1340 
1341 		switch (params->sec_channel_offset) {
1342 		case 1:
1343 			if (params->freq + 70 != params->center_freq1 &&
1344 			    params->freq + 30 != params->center_freq1 &&
1345 			    params->freq - 10 != params->center_freq1 &&
1346 			    params->freq - 50 != params->center_freq1)
1347 				return -1;
1348 			break;
1349 		case -1:
1350 			if (params->freq + 50 != params->center_freq1 &&
1351 			    params->freq + 10 != params->center_freq1 &&
1352 			    params->freq - 30 != params->center_freq1 &&
1353 			    params->freq - 70 != params->center_freq1)
1354 				return -1;
1355 			break;
1356 		case 0:
1357 			if (!is_6g)
1358 				return -1;
1359 			break;
1360 		default:
1361 			return -1;
1362 		}
1363 		break;
1364 	case 320:
1365 		if (!params->center_freq1 || params->center_freq2)
1366 			return -1;
1367 
1368 		switch (params->sec_channel_offset) {
1369 		case 1:
1370 			if (params->freq + 150 != params->center_freq1 &&
1371 			    params->freq + 110 != params->center_freq1 &&
1372 			    params->freq + 70 != params->center_freq1 &&
1373 			    params->freq + 30 != params->center_freq1 &&
1374 			    params->freq - 10 != params->center_freq1 &&
1375 			    params->freq - 50 != params->center_freq1 &&
1376 			    params->freq - 90 != params->center_freq1 &&
1377 			    params->freq - 130 != params->center_freq1)
1378 				return -1;
1379 			break;
1380 		case -1:
1381 			if (params->freq + 130 != params->center_freq1 &&
1382 			    params->freq + 90 != params->center_freq1 &&
1383 			    params->freq + 50 != params->center_freq1 &&
1384 			    params->freq + 10 != params->center_freq1 &&
1385 			    params->freq - 30 != params->center_freq1 &&
1386 			    params->freq - 70 != params->center_freq1 &&
1387 			    params->freq - 110 != params->center_freq1 &&
1388 			    params->freq - 150 != params->center_freq1)
1389 				return -1;
1390 			break;
1391 		case 0:
1392 			break;
1393 		default:
1394 			return -1;
1395 		}
1396 		break;
1397 	default:
1398 		return -1;
1399 	}
1400 
1401 	if (!punct_bitmap)
1402 		return 0;
1403 
1404 	if (!params->eht_enabled) {
1405 		wpa_printf(MSG_ERROR,
1406 			   "Preamble puncturing supported only in EHT");
1407 		return -1;
1408 	}
1409 
1410 	if (params->freq >= 2412 && params->freq <= 2484) {
1411 		wpa_printf(MSG_ERROR,
1412 			   "Preamble puncturing is not supported in 2.4 GHz");
1413 		return -1;
1414 	}
1415 
1416 	start_freq = params->center_freq1 - (params->bandwidth / 2);
1417 	if (!is_punct_bitmap_valid(params->bandwidth,
1418 				   (params->freq - start_freq) / 20,
1419 				   punct_bitmap)) {
1420 		wpa_printf(MSG_ERROR, "Invalid preamble puncturing bitmap");
1421 		return -1;
1422 	}
1423 
1424 	return 0;
1425 }
1426 
1427 
hostapd_parse_csa_settings(struct hostapd_iface * iface,const char * pos,struct csa_settings * settings)1428 int hostapd_parse_csa_settings(struct hostapd_iface *iface,
1429 			       const char *pos,
1430 			       struct csa_settings *settings)
1431 {
1432 	struct hostapd_hw_modes *target_mode;
1433 	char *end;
1434 	int ret;
1435 
1436 	os_memset(settings, 0, sizeof(*settings));
1437 	settings->cs_count = strtol(pos, &end, 10);
1438 	if (pos == end) {
1439 		wpa_printf(MSG_ERROR, "chanswitch: invalid cs_count provided");
1440 		return -1;
1441 	}
1442 
1443 	settings->block_tx = !!os_strstr(pos, " blocktx");
1444 
1445 	ret = hostapd_parse_freq_params(end, &settings->freq_params, 0);
1446 	if (ret < 0) {
1447 		wpa_printf(MSG_INFO,
1448 				"chanswitch: failed to parse frequency parameters");
1449 		return ret;
1450 	}
1451 
1452 	target_mode = get_target_hw_mode(iface, settings->freq_params.freq);
1453 	if (!target_mode) {
1454 		wpa_printf(MSG_DEBUG,
1455 			   "chanswitch: Invalid frequency settings provided for hw mode");
1456 		return -1;
1457 	}
1458 
1459 	if (iface->num_hw_features > 1 &&
1460 	    !hostapd_ctrl_is_freq_in_mode(target_mode, iface->current_hw_info,
1461 					  settings->freq_params.freq)) {
1462 		wpa_printf(MSG_INFO,
1463 			   "chanswitch: Invalid frequency settings provided for multi band phy");
1464 		return -1;
1465 	}
1466 
1467 	ret = hostapd_ctrl_check_freq_params(&settings->freq_params,
1468 					     settings->freq_params.punct_bitmap);
1469 	if (ret) {
1470 		wpa_printf(MSG_INFO,
1471 			   "chanswitch: invalid frequency settings provided");
1472 		return ret;
1473 	}
1474 
1475 	return 0;
1476 }
1477 
1478 
hostapd_ctrl_iface_stop_ap(struct hostapd_data * hapd)1479 int hostapd_ctrl_iface_stop_ap(struct hostapd_data *hapd)
1480 {
1481 	return hostapd_drv_stop_ap(hapd);
1482 }
1483 
1484 
hostapd_ctrl_iface_pmksa_list(struct hostapd_data * hapd,char * buf,size_t len)1485 int hostapd_ctrl_iface_pmksa_list(struct hostapd_data *hapd, char *buf,
1486 				  size_t len)
1487 {
1488 	return wpa_auth_pmksa_list(hapd->wpa_auth, buf, len);
1489 }
1490 
1491 
hostapd_ctrl_iface_pmksa_flush(struct hostapd_data * hapd)1492 void hostapd_ctrl_iface_pmksa_flush(struct hostapd_data *hapd)
1493 {
1494 	wpa_auth_pmksa_flush(hapd->wpa_auth);
1495 }
1496 
1497 
hostapd_ctrl_iface_pmksa_add(struct hostapd_data * hapd,char * cmd)1498 int hostapd_ctrl_iface_pmksa_add(struct hostapd_data *hapd, char *cmd)
1499 {
1500 	u8 spa[ETH_ALEN];
1501 	u8 pmkid[PMKID_LEN];
1502 	u8 pmk[PMK_LEN_MAX];
1503 	size_t pmk_len;
1504 	char *pos, *pos2;
1505 	int akmp = 0, expiration = 0;
1506 	int ret;
1507 
1508 	/*
1509 	 * Entry format:
1510 	 * <STA addr> <PMKID> <PMK> <expiration in seconds> <akmp>
1511 	 */
1512 
1513 	if (hwaddr_aton(cmd, spa))
1514 		return -1;
1515 
1516 	pos = os_strchr(cmd, ' ');
1517 	if (!pos)
1518 		return -1;
1519 	pos++;
1520 
1521 	if (hexstr2bin(pos, pmkid, PMKID_LEN) < 0)
1522 		return -1;
1523 
1524 	pos = os_strchr(pos, ' ');
1525 	if (!pos)
1526 		return -1;
1527 	pos++;
1528 
1529 	pos2 = os_strchr(pos, ' ');
1530 	if (!pos2)
1531 		return -1;
1532 	pmk_len = (pos2 - pos) / 2;
1533 	if (pmk_len < PMK_LEN || pmk_len > PMK_LEN_MAX ||
1534 	    hexstr2bin(pos, pmk, pmk_len) < 0)
1535 		return -1;
1536 
1537 	pos = pos2 + 1;
1538 
1539 	if (sscanf(pos, "%d %d", &expiration, &akmp) != 2)
1540 		return -1;
1541 
1542 	ret = wpa_auth_pmksa_add2(hapd->wpa_auth, spa, pmk, pmk_len,
1543 				  pmkid, expiration, akmp, NULL, false);
1544 	if (ret)
1545 		return ret;
1546 
1547 #ifdef CONFIG_IEEE80211BE
1548 	if (hapd->conf->mld_ap)
1549 		ret = wpa_auth_pmksa_add2(hapd->wpa_auth, spa, pmk, pmk_len,
1550 					  pmkid, expiration, akmp, NULL, true);
1551 #endif /* CONFIG_IEEE80211BE */
1552 
1553 	return ret;
1554 }
1555 
1556 
1557 #ifdef CONFIG_PMKSA_CACHE_EXTERNAL
1558 #ifdef CONFIG_MESH
1559 
hostapd_ctrl_iface_pmksa_list_mesh(struct hostapd_data * hapd,const u8 * addr,char * buf,size_t len)1560 int hostapd_ctrl_iface_pmksa_list_mesh(struct hostapd_data *hapd,
1561 				       const u8 *addr, char *buf, size_t len)
1562 {
1563 	return wpa_auth_pmksa_list_mesh(hapd->wpa_auth, addr, buf, len);
1564 }
1565 
1566 
hostapd_ctrl_iface_pmksa_create_entry(const u8 * aa,char * cmd)1567 void * hostapd_ctrl_iface_pmksa_create_entry(const u8 *aa, char *cmd)
1568 {
1569 	u8 spa[ETH_ALEN];
1570 	u8 pmkid[PMKID_LEN];
1571 	u8 pmk[PMK_LEN_MAX];
1572 	char *pos;
1573 	int expiration;
1574 
1575 	/*
1576 	 * Entry format:
1577 	 * <BSSID> <PMKID> <PMK> <expiration in seconds>
1578 	 */
1579 
1580 	if (hwaddr_aton(cmd, spa))
1581 		return NULL;
1582 
1583 	pos = os_strchr(cmd, ' ');
1584 	if (!pos)
1585 		return NULL;
1586 	pos++;
1587 
1588 	if (hexstr2bin(pos, pmkid, PMKID_LEN) < 0)
1589 		return NULL;
1590 
1591 	pos = os_strchr(pos, ' ');
1592 	if (!pos)
1593 		return NULL;
1594 	pos++;
1595 
1596 	if (hexstr2bin(pos, pmk, PMK_LEN) < 0)
1597 		return NULL;
1598 
1599 	pos = os_strchr(pos, ' ');
1600 	if (!pos)
1601 		return NULL;
1602 	pos++;
1603 
1604 	if (sscanf(pos, "%d", &expiration) != 1)
1605 		return NULL;
1606 
1607 	return wpa_auth_pmksa_create_entry(aa, spa, pmk, PMK_LEN,
1608 					   WPA_KEY_MGMT_SAE, pmkid, expiration);
1609 }
1610 
1611 #endif /* CONFIG_MESH */
1612 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
1613 
1614 
1615 #ifdef CONFIG_WNM_AP
1616 
hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data * hapd,const char * cmd)1617 int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd,
1618 					 const char *cmd)
1619 {
1620 	u8 addr[ETH_ALEN];
1621 	int disassoc_timer;
1622 	struct sta_info *sta;
1623 
1624 	if (hwaddr_aton(cmd, addr))
1625 		return -1;
1626 	if (cmd[17] != ' ')
1627 		return -1;
1628 	disassoc_timer = atoi(cmd + 17);
1629 
1630 	sta = ap_get_sta(hapd, addr);
1631 	if (sta == NULL) {
1632 		wpa_printf(MSG_DEBUG, "Station " MACSTR
1633 			   " not found for disassociation imminent message",
1634 			   MAC2STR(addr));
1635 		return -1;
1636 	}
1637 
1638 	return wnm_send_disassoc_imminent(hapd, sta, disassoc_timer);
1639 }
1640 
1641 
hostapd_ctrl_iface_ess_disassoc(struct hostapd_data * hapd,const char * cmd)1642 int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
1643 				    const char *cmd)
1644 {
1645 	u8 addr[ETH_ALEN];
1646 	const char *url, *timerstr;
1647 	int disassoc_timer;
1648 	struct sta_info *sta;
1649 
1650 	if (hwaddr_aton(cmd, addr))
1651 		return -1;
1652 
1653 	sta = ap_get_sta(hapd, addr);
1654 	if (sta == NULL) {
1655 		wpa_printf(MSG_DEBUG, "Station " MACSTR
1656 			   " not found for ESS disassociation imminent message",
1657 			   MAC2STR(addr));
1658 		return -1;
1659 	}
1660 
1661 	timerstr = cmd + 17;
1662 	if (*timerstr != ' ')
1663 		return -1;
1664 	timerstr++;
1665 	disassoc_timer = atoi(timerstr);
1666 	if (disassoc_timer < 0 || disassoc_timer > 65535)
1667 		return -1;
1668 
1669 	url = os_strchr(timerstr, ' ');
1670 	if (url == NULL)
1671 		return -1;
1672 	url++;
1673 
1674 	return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer);
1675 }
1676 
1677 
hostapd_ctrl_iface_bss_tm_req(struct hostapd_data * hapd,const char * cmd)1678 int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
1679 				  const char *cmd)
1680 {
1681 	u8 addr[ETH_ALEN];
1682 	const char *pos, *end;
1683 	int disassoc_timer = 0;
1684 	struct sta_info *sta;
1685 	u8 req_mode = 0, valid_int = 0x01, dialog_token = 0x01;
1686 	u8 bss_term_dur[12];
1687 	char *url = NULL;
1688 	int ret;
1689 	u8 nei_rep[1000];
1690 	int nei_len;
1691 	u8 mbo[10];
1692 	size_t mbo_len = 0;
1693 
1694 	if (hwaddr_aton(cmd, addr)) {
1695 		wpa_printf(MSG_DEBUG, "Invalid STA MAC address");
1696 		return -1;
1697 	}
1698 
1699 	sta = ap_get_sta(hapd, addr);
1700 	if (sta == NULL) {
1701 		wpa_printf(MSG_DEBUG, "Station " MACSTR
1702 			   " not found for BSS TM Request message",
1703 			   MAC2STR(addr));
1704 		return -1;
1705 	}
1706 
1707 	pos = os_strstr(cmd, " disassoc_timer=");
1708 	if (pos) {
1709 		pos += 16;
1710 		disassoc_timer = atoi(pos);
1711 		if (disassoc_timer < 0 || disassoc_timer > 65535) {
1712 			wpa_printf(MSG_DEBUG, "Invalid disassoc_timer");
1713 			return -1;
1714 		}
1715 	}
1716 
1717 	pos = os_strstr(cmd, " valid_int=");
1718 	if (pos) {
1719 		pos += 11;
1720 		valid_int = atoi(pos);
1721 	}
1722 
1723 	pos = os_strstr(cmd, " dialog_token=");
1724 	if (pos) {
1725 		pos += 14;
1726 		dialog_token = atoi(pos);
1727 	}
1728 
1729 	pos = os_strstr(cmd, " bss_term=");
1730 	if (pos) {
1731 		pos += 10;
1732 		req_mode |= WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED;
1733 		/* TODO: TSF configurable/learnable */
1734 		bss_term_dur[0] = 4; /* Subelement ID */
1735 		bss_term_dur[1] = 10; /* Length */
1736 		os_memset(&bss_term_dur[2], 0, 8);
1737 		end = os_strchr(pos, ',');
1738 		if (end == NULL) {
1739 			wpa_printf(MSG_DEBUG, "Invalid bss_term data");
1740 			return -1;
1741 		}
1742 		end++;
1743 		WPA_PUT_LE16(&bss_term_dur[10], atoi(end));
1744 	}
1745 
1746 	nei_len = ieee802_11_parse_candidate_list(cmd, nei_rep,
1747 						  sizeof(nei_rep));
1748 	if (nei_len < 0)
1749 		return -1;
1750 
1751 	pos = os_strstr(cmd, " url=");
1752 	if (pos) {
1753 		size_t len;
1754 		pos += 5;
1755 		end = os_strchr(pos, ' ');
1756 		if (end)
1757 			len = end - pos;
1758 		else
1759 			len = os_strlen(pos);
1760 		url = os_malloc(len + 1);
1761 		if (url == NULL)
1762 			return -1;
1763 		os_memcpy(url, pos, len);
1764 		url[len] = '\0';
1765 		req_mode |= WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
1766 	}
1767 
1768 	if (os_strstr(cmd, " pref=1"))
1769 		req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED;
1770 	if (os_strstr(cmd, " abridged=1"))
1771 		req_mode |= WNM_BSS_TM_REQ_ABRIDGED;
1772 	if (os_strstr(cmd, " disassoc_imminent=1"))
1773 		req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
1774 	if (os_strstr(cmd, " link_removal_imminent=1"))
1775 		req_mode |= WNM_BSS_TM_REQ_LINK_REMOVAL_IMMINENT;
1776 
1777 #ifdef CONFIG_MBO
1778 	pos = os_strstr(cmd, "mbo=");
1779 	if (pos) {
1780 		unsigned int mbo_reason, cell_pref, reassoc_delay;
1781 		u8 *mbo_pos = mbo;
1782 
1783 		ret = sscanf(pos, "mbo=%u:%u:%u", &mbo_reason,
1784 			     &reassoc_delay, &cell_pref);
1785 		if (ret != 3) {
1786 			wpa_printf(MSG_DEBUG,
1787 				   "MBO requires three arguments: mbo=<reason>:<reassoc_delay>:<cell_pref>");
1788 			ret = -1;
1789 			goto fail;
1790 		}
1791 
1792 		if (mbo_reason > MBO_TRANSITION_REASON_PREMIUM_AP) {
1793 			wpa_printf(MSG_DEBUG,
1794 				   "Invalid MBO transition reason code %u",
1795 				   mbo_reason);
1796 			ret = -1;
1797 			goto fail;
1798 		}
1799 
1800 		/* Valid values for Cellular preference are: 0, 1, 255 */
1801 		if (cell_pref != 0 && cell_pref != 1 && cell_pref != 255) {
1802 			wpa_printf(MSG_DEBUG,
1803 				   "Invalid MBO cellular capability %u",
1804 				   cell_pref);
1805 			ret = -1;
1806 			goto fail;
1807 		}
1808 
1809 		if (reassoc_delay > 65535 ||
1810 		    (reassoc_delay &&
1811 		     !(req_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT))) {
1812 			wpa_printf(MSG_DEBUG,
1813 				   "MBO: Assoc retry delay is only valid in disassoc imminent mode");
1814 			ret = -1;
1815 			goto fail;
1816 		}
1817 
1818 		*mbo_pos++ = MBO_ATTR_ID_TRANSITION_REASON;
1819 		*mbo_pos++ = 1;
1820 		*mbo_pos++ = mbo_reason;
1821 		*mbo_pos++ = MBO_ATTR_ID_CELL_DATA_PREF;
1822 		*mbo_pos++ = 1;
1823 		*mbo_pos++ = cell_pref;
1824 
1825 		if (reassoc_delay) {
1826 			*mbo_pos++ = MBO_ATTR_ID_ASSOC_RETRY_DELAY;
1827 			*mbo_pos++ = 2;
1828 			WPA_PUT_LE16(mbo_pos, reassoc_delay);
1829 			mbo_pos += 2;
1830 		}
1831 
1832 		mbo_len = mbo_pos - mbo;
1833 	}
1834 #endif /* CONFIG_MBO */
1835 
1836 	ret = wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer,
1837 				  valid_int, bss_term_dur, dialog_token, url,
1838 				  nei_len ? nei_rep : NULL, nei_len,
1839 				  mbo_len ? mbo : NULL, mbo_len);
1840 #ifdef CONFIG_MBO
1841 fail:
1842 #endif /* CONFIG_MBO */
1843 	os_free(url);
1844 	return ret;
1845 }
1846 
1847 #endif /* CONFIG_WNM_AP */
1848 
1849 
hostapd_ctrl_iface_acl_del_mac(struct mac_acl_entry ** acl,int * num,const char * txtaddr)1850 int hostapd_ctrl_iface_acl_del_mac(struct mac_acl_entry **acl, int *num,
1851 				   const char *txtaddr)
1852 {
1853 	u8 addr[ETH_ALEN];
1854 	struct vlan_description vlan_id;
1855 
1856 	if (!(*num))
1857 		return 0;
1858 
1859 	if (hwaddr_aton(txtaddr, addr))
1860 		return -1;
1861 
1862 	if (hostapd_maclist_found(*acl, *num, addr, &vlan_id))
1863 		hostapd_remove_acl_mac(acl, num, addr);
1864 
1865 	return 0;
1866 }
1867 
1868 
hostapd_ctrl_iface_acl_clear_list(struct mac_acl_entry ** acl,int * num)1869 void hostapd_ctrl_iface_acl_clear_list(struct mac_acl_entry **acl,
1870 				       int *num)
1871 {
1872 	while (*num)
1873 		hostapd_remove_acl_mac(acl, num, (*acl)[0].addr);
1874 }
1875 
1876 
hostapd_ctrl_iface_acl_show_mac(struct mac_acl_entry * acl,int num,char * buf,size_t buflen)1877 int hostapd_ctrl_iface_acl_show_mac(struct mac_acl_entry *acl, int num,
1878 				    char *buf, size_t buflen)
1879 {
1880 	int i = 0, len = 0, ret = 0;
1881 
1882 	if (!acl)
1883 		return 0;
1884 
1885 	while (i < num) {
1886 		ret = os_snprintf(buf + len, buflen - len,
1887 				  MACSTR " VLAN_ID=%d\n",
1888 				  MAC2STR(acl[i].addr),
1889 				  acl[i].vlan_id.untagged);
1890 		if (ret < 0 || (size_t) ret >= buflen - len)
1891 			return len;
1892 		i++;
1893 		len += ret;
1894 	}
1895 	return len;
1896 }
1897 
1898 
hostapd_ctrl_iface_acl_add_mac(struct mac_acl_entry ** acl,int * num,const char * cmd)1899 int hostapd_ctrl_iface_acl_add_mac(struct mac_acl_entry **acl, int *num,
1900 				   const char *cmd)
1901 {
1902 	u8 addr[ETH_ALEN];
1903 	struct vlan_description vlan_id;
1904 	int ret = 0, vlanid = 0;
1905 	const char *pos;
1906 
1907 	if (hwaddr_aton(cmd, addr))
1908 		return -1;
1909 
1910 	pos = os_strstr(cmd, "VLAN_ID=");
1911 	if (pos)
1912 		vlanid = atoi(pos + 8);
1913 
1914 	if (!hostapd_maclist_found(*acl, *num, addr, &vlan_id)) {
1915 		ret = hostapd_add_acl_maclist(acl, num, vlanid, addr);
1916 		if (ret != -1 && *acl)
1917 			qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp);
1918 	}
1919 
1920 	return ret < 0 ? -1 : 0;
1921 }
1922 
1923 
hostapd_disassoc_accept_mac(struct hostapd_data * hapd)1924 int hostapd_disassoc_accept_mac(struct hostapd_data *hapd)
1925 {
1926 	struct sta_info *sta;
1927 	struct vlan_description vlan_id;
1928 
1929 	if (hapd->conf->macaddr_acl != DENY_UNLESS_ACCEPTED)
1930 		return 0;
1931 
1932 	for (sta = hapd->sta_list; sta; sta = sta->next) {
1933 		if (!hostapd_maclist_found(hapd->conf->accept_mac,
1934 					   hapd->conf->num_accept_mac,
1935 					   sta->addr, &vlan_id) ||
1936 		    (vlan_id.notempty &&
1937 		     vlan_compare(&vlan_id, sta->vlan_desc)))
1938 			ap_sta_disconnect(hapd, sta, sta->addr,
1939 					  WLAN_REASON_UNSPECIFIED);
1940 	}
1941 
1942 	return 0;
1943 }
1944 
1945 
hostapd_disassoc_deny_mac(struct hostapd_data * hapd)1946 int hostapd_disassoc_deny_mac(struct hostapd_data *hapd)
1947 {
1948 	struct sta_info *sta;
1949 	struct vlan_description vlan_id;
1950 
1951 	for (sta = hapd->sta_list; sta; sta = sta->next) {
1952 #ifdef CONFIG_IEEE80211BE
1953 		int link_id;
1954 		struct mld_link_info *info;
1955 #endif /* CONFIG_IEEE80211BE */
1956 
1957 		if (hostapd_maclist_found(hapd->conf->deny_mac,
1958 					  hapd->conf->num_deny_mac, sta->addr,
1959 					  &vlan_id) &&
1960 		    (!vlan_id.notempty ||
1961 		     !vlan_compare(&vlan_id, sta->vlan_desc)))
1962 			ap_sta_disconnect(hapd, sta, sta->addr,
1963 					  WLAN_REASON_UNSPECIFIED);
1964 #ifdef CONFIG_IEEE80211BE
1965 		for (link_id = 0; hapd->conf->mld_ap &&
1966 			     link_id < MAX_NUM_MLD_LINKS &&
1967 			     sta->mld_info.mld_sta; link_id++) {
1968 			info = &sta->mld_info.links[link_id];
1969 			if (!info->valid || link_id != hapd->mld_link_id)
1970 				continue;
1971 
1972 			if (hostapd_maclist_found(hapd->conf->deny_mac,
1973 						  hapd->conf->num_deny_mac,
1974 						  info->peer_addr,
1975 						  &vlan_id) &&
1976 			    (!vlan_id.notempty ||
1977 			     !vlan_compare(&vlan_id, sta->vlan_desc)))
1978 				ap_sta_disconnect(hapd, sta, sta->addr,
1979 						  WLAN_REASON_UNSPECIFIED);
1980 		}
1981 #endif /* CONFIG_IEEE80211BE */
1982 	}
1983 
1984 	return 0;
1985 }
1986