• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * aidl interface for wpa_hostapd daemon
3  * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
4  * Copyright (c) 2004-2018, Roshan Pius <rpius@google.com>
5  *
6  * This software may be distributed under the terms of the BSD license.
7  * See README for more details.
8  */
9 #include <iomanip>
10 #include <sstream>
11 #include <string>
12 #include <vector>
13 #include <net/if.h>
14 #include <sys/socket.h>
15 #include <linux/if_bridge.h>
16 
17 #include <android-base/file.h>
18 #include <android-base/stringprintf.h>
19 #include <android-base/unique_fd.h>
20 
21 #include "hostapd.h"
22 #include <aidl/android/hardware/wifi/hostapd/ApInfo.h>
23 #include <aidl/android/hardware/wifi/hostapd/BandMask.h>
24 #include <aidl/android/hardware/wifi/hostapd/ChannelParams.h>
25 #include <aidl/android/hardware/wifi/hostapd/ClientInfo.h>
26 #include <aidl/android/hardware/wifi/hostapd/EncryptionType.h>
27 #include <aidl/android/hardware/wifi/hostapd/HostapdStatusCode.h>
28 #include <aidl/android/hardware/wifi/hostapd/IfaceParams.h>
29 #include <aidl/android/hardware/wifi/hostapd/NetworkParams.h>
30 #include <aidl/android/hardware/wifi/hostapd/ParamSizeLimits.h>
31 
32 extern "C"
33 {
34 #include "common/wpa_ctrl.h"
35 #include "drivers/linux_ioctl.h"
36 }
37 
38 
39 #ifdef ANDROID_HOSTAPD_UNITTEST
40 #include "tests/unittest_overrides.h"
41 #endif
42 
43 // The AIDL implementation for hostapd creates a hostapd.conf dynamically for
44 // each interface. This file can then be used to hook onto the normal config
45 // file parsing logic in hostapd code.  Helps us to avoid duplication of code
46 // in the AIDL interface.
47 // TOOD(b/71872409): Add unit tests for this.
48 namespace {
49 constexpr char kConfFileNameFmt[] = "/data/vendor/wifi/hostapd/hostapd_%s.conf";
50 
51 /**
52  * To add an overlay file, add
53  *
54  * PRODUCT_COPY_FILES += \
55  *   <your/path/here>/hostapd_unmetered_overlay.conf:/vendor/etc/wifi/hostapd_unmetered_overlay.conf
56  *
57  * to the build file for your device, with the <your/path/here> being the path to your overlay in
58  * your repo. See the resolveVendorConfPath function in this file for more specifics on where this
59  * overlay file will wind up on your device.
60  *
61  * This overlay may configure any of the parameters listed in kOverlayableKeys. The kOverlayableKeys
62  * list is subject to change over time, as certain parameters may be added as APIs instead in the
63  * future.
64  *
65  * Example of what an overlay file might look like:
66  * $> cat hostapd_unmetered_overlay.conf
67  * dtim_period=2
68  * ap_max_inactivity=300
69  *
70  * Anything added to this overlay will be prepended to the hostapd.conf for unmetered (typically
71  * local only hotspots) interfaces.
72  */
73 constexpr char kUnmeteredIfaceOverlayPath[] = "/etc/wifi/hostapd_unmetered_overlay.conf";
74 
75 /**
76  * Allow-list of hostapd.conf parameters (keys) that can be set via overlay.
77  *
78  * If introducing new APIs, be sure to remove keys from this list that would otherwise be
79  * controlled by the new API. This way we can avoid conflicting settings.
80  * Please file an FR to add new keys to this list.
81  */
82 static const std::set<std::string> kOverlayableKeys = {
83 	"ap_max_inactivity",
84 	"assocresp_elements"
85 	"beacon_int",
86 	"disassoc_low_ack",
87 	"dtim_period",
88 	"fragm_threshold",
89 	"max_listen_interval",
90 	"max_num_sta",
91 	"rts_threshold",
92 	"skip_inactivity_poll",
93 	"uapsd_advertisement_enabled",
94 	"wmm_enabled",
95 	"wmm_ac_vo_aifs",
96 	"wmm_ac_vo_cwmin",
97 	"wmm_ac_vo_cwmax",
98 	"wmm_ac_vo_txop_limit",
99 	"wmm_ac_vo_acm",
100 	"wmm_ac_vi_aifs",
101 	"wmm_ac_vi_cwmin",
102 	"wmm_ac_vi_cwmax",
103 	"wmm_ac_vi_txop_limit",
104 	"wmm_ac_vi_acm",
105 	"wmm_ac_bk_cwmin"
106 	"wmm_ac_bk_cwmax"
107 	"wmm_ac_bk_aifs",
108 	"wmm_ac_bk_txop_limit",
109 	"wmm_ac_bk_acm",
110 	"wmm_ac_be_aifs",
111 	"wmm_ac_be_cwmin",
112 	"wmm_ac_be_cwmax",
113 	"wmm_ac_be_txop_limit",
114 	"wmm_ac_be_acm",
115 };
116 
117 using android::base::RemoveFileIfExists;
118 using android::base::StringPrintf;
119 #ifndef ANDROID_HOSTAPD_UNITTEST
120 using android::base::ReadFileToString;
121 using android::base::WriteStringToFile;
122 #endif
123 using aidl::android::hardware::wifi::hostapd::BandMask;
124 using aidl::android::hardware::wifi::hostapd::ChannelBandwidth;
125 using aidl::android::hardware::wifi::hostapd::ChannelParams;
126 using aidl::android::hardware::wifi::hostapd::EncryptionType;
127 using aidl::android::hardware::wifi::hostapd::Generation;
128 using aidl::android::hardware::wifi::hostapd::HostapdStatusCode;
129 using aidl::android::hardware::wifi::hostapd::IfaceParams;
130 using aidl::android::hardware::wifi::hostapd::NetworkParams;
131 using aidl::android::hardware::wifi::hostapd::ParamSizeLimits;
132 
133 int band2Ghz = (int)BandMask::BAND_2_GHZ;
134 int band5Ghz = (int)BandMask::BAND_5_GHZ;
135 int band6Ghz = (int)BandMask::BAND_6_GHZ;
136 int band60Ghz = (int)BandMask::BAND_60_GHZ;
137 
138 int32_t aidl_client_version = 0;
139 int32_t aidl_service_version = 0;
140 
macAddrToArray(const uint8_t * mac_addr)141 inline std::array<uint8_t, ETH_ALEN> macAddrToArray(const uint8_t* mac_addr) {
142 	std::array<uint8_t, ETH_ALEN> arr;
143 	std::copy(mac_addr, mac_addr + ETH_ALEN, std::begin(arr));
144 	return arr;
145 }
146 
147 /**
148  * Check that the AIDL service is running at least the expected version.
149  * Use to avoid the case where the AIDL interface version
150  * is greater than the version implemented by the service.
151  */
isAidlServiceVersionAtLeast(int32_t expected_version)152 inline int32_t isAidlServiceVersionAtLeast(int32_t expected_version)
153 {
154 	return expected_version <= aidl_service_version;
155 }
156 
isAidlClientVersionAtLeast(int32_t expected_version)157 inline int32_t isAidlClientVersionAtLeast(int32_t expected_version)
158 {
159 	return expected_version <= aidl_client_version;
160 }
161 
areAidlServiceAndClientAtLeastVersion(int32_t expected_version)162 inline int32_t areAidlServiceAndClientAtLeastVersion(int32_t expected_version)
163 {
164 	return isAidlServiceVersionAtLeast(expected_version)
165 		&& isAidlClientVersionAtLeast(expected_version);
166 }
167 
168 #define MAX_PORTS 1024
GetInterfacesInBridge(std::string br_name,std::vector<std::string> * interfaces)169 bool GetInterfacesInBridge(std::string br_name,
170                            std::vector<std::string>* interfaces) {
171 	android::base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
172 	if (sock.get() < 0) {
173 		wpa_printf(MSG_ERROR, "Failed to create sock (%s) in %s",
174 			strerror(errno), __FUNCTION__);
175 		return false;
176 	}
177 
178 	struct ifreq request;
179 	int i, ifindices[MAX_PORTS];
180 	char if_name[IFNAMSIZ];
181 	unsigned long args[3];
182 
183 	memset(ifindices, 0, MAX_PORTS * sizeof(int));
184 
185 	args[0] = BRCTL_GET_PORT_LIST;
186 	args[1] = (unsigned long) ifindices;
187 	args[2] = MAX_PORTS;
188 
189 	strlcpy(request.ifr_name, br_name.c_str(), IFNAMSIZ);
190 	request.ifr_data = (char *)args;
191 
192 	if (ioctl(sock.get(), SIOCDEVPRIVATE, &request) < 0) {
193 		wpa_printf(MSG_ERROR, "Failed to ioctl SIOCDEVPRIVATE in %s",
194 			__FUNCTION__);
195 		return false;
196 	}
197 
198 	for (i = 0; i < MAX_PORTS; i ++) {
199 		memset(if_name, 0, IFNAMSIZ);
200 		if (ifindices[i] == 0 || !if_indextoname(ifindices[i], if_name)) {
201 			continue;
202 		}
203 		interfaces->push_back(if_name);
204 	}
205 	return true;
206 }
207 
resolveVendorConfPath(const std::string & conf_path)208 std::string resolveVendorConfPath(const std::string& conf_path)
209 {
210 #if defined(__ANDROID_APEX__)
211 	// returns "/apex/<apexname>" + conf_path
212 	std::string path = android::base::GetExecutablePath();
213 	return path.substr(0, path.find_first_of('/', strlen("/apex/"))) + conf_path;
214 #else
215 	return std::string("/vendor") + conf_path;
216 #endif
217 }
218 
logHostapdConfigError(int error,const std::string & file_path)219 void logHostapdConfigError(int error, const std::string& file_path) {
220 	wpa_printf(MSG_ERROR, "Cannot read/write hostapd config %s, error: %s", file_path.c_str(),
221 			strerror(error));
222 	struct stat st;
223 	int result = stat(file_path.c_str(), &st);
224 	if (result == 0) {
225 		wpa_printf(MSG_ERROR, "hostapd config file uid: %d, gid: %d, mode: %d",st.st_uid,
226 				st.st_gid, st.st_mode);
227 	} else {
228 		wpa_printf(MSG_ERROR, "Error calling stat() on hostapd config file: %s",
229 				strerror(errno));
230 	}
231 }
232 
WriteHostapdConfig(const std::string & instance_name,const std::string & config,const std::string br_name,const bool usesMlo)233 std::string WriteHostapdConfig(
234     const std::string& instance_name, const std::string& config,
235     const std::string br_name, const bool usesMlo)
236 {
237 	std::string conf_name_as_string = instance_name;
238 	if (usesMlo) {
239 		conf_name_as_string = StringPrintf(
240 				"%s-%s", br_name.c_str(), instance_name.c_str());
241 	}
242 	const std::string file_path =
243 		StringPrintf(kConfFileNameFmt, conf_name_as_string.c_str());
244 	if (WriteStringToFile(
245 		config, file_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
246 		getuid(), getgid())) {
247 		return file_path;
248 	}
249 	// Diagnose failure
250 	int error = errno;
251 	logHostapdConfigError(errno, file_path);
252 	return "";
253 }
254 
255 /*
256  * Get the op_class for a channel/band
257  * The logic here is based on Table E-4 in the 802.11 Specification
258  */
getOpClassForChannel(int channel,int band,bool support11n,bool support11ac)259 int getOpClassForChannel(int channel, int band, bool support11n, bool support11ac) {
260 	// 2GHz Band
261 	if ((band & band2Ghz) != 0) {
262 		if (channel == 14) {
263 			return 82;
264 		}
265 		if (channel >= 1 && channel <= 13) {
266 			if (!support11n) {
267 				//20MHz channel
268 				return 81;
269 			}
270 			if (channel <= 9) {
271 				// HT40 with secondary channel above primary
272 				return 83;
273 			}
274 			// HT40 with secondary channel below primary
275 			return 84;
276 		}
277 		// Error
278 		return 0;
279 	}
280 
281 	// 5GHz Band
282 	if ((band & band5Ghz) != 0) {
283 		if (support11ac) {
284 			switch (channel) {
285 				case 42:
286 				case 58:
287 				case 106:
288 				case 122:
289 				case 138:
290 				case 155:
291 					// 80MHz channel
292 					return 128;
293 				case 50:
294 				case 114:
295 					// 160MHz channel
296 					return 129;
297 			}
298 		}
299 
300 		if (!support11n) {
301 			if (channel >= 36 && channel <= 48) {
302 				return 115;
303 			}
304 			if (channel >= 52 && channel <= 64) {
305 				return 118;
306 			}
307 			if (channel >= 100 && channel <= 144) {
308 				return 121;
309 			}
310 			if (channel >= 149 && channel <= 161) {
311 				return 124;
312 			}
313 			if (channel >= 165 && channel <= 169) {
314 				return 125;
315 			}
316 		} else {
317 			switch (channel) {
318 				case 36:
319 				case 44:
320 					// HT40 with secondary channel above primary
321 					return 116;
322 				case 40:
323 				case 48:
324 					// HT40 with secondary channel below primary
325 					return 117;
326 				case 52:
327 				case 60:
328 					// HT40 with secondary channel above primary
329 					return  119;
330 				case 56:
331 				case 64:
332 					// HT40 with secondary channel below primary
333 					return 120;
334 				case 100:
335 				case 108:
336 				case 116:
337 				case 124:
338 				case 132:
339 				case 140:
340 					// HT40 with secondary channel above primary
341 					return 122;
342 				case 104:
343 				case 112:
344 				case 120:
345 				case 128:
346 				case 136:
347 				case 144:
348 					// HT40 with secondary channel below primary
349 					return 123;
350 				case 149:
351 				case 157:
352 					// HT40 with secondary channel above primary
353 					return 126;
354 				case 153:
355 				case 161:
356 					// HT40 with secondary channel below primary
357 					return 127;
358 			}
359 		}
360 		// Error
361 		return 0;
362 	}
363 
364 	// 6GHz Band
365 	if ((band & band6Ghz) != 0) {
366 		// Channels 1, 5. 9, 13, ...
367 		if ((channel & 0x03) == 0x01) {
368 			// 20MHz channel
369 			return 131;
370 		}
371 		// Channels 3, 11, 19, 27, ...
372 		if ((channel & 0x07) == 0x03) {
373 			// 40MHz channel
374 			return 132;
375 		}
376 		// Channels 7, 23, 39, 55, ...
377 		if ((channel & 0x0F) == 0x07) {
378 			// 80MHz channel
379 			return 133;
380 		}
381 		// Channels 15, 47, 69, ...
382 		if ((channel & 0x1F) == 0x0F) {
383 			// 160MHz channel
384 			return 134;
385 		}
386 		if (channel == 2) {
387 			// 20MHz channel
388 			return 136;
389 		}
390 		// Error
391 		return 0;
392 	}
393 
394 	if ((band & band60Ghz) != 0) {
395 		if (1 <= channel && channel <= 8) {
396 			return 180;
397 		} else if (9 <= channel && channel <= 15) {
398 			return 181;
399 		} else if (17 <= channel && channel <= 22) {
400 			return 182;
401 		} else if (25 <= channel && channel <= 29) {
402 			return 183;
403 		}
404 		// Error
405 		return 0;
406 	}
407 
408 	return 0;
409 }
410 
validatePassphrase(int passphrase_len,int min_len,int max_len)411 bool validatePassphrase(int passphrase_len, int min_len, int max_len)
412 {
413 	if (min_len != -1 && passphrase_len < min_len) return false;
414 	if (max_len != -1 && passphrase_len > max_len) return false;
415 	return true;
416 }
417 
getInterfaceMacAddress(const std::string & if_name)418 std::string getInterfaceMacAddress(const std::string& if_name)
419 {
420 	u8 addr[ETH_ALEN] = {};
421 	struct ifreq ifr;
422 	std::string mac_addr;
423 
424 	android::base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
425 	if (sock.get() < 0) {
426 		wpa_printf(MSG_ERROR, "Failed to create sock (%s) in %s",
427 			strerror(errno), __FUNCTION__);
428 		return "";
429 	}
430 
431 	memset(&ifr, 0, sizeof(ifr));
432 	strlcpy(ifr.ifr_name, if_name.c_str(), IFNAMSIZ);
433 	if (ioctl(sock.get(), SIOCGIFHWADDR, &ifr) < 0) {
434 		wpa_printf(MSG_ERROR, "Could not get interface %s hwaddr: %s",
435 			   if_name.c_str(), strerror(errno));
436 		return "";
437 	}
438 
439 	memcpy(addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
440 	mac_addr = StringPrintf("" MACSTR, MAC2STR(addr));
441 
442 	return mac_addr;
443 }
444 
trimWhitespace(const std::string & str)445 std::string trimWhitespace(const std::string& str) {
446 	size_t pos = 0;
447 	size_t len = str.size();
448 	for (pos; pos < str.size() && std::isspace(str[pos]); ++pos){}
449 	for (len; len - 1 > 0 && std::isspace(str[len-1]); --len){}
450 	return str.substr(pos, len);
451 }
452 
CreateHostapdConfig(const IfaceParams & iface_params,const ChannelParams & channelParams,const NetworkParams & nw_params,const std::string br_name,const std::string owe_transition_ifname)453 std::string CreateHostapdConfig(
454 	const IfaceParams& iface_params,
455 	const ChannelParams& channelParams,
456 	const NetworkParams& nw_params,
457 	const std::string br_name,
458 	const std::string owe_transition_ifname)
459 {
460 	if (nw_params.ssid.size() >
461 		static_cast<uint32_t>(
462 		ParamSizeLimits::SSID_MAX_LEN_IN_BYTES)) {
463 		wpa_printf(
464 			MSG_ERROR, "Invalid SSID size: %zu", nw_params.ssid.size());
465 		return "";
466 	}
467 
468 	// SSID string
469 	std::stringstream ss;
470 	ss << std::hex;
471 	ss << std::setfill('0');
472 	for (uint8_t b : nw_params.ssid) {
473 		ss << std::setw(2) << static_cast<unsigned int>(b);
474 	}
475 	const std::string ssid_as_string = ss.str();
476 
477 	// Encryption config string
478 	uint32_t band = 0;
479 	band |= static_cast<uint32_t>(channelParams.bandMask);
480 	bool is_2Ghz_band_only = band == static_cast<uint32_t>(band2Ghz);
481 	bool is_6Ghz_band_only = band == static_cast<uint32_t>(band6Ghz);
482 	bool is_60Ghz_band_only = band == static_cast<uint32_t>(band60Ghz);
483 	std::string encryption_config_as_string;
484 	switch (nw_params.encryptionType) {
485 	case EncryptionType::NONE:
486 		// no security params
487 		break;
488 	case EncryptionType::WPA:
489 		if (!validatePassphrase(
490 			nw_params.passphrase.size(),
491 			static_cast<uint32_t>(ParamSizeLimits::
492 				WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES),
493 			static_cast<uint32_t>(ParamSizeLimits::
494 				WPA2_PSK_PASSPHRASE_MAX_LEN_IN_BYTES))) {
495 			return "";
496 		}
497 		encryption_config_as_string = StringPrintf(
498 			"wpa=3\n"
499 			"wpa_pairwise=%s\n"
500 			"wpa_passphrase=%s",
501 			is_60Ghz_band_only ? "GCMP" : "TKIP CCMP",
502 			nw_params.passphrase.c_str());
503 		break;
504 	case EncryptionType::WPA2:
505 		if (!validatePassphrase(
506 			nw_params.passphrase.size(),
507 			static_cast<uint32_t>(ParamSizeLimits::
508 				WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES),
509 			static_cast<uint32_t>(ParamSizeLimits::
510 				WPA2_PSK_PASSPHRASE_MAX_LEN_IN_BYTES))) {
511 			return "";
512 		}
513 		encryption_config_as_string = StringPrintf(
514 			"wpa=2\n"
515 			"rsn_pairwise=%s\n"
516 #ifdef ENABLE_HOSTAPD_CONFIG_80211W_MFP_OPTIONAL
517 			"ieee80211w=1\n"
518 #endif
519 			"wpa_passphrase=%s",
520 			is_60Ghz_band_only ? "GCMP" : "CCMP",
521 			nw_params.passphrase.c_str());
522 		break;
523 	case EncryptionType::WPA3_SAE_TRANSITION:
524 		if (!validatePassphrase(
525 			nw_params.passphrase.size(),
526 			static_cast<uint32_t>(ParamSizeLimits::
527 				WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES),
528 			static_cast<uint32_t>(ParamSizeLimits::
529 				WPA2_PSK_PASSPHRASE_MAX_LEN_IN_BYTES))) {
530 			return "";
531 		}
532 		// WPA3 transition mode or SAE+WPA_PSK key management(AKM) is not allowed in 6GHz.
533 		// Auto-convert any such configurations to SAE.
534 		if ((band & band6Ghz) != 0) {
535 			wpa_printf(MSG_INFO, "WPA3_SAE_TRANSITION configured in 6GHz band."
536 				   "Enable only SAE in key_mgmt");
537 			encryption_config_as_string = StringPrintf(
538 				"wpa=2\n"
539 				"rsn_pairwise=CCMP\n"
540 				"wpa_key_mgmt=%s\n"
541 				"ieee80211w=2\n"
542 				"sae_require_mfp=2\n"
543 				"sae_pwe=%d\n"
544 				"sae_password=%s",
545 #ifdef CONFIG_IEEE80211BE
546 				iface_params.hwModeParams.enable80211BE ?
547 					"SAE SAE-EXT-KEY" : "SAE",
548 #else
549 					"SAE",
550 #endif
551 				is_6Ghz_band_only ? 1 : 2,
552 				nw_params.passphrase.c_str());
553 		} else {
554 			encryption_config_as_string = StringPrintf(
555 				"wpa=2\n"
556 				"rsn_pairwise=%s\n"
557 				"wpa_key_mgmt=%s\n"
558 				"ieee80211w=1\n"
559 				"sae_require_mfp=1\n"
560 				"wpa_passphrase=%s\n"
561 				"sae_password=%s",
562 				is_60Ghz_band_only ? "GCMP" : "CCMP",
563 #ifdef CONFIG_IEEE80211BE
564 				iface_params.hwModeParams.enable80211BE ?
565 					"WPA-PSK SAE SAE-EXT-KEY" : "WPA-PSK SAE",
566 #else
567 					"WPA-PSK SAE",
568 #endif
569 				nw_params.passphrase.c_str(),
570 				nw_params.passphrase.c_str());
571                 }
572 		break;
573 	case EncryptionType::WPA3_SAE:
574 		if (!validatePassphrase(nw_params.passphrase.size(), 1, -1)) {
575 			return "";
576 		}
577 		encryption_config_as_string = StringPrintf(
578 			"wpa=2\n"
579 			"rsn_pairwise=%s\n"
580 			"wpa_key_mgmt=%s\n"
581 			"ieee80211w=2\n"
582 			"sae_require_mfp=2\n"
583 			"sae_pwe=%d\n"
584 			"sae_password=%s",
585 			is_60Ghz_band_only ? "GCMP" : "CCMP",
586 #ifdef CONFIG_IEEE80211BE
587 			iface_params.hwModeParams.enable80211BE ? "SAE SAE-EXT-KEY" : "SAE",
588 #else
589 			"SAE",
590 #endif
591 			is_6Ghz_band_only ? 1 : 2,
592 			nw_params.passphrase.c_str());
593 		break;
594 	case EncryptionType::WPA3_OWE_TRANSITION:
595 		encryption_config_as_string = StringPrintf(
596 			"wpa=2\n"
597 			"rsn_pairwise=%s\n"
598 			"wpa_key_mgmt=OWE\n"
599 			"ieee80211w=2",
600 			is_60Ghz_band_only ? "GCMP" : "CCMP");
601 		break;
602 	case EncryptionType::WPA3_OWE:
603 		encryption_config_as_string = StringPrintf(
604 			"wpa=2\n"
605 			"rsn_pairwise=%s\n"
606 			"wpa_key_mgmt=OWE\n"
607 			"ieee80211w=2",
608 			is_60Ghz_band_only ? "GCMP" : "CCMP");
609 		break;
610 	default:
611 		wpa_printf(MSG_ERROR, "Unknown encryption type");
612 		return "";
613 	}
614 
615 	std::string channel_config_as_string;
616 	bool isFirst = true;
617 	if (channelParams.enableAcs) {
618 		std::string freqList_as_string;
619 		for (const auto &range :
620 			channelParams.acsChannelFreqRangesMhz) {
621 			if (!isFirst) {
622 				freqList_as_string += ",";
623 			}
624 			isFirst = false;
625 
626 			if (range.startMhz != range.endMhz) {
627 				freqList_as_string +=
628 					StringPrintf("%d-%d", range.startMhz, range.endMhz);
629 			} else {
630 				freqList_as_string += StringPrintf("%d", range.startMhz);
631 			}
632 		}
633 		channel_config_as_string = StringPrintf(
634 			"channel=0\n"
635 			"acs_exclude_dfs=%d\n"
636 			"freqlist=%s",
637 			channelParams.acsShouldExcludeDfs,
638 			freqList_as_string.c_str());
639 	} else {
640 		int op_class = getOpClassForChannel(
641 			channelParams.channel,
642 			band,
643 			iface_params.hwModeParams.enable80211N,
644 			iface_params.hwModeParams.enable80211AC);
645 		channel_config_as_string = StringPrintf(
646 			"channel=%d\n"
647 			"op_class=%d",
648 			channelParams.channel, op_class);
649 	}
650 
651 	std::string hw_mode_as_string;
652 	std::string enable_edmg_as_string;
653 	std::string edmg_channel_as_string;
654 	bool is_60Ghz_used = false;
655 
656 	if (((band & band60Ghz) != 0)) {
657 		hw_mode_as_string = "hw_mode=ad";
658 		if (iface_params.hwModeParams.enableEdmg) {
659 			enable_edmg_as_string = "enable_edmg=1";
660 			edmg_channel_as_string = StringPrintf(
661 				"edmg_channel=%d",
662 				channelParams.channel);
663 		}
664 		is_60Ghz_used = true;
665 	} else if ((band & band2Ghz) != 0) {
666 		if (((band & band5Ghz) != 0)
667 		    || ((band & band6Ghz) != 0)) {
668 			hw_mode_as_string = "hw_mode=any";
669 		} else {
670 			hw_mode_as_string = "hw_mode=g";
671 		}
672 	} else if (((band & band5Ghz) != 0)
673 		    || ((band & band6Ghz) != 0)) {
674 			hw_mode_as_string = "hw_mode=a";
675 	} else {
676 		wpa_printf(MSG_ERROR, "Invalid band");
677 		return "";
678 	}
679 
680 	std::string he_params_as_string;
681 #ifdef CONFIG_IEEE80211AX
682 	if (iface_params.hwModeParams.enable80211AX && !is_60Ghz_used) {
683 		he_params_as_string = StringPrintf(
684 			"ieee80211ax=1\n"
685 			"he_su_beamformer=%d\n"
686 			"he_su_beamformee=%d\n"
687 			"he_mu_beamformer=%d\n"
688 			"he_twt_required=%d\n",
689 			iface_params.hwModeParams.enableHeSingleUserBeamformer ? 1 : 0,
690 			iface_params.hwModeParams.enableHeSingleUserBeamformee ? 1 : 0,
691 			iface_params.hwModeParams.enableHeMultiUserBeamformer ? 1 : 0,
692 			iface_params.hwModeParams.enableHeTargetWakeTime ? 1 : 0);
693 	} else {
694 		he_params_as_string = "ieee80211ax=0";
695 	}
696 #endif /* CONFIG_IEEE80211AX */
697 	std::string eht_params_as_string;
698 #ifdef CONFIG_IEEE80211BE
699 	if (iface_params.hwModeParams.enable80211BE && !is_60Ghz_used) {
700 		eht_params_as_string = "ieee80211be=1\n";
701 		if (areAidlServiceAndClientAtLeastVersion(2)) {
702 			std::string interface_mac_addr = getInterfaceMacAddress(
703 					iface_params.usesMlo ? br_name : iface_params.name);
704 			if (interface_mac_addr.empty()) {
705 				wpa_printf(MSG_ERROR,
706 				    "Unable to set interface mac address as bssid for 11BE SAP");
707 				return "";
708 			}
709             if (iface_params.usesMlo) {
710                 eht_params_as_string += StringPrintf(
711                     "mld_addr=%s\n"
712                     "mld_ap=1",
713                     interface_mac_addr.c_str());
714             } else {
715                 eht_params_as_string += StringPrintf(
716                     "bssid=%s\n"
717                     "mld_ap=1",
718                     interface_mac_addr.c_str());
719             }
720 		}
721 		/* TODO set eht_su_beamformer, eht_su_beamformee, eht_mu_beamformer */
722 	} else {
723 		eht_params_as_string = "ieee80211be=0";
724 	}
725 #endif /* CONFIG_IEEE80211BE */
726 
727 	std::string ht_cap_vht_oper_he_oper_eht_oper_chwidth_as_string;
728 	switch (iface_params.hwModeParams.maximumChannelBandwidth) {
729 	case ChannelBandwidth::BANDWIDTH_20:
730 		ht_cap_vht_oper_he_oper_eht_oper_chwidth_as_string = StringPrintf(
731 #ifdef CONFIG_IEEE80211BE
732 			"eht_oper_chwidth=0\n"
733 #endif /* CONFIG_IEEE80211BE */
734 #ifdef CONFIG_IEEE80211AX
735 			"he_oper_chwidth=0\n"
736 #endif
737 			"vht_oper_chwidth=0\n"
738 			"%s", (band & band6Ghz) ? "op_class=131" : "");
739 		break;
740 	case ChannelBandwidth::BANDWIDTH_40:
741 		ht_cap_vht_oper_he_oper_eht_oper_chwidth_as_string = StringPrintf(
742 			"ht_capab=[HT40+]\n"
743 #ifdef CONFIG_IEEE80211BE
744 			"eht_oper_chwidth=0\n"
745 #endif /* CONFIG_IEEE80211BE */
746 #ifdef CONFIG_IEEE80211AX
747 			"he_oper_chwidth=0\n"
748 #endif
749 			"vht_oper_chwidth=0\n"
750 			"%s", (band & band6Ghz) ? "op_class=132" : "");
751 		break;
752 	case ChannelBandwidth::BANDWIDTH_80:
753 		ht_cap_vht_oper_he_oper_eht_oper_chwidth_as_string = StringPrintf(
754 			"ht_capab=[HT40+]\n"
755 #ifdef CONFIG_IEEE80211BE
756 			"eht_oper_chwidth=%d\n"
757 #endif /* CONFIG_IEEE80211BE */
758 #ifdef CONFIG_IEEE80211AX
759 			"he_oper_chwidth=%d\n"
760 #endif
761 			"vht_oper_chwidth=%d\n"
762 			"%s",
763 #ifdef CONFIG_IEEE80211BE
764 			(iface_params.hwModeParams.enable80211BE && !is_60Ghz_used) ? 1 : 0,
765 #endif
766 #ifdef CONFIG_IEEE80211AX
767 			(iface_params.hwModeParams.enable80211AX && !is_60Ghz_used) ? 1 : 0,
768 #endif
769 			iface_params.hwModeParams.enable80211AC ? 1 : 0,
770 			(band & band6Ghz) ? "op_class=133" : "");
771 		break;
772 	case ChannelBandwidth::BANDWIDTH_160:
773 		ht_cap_vht_oper_he_oper_eht_oper_chwidth_as_string = StringPrintf(
774 			"ht_capab=[HT40+]\n"
775 #ifdef CONFIG_IEEE80211BE
776 			"eht_oper_chwidth=%d\n"
777 #endif /* CONFIG_IEEE80211BE */
778 #ifdef CONFIG_IEEE80211AX
779 			"he_oper_chwidth=%d\n"
780 #endif
781 			"vht_oper_chwidth=%d\n"
782 			"%s",
783 #ifdef CONFIG_IEEE80211BE
784 			(iface_params.hwModeParams.enable80211BE && !is_60Ghz_used) ? 2 : 0,
785 #endif
786 #ifdef CONFIG_IEEE80211AX
787 			(iface_params.hwModeParams.enable80211AX && !is_60Ghz_used) ? 2 : 0,
788 #endif
789 			iface_params.hwModeParams.enable80211AC ? 2 : 0,
790 			(band & band6Ghz) ? "op_class=134" : "");
791 		break;
792 	default:
793 		if (!is_2Ghz_band_only && !is_60Ghz_used) {
794 			if (iface_params.hwModeParams.enable80211AC) {
795 				ht_cap_vht_oper_he_oper_eht_oper_chwidth_as_string =
796 					"ht_capab=[HT40+]\n"
797 					"vht_oper_chwidth=1\n";
798 			}
799 			if (band & band6Ghz) {
800 #ifdef CONFIG_IEEE80211BE
801 				if (iface_params.hwModeParams.enable80211BE)
802 					ht_cap_vht_oper_he_oper_eht_oper_chwidth_as_string += "op_class=137\n";
803 				else
804 					ht_cap_vht_oper_he_oper_eht_oper_chwidth_as_string += "op_class=134\n";
805 #else /* CONFIG_IEEE80211BE */
806 				ht_cap_vht_oper_he_oper_eht_oper_chwidth_as_string += "op_class=134\n";
807 #endif /* CONFIG_IEEE80211BE */
808 			}
809 #ifdef CONFIG_IEEE80211AX
810 			if (iface_params.hwModeParams.enable80211AX) {
811 				ht_cap_vht_oper_he_oper_eht_oper_chwidth_as_string += "he_oper_chwidth=1\n";
812 			}
813 #endif
814 #ifdef CONFIG_IEEE80211BE
815 			if (iface_params.hwModeParams.enable80211BE) {
816 				ht_cap_vht_oper_he_oper_eht_oper_chwidth_as_string += "eht_oper_chwidth=1";
817 			}
818 #endif
819 		}
820 		break;
821 	}
822 
823 #ifdef CONFIG_INTERWORKING
824 	std::string access_network_params_as_string;
825 	if (nw_params.isMetered) {
826 		access_network_params_as_string = StringPrintf(
827 			"interworking=1\n"
828 			"access_network_type=2\n"); // CHARGEABLE_PUBLIC_NETWORK
829 	} else {
830 	    access_network_params_as_string = StringPrintf(
831 			"interworking=0\n");
832 	}
833 #endif /* CONFIG_INTERWORKING */
834 
835 	std::string bridge_as_string;
836 	if (!br_name.empty() && !iface_params.usesMlo) {
837 		bridge_as_string = StringPrintf("bridge=%s", br_name.c_str());
838 	}
839 
840 	// vendor_elements string
841 	std::string vendor_elements_as_string;
842 	if (nw_params.vendorElements.size() > 0) {
843 		std::stringstream ss;
844 		ss << std::hex;
845 		ss << std::setfill('0');
846 		for (uint8_t b : nw_params.vendorElements) {
847 			ss << std::setw(2) << static_cast<unsigned int>(b);
848 		}
849 		vendor_elements_as_string = StringPrintf("vendor_elements=%s", ss.str().c_str());
850 	}
851 
852 	std::string owe_transition_ifname_as_string;
853 	if (!owe_transition_ifname.empty()) {
854 		owe_transition_ifname_as_string = StringPrintf(
855 			"owe_transition_ifname=%s", owe_transition_ifname.c_str());
856 	}
857 
858 	std::string ap_isolation_as_string = StringPrintf("ap_isolate=%s",
859 			isAidlServiceVersionAtLeast(3) && nw_params.isClientIsolationEnabled ?
860 			"1" : "0");
861 
862 	// Overlay for LOHS (unmetered SoftAP)
863 	std::string overlay_path = resolveVendorConfPath(kUnmeteredIfaceOverlayPath);
864 	std::string overlay_string;
865 	if (!nw_params.isMetered
866 			&& 0 == access(overlay_path.c_str(), R_OK)
867 			&& !ReadFileToString(overlay_path, &overlay_string)) {
868 		logHostapdConfigError(errno, overlay_path);
869 		return "";
870 	}
871 	std::string sanitized_overlay = "";
872 	std::istringstream overlay_stream(overlay_string);
873 	for (std::string line; std::getline(overlay_stream, line);) {
874 		std::string overlay_key = trimWhitespace(line.substr(0, line.find("=")));
875 		if (kOverlayableKeys.contains(overlay_key)) {
876 			sanitized_overlay.append(line + "\n");
877 		}
878 	}
879 
880 	return StringPrintf(
881 		"%s\n"
882 		"interface=%s\n"
883 		"driver=nl80211\n"
884 		"ctrl_interface=/data/vendor/wifi/hostapd/ctrl\n"
885 		// ssid2 signals to hostapd that the value is not a literal value
886 		// for use as a SSID.  In this case, we're giving it a hex
887 		// std::string and hostapd needs to expect that.
888 		"ssid2=%s\n"
889 		"%s\n"
890 		"ieee80211n=%d\n"
891 		"ieee80211ac=%d\n"
892 		"%s\n"
893 		"%s\n"
894 		"%s\n"
895 		"%s\n"
896 		"ignore_broadcast_ssid=%d\n"
897 		"wowlan_triggers=any\n"
898 #ifdef CONFIG_INTERWORKING
899 		"%s\n"
900 #endif /* CONFIG_INTERWORKING */
901 		"%s\n"
902 		"%s\n"
903 		"%s\n"
904 		"%s\n"
905 		"%s\n"
906 		"%s\n"
907 		"%s\n",
908 		sanitized_overlay.c_str(),
909 		iface_params.usesMlo ? br_name.c_str() : iface_params.name.c_str(),
910 		ssid_as_string.c_str(),
911 		channel_config_as_string.c_str(),
912 		iface_params.hwModeParams.enable80211N ? 1 : 0,
913 		iface_params.hwModeParams.enable80211AC ? 1 : 0,
914 		he_params_as_string.c_str(),
915 		eht_params_as_string.c_str(),
916 		hw_mode_as_string.c_str(), ht_cap_vht_oper_he_oper_eht_oper_chwidth_as_string.c_str(),
917 		nw_params.isHidden ? 1 : 0,
918 #ifdef CONFIG_INTERWORKING
919 		access_network_params_as_string.c_str(),
920 #endif /* CONFIG_INTERWORKING */
921 		encryption_config_as_string.c_str(),
922 		bridge_as_string.c_str(),
923 		owe_transition_ifname_as_string.c_str(),
924 		enable_edmg_as_string.c_str(),
925 		edmg_channel_as_string.c_str(),
926 		vendor_elements_as_string.c_str(),
927 		ap_isolation_as_string.c_str());
928 }
929 
getGeneration(hostapd_hw_modes * current_mode,bool is_conf_enable_11ax,bool is_conf_enable_11be)930 Generation getGeneration(hostapd_hw_modes *current_mode,
931 						 bool is_conf_enable_11ax,
932 						 bool is_conf_enable_11be)
933 {
934 	wpa_printf(MSG_DEBUG, "getGeneration hwmode=%d, ht_enabled=%d,"
935 			" vht_enabled=%d, he_supported=%d, eht_supported=%d,"
936 			" ieee80211ax = %d, ieee80211be=%d",
937 			current_mode->mode, current_mode->ht_capab != 0,
938 			current_mode->vht_capab != 0,
939 			current_mode->he_capab[IEEE80211_MODE_AP].he_supported,
940 			current_mode->eht_capab[IEEE80211_MODE_AP].eht_supported,
941 			is_conf_enable_11ax,
942 			is_conf_enable_11be);
943 	switch (current_mode->mode) {
944 	case HOSTAPD_MODE_IEEE80211B:
945 		return Generation::WIFI_STANDARD_LEGACY;
946 	case HOSTAPD_MODE_IEEE80211G:
947 		if (is_conf_enable_11be
948 			&& current_mode->eht_capab[IEEE80211_MODE_AP].eht_supported) {
949 			return Generation::WIFI_STANDARD_11BE;
950 		}
951 		if (is_conf_enable_11ax
952 			&& current_mode->he_capab[IEEE80211_MODE_AP].he_supported) {
953 			return Generation::WIFI_STANDARD_11AX;
954 		}
955 		return current_mode->ht_capab == 0 ?
956 				Generation::WIFI_STANDARD_LEGACY : Generation::WIFI_STANDARD_11N;
957 	case HOSTAPD_MODE_IEEE80211A:
958 		if (is_conf_enable_11be
959 			&& current_mode->eht_capab[IEEE80211_MODE_AP].eht_supported) {
960 			return Generation::WIFI_STANDARD_11BE;
961 		}
962 		if (is_conf_enable_11ax
963 			&& current_mode->he_capab[IEEE80211_MODE_AP].he_supported) {
964 			return Generation::WIFI_STANDARD_11AX;
965 		}
966 		return current_mode->vht_capab == 0 ?
967 		       Generation::WIFI_STANDARD_11N : Generation::WIFI_STANDARD_11AC;
968 	case HOSTAPD_MODE_IEEE80211AD:
969 		return Generation::WIFI_STANDARD_11AD;
970 	default:
971 		return Generation::WIFI_STANDARD_UNKNOWN;
972 	}
973 }
974 
getChannelBandwidth(struct hostapd_config * iconf)975 ChannelBandwidth getChannelBandwidth(struct hostapd_config *iconf)
976 {
977 	wpa_printf(MSG_DEBUG, "getChannelBandwidth %d, isHT=%d, isHT40=%d",
978 		   iconf->vht_oper_chwidth, iconf->ieee80211n,
979 		   iconf->secondary_channel);
980 	switch (iconf->vht_oper_chwidth) {
981 	case CONF_OPER_CHWIDTH_80MHZ:
982 		return ChannelBandwidth::BANDWIDTH_80;
983 	case CONF_OPER_CHWIDTH_80P80MHZ:
984 		return ChannelBandwidth::BANDWIDTH_80P80;
985 		break;
986 	case CONF_OPER_CHWIDTH_160MHZ:
987 		return ChannelBandwidth::BANDWIDTH_160;
988 		break;
989 	case CONF_OPER_CHWIDTH_USE_HT:
990 		if (iconf->ieee80211n) {
991 			return iconf->secondary_channel != 0 ?
992 				ChannelBandwidth::BANDWIDTH_40 : ChannelBandwidth::BANDWIDTH_20;
993 		}
994 		return ChannelBandwidth::BANDWIDTH_20_NOHT;
995 	case CONF_OPER_CHWIDTH_2160MHZ:
996 		return ChannelBandwidth::BANDWIDTH_2160;
997 	case CONF_OPER_CHWIDTH_4320MHZ:
998 		return ChannelBandwidth::BANDWIDTH_4320;
999 	case CONF_OPER_CHWIDTH_6480MHZ:
1000 		return ChannelBandwidth::BANDWIDTH_6480;
1001 	case CONF_OPER_CHWIDTH_8640MHZ:
1002 		return ChannelBandwidth::BANDWIDTH_8640;
1003 	default:
1004 		return ChannelBandwidth::BANDWIDTH_INVALID;
1005 	}
1006 }
1007 
getStaInfoByMacAddr(const struct hostapd_data * iface_hapd,const u8 * mac_addr)1008 std::optional<struct sta_info*> getStaInfoByMacAddr(const struct hostapd_data* iface_hapd,
1009 		const u8 *mac_addr) {
1010 	if (iface_hapd == nullptr || mac_addr == nullptr){
1011 		wpa_printf(MSG_ERROR, "nullptr passsed to getStaInfoByMacAddr!");
1012 		return std::nullopt;
1013 	}
1014 
1015 	for (struct sta_info* sta_ptr = iface_hapd->sta_list; sta_ptr; sta_ptr = sta_ptr->next) {
1016 		int res;
1017 		res = memcmp(sta_ptr->addr, mac_addr, ETH_ALEN);
1018 		if (res == 0) {
1019 			return sta_ptr;
1020 		}
1021 	}
1022 	return std::nullopt;
1023 }
1024 
forceStaDisconnection(struct hostapd_data * hapd,const std::vector<uint8_t> & client_address,const uint16_t reason_code)1025 bool forceStaDisconnection(struct hostapd_data* hapd,
1026 			   const std::vector<uint8_t>& client_address,
1027 			   const uint16_t reason_code) {
1028 	if (client_address.size() != ETH_ALEN) {
1029 		return false;
1030 	}
1031 
1032 	auto sta_ptr_optional = getStaInfoByMacAddr(hapd, client_address.data());
1033 	if (sta_ptr_optional.has_value()) {
1034 		wpa_printf(MSG_INFO, "Force client:" MACSTR " disconnect with reason: %d",
1035 				MAC2STR(client_address.data()), reason_code);
1036 		ap_sta_disconnect(hapd, sta_ptr_optional.value(), sta_ptr_optional.value()->addr,
1037 				reason_code);
1038 		return true;
1039 	}
1040 
1041 	return false;
1042 }
1043 
1044 // hostapd core functions accept "C" style function pointers, so use global
1045 // functions to pass to the hostapd core function and store the corresponding
1046 // std::function methods to be invoked.
1047 //
1048 // NOTE: Using the pattern from the vendor HAL (wifi_legacy_hal.cpp).
1049 //
1050 // Callback to be invoked once setup is complete
1051 std::function<void(struct hostapd_data*)> on_setup_complete_internal_callback;
onAsyncSetupCompleteCb(void * ctx)1052 void onAsyncSetupCompleteCb(void* ctx)
1053 {
1054 	struct hostapd_data* iface_hapd = (struct hostapd_data*)ctx;
1055 	if (on_setup_complete_internal_callback) {
1056 		on_setup_complete_internal_callback(iface_hapd);
1057 		// Invalidate this callback since we don't want this firing
1058 		// again in single AP mode.
1059 		if (strlen(iface_hapd->conf->bridge) > 0) {
1060 			on_setup_complete_internal_callback = nullptr;
1061 		}
1062 	}
1063 }
1064 
1065 // Callback to be invoked on hotspot client connection/disconnection
1066 std::function<void(struct hostapd_data*, const u8 *mac_addr, int authorized,
1067 		const u8 *p2p_dev_addr)> on_sta_authorized_internal_callback;
onAsyncStaAuthorizedCb(void * ctx,const u8 * mac_addr,int authorized,const u8 * p2p_dev_addr,const u8 * ip)1068 void onAsyncStaAuthorizedCb(void* ctx, const u8 *mac_addr, int authorized,
1069 		const u8 *p2p_dev_addr, const u8 *ip)
1070 {
1071 	struct hostapd_data* iface_hapd = (struct hostapd_data*)ctx;
1072 	if (on_sta_authorized_internal_callback) {
1073 		on_sta_authorized_internal_callback(iface_hapd, mac_addr,
1074 			authorized, p2p_dev_addr);
1075 	}
1076 }
1077 
1078 std::function<void(struct hostapd_data*, int level,
1079 			enum wpa_msg_type type, const char *txt,
1080 			size_t len)> on_wpa_msg_internal_callback;
1081 
onAsyncWpaEventCb(void * ctx,int level,enum wpa_msg_type type,const char * txt,size_t len)1082 void onAsyncWpaEventCb(void *ctx, int level,
1083 			enum wpa_msg_type type, const char *txt,
1084 			size_t len)
1085 {
1086 	struct hostapd_data* iface_hapd = (struct hostapd_data*)ctx;
1087 	if (on_wpa_msg_internal_callback) {
1088 		on_wpa_msg_internal_callback(iface_hapd, level,
1089 					type, txt, len);
1090 	}
1091 }
1092 
createStatus(HostapdStatusCode status_code)1093 inline ndk::ScopedAStatus createStatus(HostapdStatusCode status_code) {
1094 	return ndk::ScopedAStatus::fromServiceSpecificError(
1095 		static_cast<int32_t>(status_code));
1096 }
1097 
createStatusWithMsg(HostapdStatusCode status_code,std::string msg)1098 inline ndk::ScopedAStatus createStatusWithMsg(
1099 	HostapdStatusCode status_code, std::string msg)
1100 {
1101 	return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
1102 		static_cast<int32_t>(status_code), msg.c_str());
1103 }
1104 
1105 // Method called by death_notifier_ on client death.
onDeath(void * cookie)1106 void onDeath(void* cookie) {
1107 	wpa_printf(MSG_ERROR, "Client died. Terminating...");
1108 	eloop_terminate();
1109 }
1110 
1111 }  // namespace
1112 
1113 namespace aidl {
1114 namespace android {
1115 namespace hardware {
1116 namespace wifi {
1117 namespace hostapd {
1118 
Hostapd(struct hapd_interfaces * interfaces)1119 Hostapd::Hostapd(struct hapd_interfaces* interfaces)
1120 	: interfaces_(interfaces)
1121 {
1122 	death_notifier_ = AIBinder_DeathRecipient_new(onDeath);
1123 }
1124 
addAccessPoint(const IfaceParams & iface_params,const NetworkParams & nw_params)1125 ::ndk::ScopedAStatus Hostapd::addAccessPoint(
1126 	const IfaceParams& iface_params, const NetworkParams& nw_params)
1127 {
1128 	return addAccessPointInternal(iface_params, nw_params);
1129 }
1130 
removeAccessPoint(const std::string & iface_name)1131 ::ndk::ScopedAStatus Hostapd::removeAccessPoint(const std::string& iface_name)
1132 {
1133 	return removeAccessPointInternal(iface_name);
1134 }
1135 
terminate()1136 ::ndk::ScopedAStatus Hostapd::terminate()
1137 {
1138 	wpa_printf(MSG_INFO, "Terminating...");
1139 	// Clear the callback to avoid IPCThreadState shutdown during the
1140 	// callback event.
1141 	callbacks_.clear();
1142 	eloop_terminate();
1143 	return ndk::ScopedAStatus::ok();
1144 }
1145 
registerCallback(const std::shared_ptr<IHostapdCallback> & callback)1146 ::ndk::ScopedAStatus Hostapd::registerCallback(
1147 	const std::shared_ptr<IHostapdCallback>& callback)
1148 {
1149 	return registerCallbackInternal(callback);
1150 }
1151 
forceClientDisconnect(const std::string & iface_name,const std::vector<uint8_t> & client_address,Ieee80211ReasonCode reason_code)1152 ::ndk::ScopedAStatus Hostapd::forceClientDisconnect(
1153 	const std::string& iface_name, const std::vector<uint8_t>& client_address,
1154 	Ieee80211ReasonCode reason_code)
1155 {
1156 	return forceClientDisconnectInternal(iface_name, client_address, reason_code);
1157 }
1158 
setDebugParams(DebugLevel level)1159 ::ndk::ScopedAStatus Hostapd::setDebugParams(DebugLevel level)
1160 {
1161 	return setDebugParamsInternal(level);
1162 }
1163 
removeLinkFromMultipleLinkBridgedApIface(const std::string & iface_name,const std::string & linkIdentity)1164 ::ndk::ScopedAStatus Hostapd::removeLinkFromMultipleLinkBridgedApIface(
1165         const std::string& iface_name, const std::string& linkIdentity)
1166 {
1167 	return removeLinkFromMultipleLinkBridgedApIfaceInternal(iface_name, linkIdentity);
1168 }
1169 
addAccessPointInternal(const IfaceParams & iface_params,const NetworkParams & nw_params)1170 ::ndk::ScopedAStatus Hostapd::addAccessPointInternal(
1171 	const IfaceParams& iface_params,
1172 	const NetworkParams& nw_params)
1173 {
1174 	int channelParamsSize = iface_params.channelParams.size();
1175 	if (channelParamsSize == 1) {
1176 		// Single AP
1177 		wpa_printf(MSG_INFO, "AddSingleAccessPoint, iface=%s",
1178 			iface_params.name.c_str());
1179 		return addSingleAccessPoint(iface_params, iface_params.channelParams[0],
1180 		    nw_params, "", "");
1181 	} else if (channelParamsSize == 2) {
1182 		// Concurrent APs
1183 		wpa_printf(MSG_INFO, "AddDualAccessPoint, iface=%s",
1184 			iface_params.name.c_str());
1185 		return addConcurrentAccessPoints(iface_params, nw_params);
1186 	}
1187 	return createStatus(HostapdStatusCode::FAILURE_ARGS_INVALID);
1188 }
1189 
generateRandomOweSsid()1190 std::vector<uint8_t>  generateRandomOweSsid()
1191 {
1192 	u8 random[8] = {0};
1193 	os_get_random(random, 8);
1194 
1195 	std::string ssid = StringPrintf("Owe-%s", random);
1196 	wpa_printf(MSG_INFO, "Generated OWE SSID: %s", ssid.c_str());
1197 	std::vector<uint8_t> vssid(ssid.begin(), ssid.end());
1198 
1199 	return vssid;
1200 }
1201 
1202 
1203 // Both of bridged dual APs and MLO AP will be treated as concurrenct APs.
1204 // -----------------------------------------
1205 //                  | br_name     |  instance#1 | instance#2 |
1206 // ___________________________________________________________
1207 // bridged dual APs | ap_br_wlanX |   wlan X    |   wlanY    |
1208 // ___________________________________________________________
1209 // MLO AP           | wlanX       |     0       |     1      |
1210 // ___________________________________________________________
1211 // Both will be added in br_interfaces_[$br_name] and use instance's name
1212 // to be iface_params_new.name to create single Access point.
addConcurrentAccessPoints(const IfaceParams & iface_params,const NetworkParams & nw_params)1213 ::ndk::ScopedAStatus Hostapd::addConcurrentAccessPoints(
1214 	const IfaceParams& iface_params, const NetworkParams& nw_params)
1215 {
1216 	int channelParamsListSize = iface_params.channelParams.size();
1217 	// Get available interfaces in bridge
1218 	std::vector<std::string> managed_instances;
1219 	std::string br_name = StringPrintf("%s", iface_params.name.c_str());
1220 	if (iface_params.usesMlo) {
1221 		// MLO AP is using link id as instance.
1222 		for (std::size_t i = 0; i < iface_params.instanceIdentities->size(); i++) {
1223 			managed_instances.push_back(iface_params.instanceIdentities->at(i)->c_str());
1224 		}
1225 	} else {
1226 		if (!GetInterfacesInBridge(br_name, &managed_instances)) {
1227 			return createStatusWithMsg(HostapdStatusCode::FAILURE_UNKNOWN,
1228 					"Get interfaces in bridge failed.");
1229 		}
1230 	}
1231 	// Either bridged AP or MLO AP should have two instances.
1232 	if (managed_instances.size() < channelParamsListSize) {
1233 		return createStatusWithMsg(HostapdStatusCode::FAILURE_UNKNOWN,
1234 				"Available interfaces less than requested bands");
1235 	}
1236 
1237 	if (iface_params.usesMlo
1238 				&& nw_params.encryptionType == EncryptionType::WPA3_OWE_TRANSITION) {
1239 		return createStatusWithMsg(HostapdStatusCode::FAILURE_UNKNOWN,
1240 				"Invalid encryptionType (OWE transition) for MLO SAP.");
1241 	}
1242 	// start BSS on specified bands
1243 	for (std::size_t i = 0; i < channelParamsListSize; i ++) {
1244 		IfaceParams iface_params_new = iface_params;
1245 		NetworkParams nw_params_new = nw_params;
1246 		std::string owe_transition_ifname = "";
1247 		iface_params_new.name = managed_instances[i];
1248 		if (nw_params.encryptionType == EncryptionType::WPA3_OWE_TRANSITION) {
1249 			if (i == 0 && i+1 < channelParamsListSize) {
1250 				owe_transition_ifname = managed_instances[i+1];
1251 				nw_params_new.encryptionType = EncryptionType::NONE;
1252 			} else {
1253 				owe_transition_ifname = managed_instances[0];
1254 				nw_params_new.isHidden = true;
1255 				nw_params_new.ssid = generateRandomOweSsid();
1256 			}
1257 		}
1258 
1259 		ndk::ScopedAStatus status = addSingleAccessPoint(
1260 		    iface_params_new, iface_params.channelParams[i], nw_params_new,
1261 		    br_name, owe_transition_ifname);
1262 		if (!status.isOk()) {
1263 			wpa_printf(MSG_ERROR, "Failed to addAccessPoint %s",
1264 				   managed_instances[i].c_str());
1265 			return status;
1266 		}
1267 	}
1268 
1269 	if (iface_params.usesMlo) {
1270 		std::size_t i = 0;
1271 		std::size_t j = 0;
1272 		for (i = 0; i < interfaces_->count; i++) {
1273 			struct hostapd_iface *iface = interfaces_->iface[i];
1274 
1275 			for (j = 0; j < iface->num_bss; j++) {
1276 				struct hostapd_data *iface_hapd = iface->bss[j];
1277 				if (hostapd_enable_iface(iface_hapd->iface) < 0) {
1278 					wpa_printf(
1279 					MSG_ERROR, "Enabling interface %s failed on %zu",
1280 						iface_params.name.c_str(), i);
1281 					return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
1282 				}
1283 			}
1284 		}
1285     }
1286 	// Save bridge interface info
1287 	br_interfaces_[br_name] = managed_instances;
1288 	return ndk::ScopedAStatus::ok();
1289 }
1290 
hostapd_get_iface_by_link_id(struct hapd_interfaces * interfaces,const size_t link_id)1291 struct hostapd_data * hostapd_get_iface_by_link_id(struct hapd_interfaces *interfaces,
1292 					const size_t link_id)
1293 {
1294 #ifdef CONFIG_IEEE80211BE
1295 	size_t i, j;
1296 
1297 	for (i = 0; i < interfaces->count; i++) {
1298 		struct hostapd_iface *iface = interfaces->iface[i];
1299 
1300 		for (j = 0; j < iface->num_bss; j++) {
1301 			struct hostapd_data *hapd = iface->bss[j];
1302 
1303 			if (link_id == hapd->mld_link_id)
1304 				return hapd;
1305 		}
1306 	}
1307 #endif /* CONFIG_IEEE80211BE */
1308 	return NULL;
1309 }
1310 
1311 // Both of bridged dual APs and MLO AP will be treated as concurrenct APs.
1312 // -----------------------------------------
1313 //                  | br_name                 |  iface_params.name
1314 // _______________________________________________________________
1315 // bridged dual APs | bridged interface name  |  interface name
1316 // _______________________________________________________________
1317 // MLO AP           | AP interface name       |  mld link id as instance name
1318 // _______________________________________________________________
addSingleAccessPoint(const IfaceParams & iface_params,const ChannelParams & channelParams,const NetworkParams & nw_params,const std::string br_name,const std::string owe_transition_ifname)1319 ::ndk::ScopedAStatus Hostapd::addSingleAccessPoint(
1320 	const IfaceParams& iface_params,
1321 	const ChannelParams& channelParams,
1322 	const NetworkParams& nw_params,
1323 	const std::string br_name,
1324 	const std::string owe_transition_ifname)
1325 {
1326 	if (iface_params.usesMlo) { // the mlo case, iface name is instance name which is mld_link_id
1327 		if (hostapd_get_iface_by_link_id(interfaces_, std::stoi(iface_params.name.c_str()))) {
1328 			wpa_printf(
1329 				MSG_ERROR, "Instance link id %s already present",
1330 				iface_params.name.c_str());
1331 			return createStatus(HostapdStatusCode::FAILURE_IFACE_EXISTS);
1332 		}
1333 #ifdef CONFIG_IEEE80211BE
1334 		// The MLO AP uses the same interface name for all links. Thus, make sure the
1335 		// interface name wasn't used for non-mld AP only when adding a new interface.
1336 		// Also it is valid to have a hostapd_data with the same interface name when adding
1337 		// the second link instance.
1338 		struct hostapd_data* hapd = hostapd_get_iface(interfaces_, br_name.c_str());
1339 		if (hapd && !hapd->conf->mld_ap) {
1340 			wpa_printf(
1341 				MSG_ERROR, "Instance interface %s already present",
1342 						br_name.c_str());
1343 			return createStatus(HostapdStatusCode::FAILURE_IFACE_EXISTS);
1344 		}
1345 #endif
1346 	} else {
1347 		if (hostapd_get_iface(interfaces_, iface_params.name.c_str())) {
1348 			wpa_printf(
1349 				MSG_ERROR, "Instance interface %s already present",
1350 					iface_params.name.c_str());
1351 			return createStatus(HostapdStatusCode::FAILURE_IFACE_EXISTS);
1352 		}
1353 	}
1354 	const auto conf_params = CreateHostapdConfig(iface_params, channelParams, nw_params,
1355 					br_name, owe_transition_ifname);
1356 	if (conf_params.empty()) {
1357 		wpa_printf(MSG_ERROR, "Failed to create config params");
1358 		return createStatus(HostapdStatusCode::FAILURE_ARGS_INVALID);
1359 	}
1360 	const auto conf_file_path =
1361 		WriteHostapdConfig(iface_params.name, conf_params, br_name, iface_params.usesMlo);
1362 	if (conf_file_path.empty()) {
1363 		wpa_printf(MSG_ERROR, "Failed to write config file");
1364 		return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
1365 	}
1366 	std::string add_iface_param_str = StringPrintf(
1367 		"%s config=%s", iface_params.usesMlo ? br_name.c_str(): iface_params.name.c_str(),
1368 		conf_file_path.c_str());
1369 	std::vector<char> add_iface_param_vec(
1370 		add_iface_param_str.begin(), add_iface_param_str.end() + 1);
1371 	if (hostapd_add_iface(interfaces_, add_iface_param_vec.data()) < 0) {
1372 		wpa_printf(
1373 			MSG_ERROR, "Adding hostapd iface %s failed",
1374 			add_iface_param_str.c_str());
1375 		return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
1376 	}
1377 
1378 	// find the iface and set up callback.
1379 	struct hostapd_data* iface_hapd = iface_params.usesMlo ?
1380 		hostapd_get_iface_by_link_id(interfaces_, std::stoi(iface_params.name.c_str())) :
1381 		hostapd_get_iface(interfaces_, iface_params.name.c_str());
1382 	WPA_ASSERT(iface_hapd != nullptr && iface_hapd->iface != nullptr);
1383 	if (iface_params.usesMlo) {
1384 		memcmp(iface_hapd->conf->iface, br_name.c_str(), br_name.size());
1385 	}
1386 
1387 	// Callback discrepancy between bridged dual APs and MLO AP
1388 	// Note: Only bridged dual APs will have "iface_hapd->conf->bridge" and
1389 	// Only MLO AP will have "iface_hapd->mld_link_id"
1390 	// Register the setup complete callbacks
1391 	// -----------------------------------------
1392 	//                    |   bridged dual APs     | bridged single link MLO | MLO SAP
1393 	// _________________________________________________________________________________________
1394 	// hapd->conf->bridge | bridged interface name |  bridged interface nam  | N/A
1395 	// _________________________________________________________________________________________
1396 	// hapd->conf->iface  | AP interface name      |  AP interface name      | AP interface name
1397 	// _________________________________________________________________________________________
1398 	// hapd->mld_link_id  | 0 (default value)      |      link id (0)        | link id (0 or 1)
1399 	// _________________________________________________________________________________________
1400 	// hapd->mld_ap       |         0              |            1            |     1
1401 	on_setup_complete_internal_callback =
1402 		[this](struct hostapd_data* iface_hapd) {
1403 			wpa_printf(
1404 			MSG_INFO, "AP interface setup completed - state %s",
1405 			hostapd_state_text(iface_hapd->iface->state));
1406 			if (iface_hapd->iface->state == HAPD_IFACE_DISABLED) {
1407 				// Invoke the failure callback on all registered
1408 				// clients.
1409 				std::string instanceName = iface_hapd->conf->iface;
1410 #ifdef CONFIG_IEEE80211BE
1411 				if (iface_hapd->conf->mld_ap
1412 						&& strlen(iface_hapd->conf->bridge) == 0) {
1413 					instanceName = std::to_string(iface_hapd->mld_link_id);
1414 				}
1415 #endif /* CONFIG_IEEE80211BE */
1416 				for (const auto& callback : callbacks_) {
1417 					auto status = callback->onFailure(
1418 						strlen(iface_hapd->conf->bridge) > 0 ?
1419 						iface_hapd->conf->bridge : iface_hapd->conf->iface,
1420 							    instanceName);
1421 					if (!status.isOk()) {
1422 						wpa_printf(MSG_ERROR, "Failed to invoke onFailure");
1423 					}
1424 				}
1425 			}
1426 		};
1427 
1428 	// Register for new client connect/disconnect indication.
1429 	on_sta_authorized_internal_callback =
1430 		[this](struct hostapd_data* iface_hapd, const u8 *mac_addr,
1431 			int authorized, const u8 *p2p_dev_addr) {
1432 		wpa_printf(MSG_DEBUG, "notify client " MACSTR " %s",
1433 				MAC2STR(mac_addr),
1434 				(authorized) ? "Connected" : "Disconnected");
1435 		ClientInfo info;
1436 		info.ifaceName = strlen(iface_hapd->conf->bridge) > 0 ?
1437 			iface_hapd->conf->bridge : iface_hapd->conf->iface;
1438 		std::string instanceName = iface_hapd->conf->iface;
1439 #ifdef CONFIG_IEEE80211BE
1440 		if (iface_hapd->conf->mld_ap
1441 				&& strlen(iface_hapd->conf->bridge) == 0) {
1442 			instanceName = std::to_string(iface_hapd->mld_link_id);
1443 		}
1444 #endif /* CONFIG_IEEE80211BE */
1445 		info.apIfaceInstance = instanceName;
1446 		info.clientAddress.assign(mac_addr, mac_addr + ETH_ALEN);
1447 		info.isConnected = authorized;
1448 		if(isAidlServiceVersionAtLeast(3) && !authorized) {
1449 			u16 disconnect_reason_code = WLAN_REASON_UNSPECIFIED;
1450 			auto sta_ptr_optional = getStaInfoByMacAddr(iface_hapd, mac_addr);
1451 			if (sta_ptr_optional.has_value()){
1452 				disconnect_reason_code = sta_ptr_optional.value()->deauth_reason;
1453 			}
1454 			info.disconnectReasonCode =
1455 					static_cast<common::DeauthenticationReasonCode>(disconnect_reason_code);
1456 		}
1457 		for (const auto &callback : callbacks_) {
1458 			auto status = callback->onConnectedClientsChanged(info);
1459 			if (!status.isOk()) {
1460 				wpa_printf(MSG_ERROR, "Failed to invoke onConnectedClientsChanged");
1461 			}
1462 		}
1463 		};
1464 
1465 	// Register for wpa_event which used to get channel switch event
1466 	on_wpa_msg_internal_callback =
1467 		[this](struct hostapd_data* iface_hapd, int level,
1468 			enum wpa_msg_type type, const char *txt,
1469 			size_t len) {
1470 		wpa_printf(MSG_DEBUG, "Receive wpa msg : %s", txt);
1471 		if (os_strncmp(txt, AP_EVENT_ENABLED,
1472 					strlen(AP_EVENT_ENABLED)) == 0 ||
1473 			os_strncmp(txt, WPA_EVENT_CHANNEL_SWITCH,
1474 					strlen(WPA_EVENT_CHANNEL_SWITCH)) == 0) {
1475 			std::string instanceName = iface_hapd->conf->iface;
1476 #ifdef CONFIG_IEEE80211BE
1477 			if (iface_hapd->conf->mld_ap && strlen(iface_hapd->conf->bridge) == 0) {
1478 				instanceName = std::to_string(iface_hapd->mld_link_id);
1479 			}
1480 #endif /* CONFIG_IEEE80211BE */
1481 			ApInfo info;
1482 			info.ifaceName = strlen(iface_hapd->conf->bridge) > 0 ?
1483 				iface_hapd->conf->bridge : iface_hapd->conf->iface,
1484 			info.apIfaceInstance = instanceName;
1485 			info.freqMhz = iface_hapd->iface->freq;
1486 			info.channelBandwidth = getChannelBandwidth(iface_hapd->iconf);
1487 			info.generation =
1488 				getGeneration(iface_hapd->iface->current_mode,
1489 					iface_hapd->iconf->ieee80211ax, iface_hapd->iconf->ieee80211be);
1490 			info.apIfaceInstanceMacAddress.assign(iface_hapd->own_addr,
1491 				iface_hapd->own_addr + ETH_ALEN);
1492 #ifdef CONFIG_IEEE80211BE
1493 			if (iface_hapd->conf->mld_ap) {
1494 				info.mldMacAddress = macAddrToArray(iface_hapd->mld->mld_addr);
1495 			}
1496 #endif /* CONFIG_IEEE80211BE */
1497 			for (const auto &callback : callbacks_) {
1498 				auto status = callback->onApInstanceInfoChanged(info);
1499 				if (!status.isOk()) {
1500 					wpa_printf(MSG_ERROR,
1501 						   "Failed to invoke onApInstanceInfoChanged");
1502 				}
1503 			}
1504 		} else if (os_strncmp(txt, AP_EVENT_DISABLED, strlen(AP_EVENT_DISABLED)) == 0
1505                            || os_strncmp(txt, INTERFACE_DISABLED, strlen(INTERFACE_DISABLED)) == 0)
1506 		{
1507 			std::string instanceName = iface_hapd->conf->iface;
1508 #ifdef CONFIG_IEEE80211BE
1509 			if (iface_hapd->conf->mld_ap && strlen(iface_hapd->conf->bridge) == 0) {
1510 				instanceName = std::to_string(iface_hapd->mld_link_id);
1511 			}
1512 #endif /* CONFIG_IEEE80211BE */
1513 			// Invoke the failure callback on all registered clients.
1514 			for (const auto& callback : callbacks_) {
1515 				auto status =
1516 					callback->onFailure(strlen(iface_hapd->conf->bridge) > 0 ?
1517 					iface_hapd->conf->bridge : iface_hapd->conf->iface,
1518 						instanceName);
1519 				if (!status.isOk()) {
1520 					wpa_printf(MSG_ERROR, "Failed to invoke onFailure");
1521 				}
1522 			}
1523 		}
1524 	};
1525 
1526 	// Setup callback
1527 	iface_hapd->setup_complete_cb = onAsyncSetupCompleteCb;
1528 	iface_hapd->setup_complete_cb_ctx = iface_hapd;
1529 	iface_hapd->sta_authorized_cb = onAsyncStaAuthorizedCb;
1530 	iface_hapd->sta_authorized_cb_ctx = iface_hapd;
1531 	wpa_msg_register_aidl_cb(onAsyncWpaEventCb);
1532 
1533 	// Multi-link MLO should enable iface after both links have been set.
1534 	if (!iface_params.usesMlo && hostapd_enable_iface(iface_hapd->iface) < 0) {
1535 		wpa_printf(
1536 			MSG_ERROR, "Enabling interface %s failed",
1537 			iface_params.name.c_str());
1538 		return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
1539 	}
1540 	return ndk::ScopedAStatus::ok();
1541 }
1542 
removeAccessPointInternal(const std::string & iface_name)1543 ::ndk::ScopedAStatus Hostapd::removeAccessPointInternal(const std::string& iface_name)
1544 {
1545 	// interfaces to be removed
1546 	std::vector<std::string> interfaces;
1547 	bool is_error = false;
1548 
1549 	const auto it = br_interfaces_.find(iface_name);
1550 	if (it != br_interfaces_.end()) {
1551 		// In case bridge, remove managed interfaces
1552 		interfaces = it->second;
1553 		br_interfaces_.erase(iface_name);
1554 	} else {
1555 		// else remove current interface
1556 		interfaces.push_back(iface_name);
1557 	}
1558 
1559 	for (auto& iface : interfaces) {
1560 		std::vector<char> remove_iface_param_vec(
1561 		    iface.begin(), iface.end() + 1);
1562 		if (hostapd_remove_iface(interfaces_, remove_iface_param_vec.data()) <  0) {
1563 			wpa_printf(MSG_INFO, "Remove interface %s failed", iface.c_str());
1564 			is_error = true;
1565 		}
1566 	}
1567 	if (is_error) {
1568 		return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
1569 	}
1570 	return ndk::ScopedAStatus::ok();
1571 }
1572 
registerCallbackInternal(const std::shared_ptr<IHostapdCallback> & callback)1573 ::ndk::ScopedAStatus Hostapd::registerCallbackInternal(
1574 	const std::shared_ptr<IHostapdCallback>& callback)
1575 {
1576 	binder_status_t status = AIBinder_linkToDeath(callback->asBinder().get(),
1577 			death_notifier_, this /* cookie */);
1578 	if (status != STATUS_OK) {
1579 		wpa_printf(
1580 			MSG_ERROR,
1581 			"Error registering for death notification for "
1582 			"hostapd callback object");
1583 		return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
1584 	}
1585 	callbacks_.push_back(callback);
1586 	if (aidl_service_version == 0) {
1587 	    aidl_service_version = Hostapd::version;
1588 	    wpa_printf(MSG_INFO, "AIDL service version: %d", aidl_service_version);
1589 	}
1590 	if (aidl_client_version == 0) {
1591 	    callback->getInterfaceVersion(&aidl_client_version);
1592 	    wpa_printf(MSG_INFO, "AIDL client version: %d", aidl_client_version);
1593 	}
1594 	return ndk::ScopedAStatus::ok();
1595 }
1596 
forceClientDisconnectInternal(const std::string & iface_name,const std::vector<uint8_t> & client_address,Ieee80211ReasonCode reason_code)1597 ::ndk::ScopedAStatus Hostapd::forceClientDisconnectInternal(const std::string& iface_name,
1598 	const std::vector<uint8_t>& client_address, Ieee80211ReasonCode reason_code)
1599 {
1600 	struct hostapd_data *hapd = hostapd_get_iface(interfaces_, iface_name.c_str());
1601 	bool result;
1602 	if (!hapd) {
1603 		for (auto const& iface : br_interfaces_) {
1604 			if (iface.first == iface_name) {
1605 				for (auto const& instance : iface.second) {
1606 					hapd = hostapd_get_iface(interfaces_, instance.c_str());
1607 					if (hapd) {
1608 						result = forceStaDisconnection(hapd, client_address,
1609 								(uint16_t) reason_code);
1610 						if (result) break;
1611 					}
1612 				}
1613 			}
1614 		}
1615 	} else {
1616 		result = forceStaDisconnection(hapd, client_address, (uint16_t) reason_code);
1617 	}
1618 	if (!hapd) {
1619 		wpa_printf(MSG_ERROR, "Interface %s doesn't exist", iface_name.c_str());
1620 		return createStatus(HostapdStatusCode::FAILURE_IFACE_UNKNOWN);
1621 	}
1622 	if (result) {
1623 		return ndk::ScopedAStatus::ok();
1624 	}
1625 	return createStatus(HostapdStatusCode::FAILURE_CLIENT_UNKNOWN);
1626 }
1627 
setDebugParamsInternal(DebugLevel level)1628 ::ndk::ScopedAStatus Hostapd::setDebugParamsInternal(DebugLevel level)
1629 {
1630 	wpa_debug_level = static_cast<uint32_t>(level);
1631 	return ndk::ScopedAStatus::ok();
1632 }
1633 
removeLinkFromMultipleLinkBridgedApIfaceInternal(const std::string & iface_name,const std::string & linkIdentity)1634 ::ndk::ScopedAStatus Hostapd::removeLinkFromMultipleLinkBridgedApIfaceInternal(
1635 const std::string& iface_name, const std::string& linkIdentity)
1636 {
1637 #ifdef CONFIG_IEEE80211BE
1638 	if (!hostapd_get_iface(interfaces_, iface_name.c_str())) {
1639 		wpa_printf(MSG_ERROR, "Interface %s doesn't exist", iface_name.c_str());
1640 		return createStatus(HostapdStatusCode::FAILURE_IFACE_UNKNOWN);
1641 	}
1642 	struct hostapd_data* iface_hapd =
1643 		hostapd_get_iface_by_link_id(interfaces_, std::stoi(linkIdentity.c_str()));
1644 	if (iface_hapd) {
1645 // Currently, hostapd_link_remove is still under CONFIG_TESTING_OPTIONS.
1646 // TODO: b/340821197 - Make sure to take out the hostapd_link_remove() and other related code
1647 // out of CONFIG_TESTING_OPTIONS.
1648 #ifdef CONFIG_TESTING_OPTIONS
1649 		if (0 == hostapd_link_remove(iface_hapd, 1)) {
1650 			return ndk::ScopedAStatus::ok();
1651 		}
1652 #endif /* CONFIG_TESTING_OPTIONS */
1653 	}
1654 	return createStatus(HostapdStatusCode::FAILURE_ARGS_INVALID);
1655 #endif /* CONFIG_IEEE80211BE */
1656 	return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
1657 }
1658 
1659 }  // namespace hostapd
1660 }  // namespace wifi
1661 }  // namespace hardware
1662 }  // namespace android
1663 }  // namespace aidl
1664