• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * hidl 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 
18 #include <android-base/file.h>
19 #include <android-base/stringprintf.h>
20 #include <android-base/unique_fd.h>
21 
22 #include "hostapd.h"
23 #include "hidl_return_util.h"
24 
25 extern "C"
26 {
27 #include "common/wpa_ctrl.h"
28 #include "drivers/linux_ioctl.h"
29 }
30 
31 // The HIDL implementation for hostapd creates a hostapd.conf dynamically for
32 // each interface. This file can then be used to hook onto the normal config
33 // file parsing logic in hostapd code.  Helps us to avoid duplication of code
34 // in the HIDL interface.
35 // TOOD(b/71872409): Add unit tests for this.
36 namespace {
37 constexpr char kConfFileNameFmt[] = "/data/vendor/wifi/hostapd/hostapd_%s.conf";
38 
39 using android::base::RemoveFileIfExists;
40 using android::base::StringPrintf;
41 using android::base::WriteStringToFile;
42 using android::hardware::wifi::hostapd::V1_3::IHostapd;
43 using android::hardware::wifi::hostapd::V1_3::Generation;
44 using android::hardware::wifi::hostapd::V1_3::Bandwidth;
45 
46 #define MAX_PORTS 1024
GetInterfacesInBridge(std::string br_name,std::vector<std::string> * interfaces)47 bool GetInterfacesInBridge(std::string br_name,
48                            std::vector<std::string>* interfaces) {
49 	android::base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
50 	if (sock.get() < 0) {
51 		wpa_printf(MSG_ERROR, "Failed to create sock (%s) in %s",
52 			strerror(errno), __FUNCTION__);
53 		return false;
54 	}
55 
56 	struct ifreq request;
57 	int i, ifindices[MAX_PORTS];
58 	char if_name[IFNAMSIZ];
59 	unsigned long args[3];
60 
61 	memset(ifindices, 0, MAX_PORTS * sizeof(int));
62 
63 	args[0] = BRCTL_GET_PORT_LIST;
64 	args[1] = (unsigned long) ifindices;
65 	args[2] = MAX_PORTS;
66 
67 	strlcpy(request.ifr_name, br_name.c_str(), IFNAMSIZ);
68 	request.ifr_data = (char *)args;
69 
70 	if (ioctl(sock.get(), SIOCDEVPRIVATE, &request) < 0) {
71 		wpa_printf(MSG_ERROR, "Failed to ioctl SIOCDEVPRIVATE in %s",
72 			__FUNCTION__);
73 		return false;
74 	}
75 
76 	for (i = 0; i < MAX_PORTS; i ++) {
77 		memset(if_name, 0, IFNAMSIZ);
78 		if (ifindices[i] == 0 || !if_indextoname(ifindices[i], if_name)) {
79 			continue;
80 		}
81 		interfaces->push_back(if_name);
82 	}
83 	return true;
84 }
85 
WriteHostapdConfig(const std::string & interface_name,const std::string & config)86 std::string WriteHostapdConfig(
87     const std::string& interface_name, const std::string& config)
88 {
89 	const std::string file_path =
90 	    StringPrintf(kConfFileNameFmt, interface_name.c_str());
91 	if (WriteStringToFile(
92 		config, file_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
93 		getuid(), getgid())) {
94 		return file_path;
95 	}
96 	// Diagnose failure
97 	int error = errno;
98 	wpa_printf(
99 	    MSG_ERROR, "Cannot write hostapd config to %s, error: %s",
100 	    file_path.c_str(), strerror(error));
101 	struct stat st;
102 	int result = stat(file_path.c_str(), &st);
103 	if (result == 0) {
104 		wpa_printf(
105 		    MSG_ERROR, "hostapd config file uid: %d, gid: %d, mode: %d",
106 		    st.st_uid, st.st_gid, st.st_mode);
107 	} else {
108 		wpa_printf(
109 		    MSG_ERROR,
110 		    "Error calling stat() on hostapd config file: %s",
111 		    strerror(errno));
112 	}
113 	return "";
114 }
115 
116 /*
117  * Get the op_class for a channel/band
118  * The logic here is based on Table E-4 in the 802.11 Specification
119  */
getOpClassForChannel(int channel,int band,bool support11n,bool support11ac)120 int getOpClassForChannel(int channel, int band, bool support11n, bool support11ac) {
121 	// 2GHz Band
122 	if ((band & IHostapd::BandMask::BAND_2_GHZ) != 0) {
123 		if (channel == 14) {
124 			return 82;
125 		}
126 		if (channel >= 1 && channel <= 13) {
127 			if (!support11n) {
128 				//20MHz channel
129 				return 81;
130 			}
131 			if (channel <= 9) {
132 				// HT40 with secondary channel above primary
133 				return 83;
134 			}
135 			// HT40 with secondary channel below primary
136 			return 84;
137 		}
138 		// Error
139 		return 0;
140 	}
141 
142 	// 5GHz Band
143 	if ((band & IHostapd::BandMask::BAND_5_GHZ) != 0) {
144 		if (support11ac) {
145 			switch (channel) {
146 				case 42:
147 				case 58:
148 				case 106:
149 				case 122:
150 				case 138:
151 				case 155:
152 					// 80MHz channel
153 					return 128;
154 				case 50:
155 				case 114:
156 					// 160MHz channel
157 					return 129;
158 			}
159 		}
160 
161 		if (!support11n) {
162 			if (channel >= 36 && channel <= 48) {
163 				return 115;
164 			}
165 			if (channel >= 52 && channel <= 64) {
166 				return 118;
167 			}
168 			if (channel >= 100 && channel <= 144) {
169 				return 121;
170 			}
171 			if (channel >= 149 && channel <= 161) {
172 				return 124;
173 			}
174 			if (channel >= 165 && channel <= 169) {
175 				return 125;
176 			}
177 		} else {
178 			switch (channel) {
179 				case 36:
180 				case 44:
181 					// HT40 with secondary channel above primary
182 					return 116;
183 				case 40:
184 				case 48:
185 					// HT40 with secondary channel below primary
186 					return 117;
187 				case 52:
188 				case 60:
189 					// HT40 with secondary channel above primary
190 					return  119;
191 				case 56:
192 				case 64:
193 					// HT40 with secondary channel below primary
194 					return 120;
195 				case 100:
196 				case 108:
197 				case 116:
198 				case 124:
199 				case 132:
200 				case 140:
201 					// HT40 with secondary channel above primary
202 					return 122;
203 				case 104:
204 				case 112:
205 				case 120:
206 				case 128:
207 				case 136:
208 				case 144:
209 					// HT40 with secondary channel below primary
210 					return 123;
211 				case 149:
212 				case 157:
213 					// HT40 with secondary channel above primary
214 					return 126;
215 				case 153:
216 				case 161:
217 					// HT40 with secondary channel below primary
218 					return 127;
219 			}
220 		}
221 		// Error
222 		return 0;
223 	}
224 
225 	// 6GHz Band
226 	if ((band & IHostapd::BandMask::BAND_6_GHZ) != 0) {
227 		// Channels 1, 5. 9, 13, ...
228 		if ((channel & 0x03) == 0x01) {
229 			// 20MHz channel
230 			return 131;
231 		}
232 		// Channels 3, 11, 19, 27, ...
233 		if ((channel & 0x07) == 0x03) {
234 			// 40MHz channel
235 			return 132;
236 		}
237 		// Channels 7, 23, 39, 55, ...
238 		if ((channel & 0x0F) == 0x07) {
239 			// 80MHz channel
240 			return 133;
241 		}
242 		// Channels 15, 47, 69, ...
243 		if ((channel & 0x1F) == 0x0F) {
244 			// 160MHz channel
245 			return 134;
246 		}
247 		if (channel == 2) {
248 			// 20MHz channel
249 			return 136;
250 		}
251 		// Error
252 		return 0;
253 	}
254 
255 	if ((band & IHostapd::BandMask::BAND_60_GHZ) != 0) {
256 		if (1 <= channel && channel <= 8) {
257 			return 180;
258 		} else if (9 <= channel && channel <= 15) {
259 			return 181;
260 		} else if (17 <= channel && channel <= 22) {
261 			return 182;
262 		} else if (25 <= channel && channel <= 29) {
263 			return 183;
264 		}
265 		// Error
266 		return 0;
267 	}
268 
269 	return 0;
270 }
271 
validatePassphrase(int passphrase_len,int min_len,int max_len)272 bool validatePassphrase(int passphrase_len, int min_len, int max_len)
273 {
274 	if (min_len != -1 && passphrase_len < min_len) return false;
275 	if (max_len != -1 && passphrase_len > max_len) return false;
276 	return true;
277 }
278 
CreateHostapdConfig(const android::hardware::wifi::hostapd::V1_3::IHostapd::IfaceParams & iface_params,const android::hardware::wifi::hostapd::V1_3::IHostapd::ChannelParams & channelParams,const IHostapd::NetworkParams & nw_params,const std::string br_name)279 std::string CreateHostapdConfig(
280     const android::hardware::wifi::hostapd::V1_3::IHostapd::IfaceParams& iface_params,
281     const android::hardware::wifi::hostapd::V1_3::IHostapd::ChannelParams& channelParams,
282     const IHostapd::NetworkParams& nw_params,
283     const std::string br_name)
284 {
285 	if (nw_params.V1_2.V1_0.ssid.size() >
286 	    static_cast<uint32_t>(
287 		IHostapd::ParamSizeLimits::SSID_MAX_LEN_IN_BYTES)) {
288 		wpa_printf(
289 		    MSG_ERROR, "Invalid SSID size: %zu", nw_params.V1_2.V1_0.ssid.size());
290 		return "";
291 	}
292 
293 	// SSID string
294 	std::stringstream ss;
295 	ss << std::hex;
296 	ss << std::setfill('0');
297 	for (uint8_t b : nw_params.V1_2.V1_0.ssid) {
298 		ss << std::setw(2) << static_cast<unsigned int>(b);
299 	}
300 	const std::string ssid_as_string = ss.str();
301 
302 	// Encryption config string
303 	uint32_t band = 0;
304 	band |= channelParams.bandMask;
305 	bool is_6Ghz_band_only = band == static_cast<uint32_t>(IHostapd::BandMask::BAND_6_GHZ);
306 	bool is_60Ghz_band_only = band == static_cast<uint32_t>(IHostapd::BandMask::BAND_60_GHZ);
307 	std::string encryption_config_as_string;
308 	switch (nw_params.V1_2.encryptionType) {
309 	case IHostapd::EncryptionType::NONE:
310 		// no security params
311 		break;
312 	case IHostapd::EncryptionType::WPA:
313 		if (!validatePassphrase(
314 		    nw_params.V1_2.passphrase.size(),
315 		    static_cast<uint32_t>(IHostapd::ParamSizeLimits::
316 				WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES),
317 		    static_cast<uint32_t>(IHostapd::ParamSizeLimits::
318 				WPA2_PSK_PASSPHRASE_MAX_LEN_IN_BYTES))) {
319 			return "";
320 		}
321 		encryption_config_as_string = StringPrintf(
322 		    "wpa=3\n"
323 		    "wpa_pairwise=%s\n"
324 		    "wpa_passphrase=%s",
325 		    is_60Ghz_band_only ? "GCMP" : "TKIP CCMP",
326 		    nw_params.V1_2.passphrase.c_str());
327 		break;
328 	case IHostapd::EncryptionType::WPA2:
329 		if (!validatePassphrase(
330 		    nw_params.V1_2.passphrase.size(),
331 		    static_cast<uint32_t>(IHostapd::ParamSizeLimits::
332 				WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES),
333 		    static_cast<uint32_t>(IHostapd::ParamSizeLimits::
334 				WPA2_PSK_PASSPHRASE_MAX_LEN_IN_BYTES))) {
335 			return "";
336 		}
337 		encryption_config_as_string = StringPrintf(
338 		    "wpa=2\n"
339 		    "rsn_pairwise=%s\n"
340 		    "wpa_passphrase=%s",
341 		    is_60Ghz_band_only ? "GCMP" : "CCMP",
342 		    nw_params.V1_2.passphrase.c_str());
343 		break;
344 	case IHostapd::EncryptionType::WPA3_SAE_TRANSITION:
345 		if (!validatePassphrase(
346 		    nw_params.V1_2.passphrase.size(),
347 		    static_cast<uint32_t>(IHostapd::ParamSizeLimits::
348 				WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES),
349 		    static_cast<uint32_t>(IHostapd::ParamSizeLimits::
350 				WPA2_PSK_PASSPHRASE_MAX_LEN_IN_BYTES))) {
351 			return "";
352 		}
353 		encryption_config_as_string = StringPrintf(
354 		    "wpa=2\n"
355 		    "rsn_pairwise=%s\n"
356 		    "wpa_key_mgmt=WPA-PSK SAE\n"
357 		    "ieee80211w=1\n"
358 		    "sae_require_mfp=1\n"
359 		    "wpa_passphrase=%s\n"
360 		    "sae_password=%s",
361 		    is_60Ghz_band_only ? "GCMP" : "CCMP",
362 		    nw_params.V1_2.passphrase.c_str(),
363 		    nw_params.V1_2.passphrase.c_str());
364 		break;
365 	case IHostapd::EncryptionType::WPA3_SAE:
366 		if (!validatePassphrase(nw_params.V1_2.passphrase.size(), 1, -1)) {
367 			return "";
368 		}
369 		encryption_config_as_string = StringPrintf(
370 		    "wpa=2\n"
371 		    "rsn_pairwise=%s\n"
372 		    "wpa_key_mgmt=SAE\n"
373 		    "ieee80211w=2\n"
374 		    "sae_require_mfp=2\n"
375 		    "sae_pwe=%d\n"
376 		    "sae_password=%s",
377 		    is_60Ghz_band_only ? "GCMP" : "CCMP",
378 		    is_6Ghz_band_only ? 1 : 2,
379 		    nw_params.V1_2.passphrase.c_str());
380 		break;
381 	default:
382 		wpa_printf(MSG_ERROR, "Unknown encryption type");
383 		return "";
384 	}
385 
386 	std::string channel_config_as_string;
387 	bool isFirst = true;
388 	if (channelParams.enableAcs) {
389 		std::string freqList_as_string;
390 		for (const auto &range :
391 		    channelParams.V1_2.acsChannelFreqRangesMhz) {
392 			if (!isFirst) {
393 				freqList_as_string += ",";
394 			}
395 			isFirst = false;
396 
397 			if (range.start != range.end) {
398 				freqList_as_string +=
399 				    StringPrintf("%d-%d", range.start, range.end);
400 			} else {
401 				freqList_as_string += StringPrintf("%d", range.start);
402 			}
403 		}
404 		channel_config_as_string = StringPrintf(
405 		    "channel=0\n"
406 		    "acs_exclude_dfs=%d\n"
407 		    "freqlist=%s",
408 		    iface_params.V1_2.V1_1.V1_0.channelParams.acsShouldExcludeDfs,
409 		    freqList_as_string.c_str());
410 	} else {
411 		int op_class = getOpClassForChannel(
412 		    channelParams.channel,
413 		    band,
414 		    iface_params.V1_2.V1_1.V1_0.hwModeParams.enable80211N,
415 		    iface_params.V1_2.V1_1.V1_0.hwModeParams.enable80211AC);
416 		channel_config_as_string = StringPrintf(
417 		    "channel=%d\n"
418 		    "op_class=%d",
419 		    channelParams.channel, op_class);
420 	}
421 
422 	std::string hw_mode_as_string;
423 	std::string ht_cap_vht_oper_chwidth_as_string;
424 	std::string enable_edmg_as_string;
425 	std::string edmg_channel_as_string;
426 	bool is_60Ghz_used = false;
427 
428 	if (((band & IHostapd::BandMask::BAND_60_GHZ) != 0)) {
429 		hw_mode_as_string = "hw_mode=ad";
430 		if (iface_params.hwModeParams.enableEdmg) {
431 			enable_edmg_as_string = "enable_edmg=1";
432 			edmg_channel_as_string = StringPrintf(
433 				"edmg_channel=%d",
434 				channelParams.channel);
435 		}
436 		is_60Ghz_used = true;
437 	} else if ((band & IHostapd::BandMask::BAND_2_GHZ) != 0) {
438 		if (((band & IHostapd::BandMask::BAND_5_GHZ) != 0)
439 		    || ((band & IHostapd::BandMask::BAND_6_GHZ) != 0)) {
440 			hw_mode_as_string = "hw_mode=any";
441 			if (iface_params.V1_2.V1_1.V1_0.hwModeParams.enable80211AC) {
442 				ht_cap_vht_oper_chwidth_as_string =
443 				    "ht_capab=[HT40+]\n"
444 				    "vht_oper_chwidth=1";
445 			}
446 		} else {
447 			hw_mode_as_string = "hw_mode=g";
448 		}
449 	} else if (((band & IHostapd::BandMask::BAND_5_GHZ) != 0)
450 		    || ((band & IHostapd::BandMask::BAND_6_GHZ) != 0)) {
451 			hw_mode_as_string = "hw_mode=a";
452 		if (iface_params.V1_2.V1_1.V1_0.hwModeParams.enable80211AC) {
453 			ht_cap_vht_oper_chwidth_as_string =
454 			    "ht_capab=[HT40+]\n"
455 			    "vht_oper_chwidth=1";
456 		}
457 	} else {
458 		wpa_printf(MSG_ERROR, "Invalid band");
459 		return "";
460 	}
461 
462 	std::string he_params_as_string;
463 #ifdef CONFIG_IEEE80211AX
464 	if (iface_params.V1_2.hwModeParams.enable80211AX && !is_60Ghz_used) {
465 		he_params_as_string = StringPrintf(
466 		    "ieee80211ax=1\n"
467 		    "he_oper_chwidth=1\n"
468 		    "he_su_beamformer=%d\n"
469 		    "he_su_beamformee=%d\n"
470 		    "he_mu_beamformer=%d\n"
471 		    "he_twt_required=%d\n",
472 		    iface_params.V1_2.hwModeParams.enableHeSingleUserBeamformer ? 1 : 0,
473 		    iface_params.V1_2.hwModeParams.enableHeSingleUserBeamformee ? 1 : 0,
474 		    iface_params.V1_2.hwModeParams.enableHeMultiUserBeamformer ? 1 : 0,
475 		    iface_params.V1_2.hwModeParams.enableHeTargetWakeTime ? 1 : 0);
476 	} else {
477 		he_params_as_string = "ieee80211ax=0";
478 	}
479 #endif /* CONFIG_IEEE80211AX */
480 
481 #ifdef CONFIG_INTERWORKING
482 	std::string access_network_params_as_string;
483 	if (nw_params.isMetered) {
484 		access_network_params_as_string = StringPrintf(
485 		    "interworking=1\n"
486 		    "access_network_type=2\n"); // CHARGEABLE_PUBLIC_NETWORK
487 	} else {
488 	    access_network_params_as_string = StringPrintf(
489 		    "interworking=0\n");
490 	}
491 #endif /* CONFIG_INTERWORKING */
492 
493 	std::string bridge_as_string;
494 	if (!br_name.empty()) {
495 		bridge_as_string = StringPrintf("bridge=%s", br_name.c_str());
496 	}
497 
498 	return StringPrintf(
499 	    "interface=%s\n"
500 	    "driver=nl80211\n"
501 	    "ctrl_interface=/data/vendor/wifi/hostapd/ctrl\n"
502 	    // ssid2 signals to hostapd that the value is not a literal value
503 	    // for use as a SSID.  In this case, we're giving it a hex
504 	    // std::string and hostapd needs to expect that.
505 	    "ssid2=%s\n"
506 	    "%s\n"
507 	    "ieee80211n=%d\n"
508 	    "ieee80211ac=%d\n"
509 	    "%s\n"
510 	    "%s\n"
511 	    "%s\n"
512 	    "ignore_broadcast_ssid=%d\n"
513 	    "wowlan_triggers=any\n"
514 #ifdef CONFIG_INTERWORKING
515 	    "%s\n"
516 #endif /* CONFIG_INTERWORKING */
517 	    "%s\n"
518 	    "%s\n"
519 	    "%s\n"
520 	    "%s\n",
521 	    iface_params.V1_2.V1_1.V1_0.ifaceName.c_str(), ssid_as_string.c_str(),
522 	    channel_config_as_string.c_str(),
523 	    iface_params.V1_2.V1_1.V1_0.hwModeParams.enable80211N ? 1 : 0,
524 	    iface_params.V1_2.V1_1.V1_0.hwModeParams.enable80211AC ? 1 : 0,
525 	    he_params_as_string.c_str(),
526 	    hw_mode_as_string.c_str(), ht_cap_vht_oper_chwidth_as_string.c_str(),
527 	    nw_params.V1_2.V1_0.isHidden ? 1 : 0,
528 #ifdef CONFIG_INTERWORKING
529 	    access_network_params_as_string.c_str(),
530 #endif /* CONFIG_INTERWORKING */
531 	    encryption_config_as_string.c_str(),
532 	    bridge_as_string.c_str(),
533 	    enable_edmg_as_string.c_str(),
534 	    edmg_channel_as_string.c_str());
535 }
536 
getGeneration(hostapd_hw_modes * current_mode)537 Generation getGeneration(hostapd_hw_modes *current_mode)
538 {
539 	wpa_printf(MSG_DEBUG, "getGeneration hwmode=%d, ht_enabled=%d,"
540 		   " vht_enabled=%d, he_supported=%d",
541 		   current_mode->mode, current_mode->ht_capab != 0,
542 		   current_mode->vht_capab != 0, current_mode->he_capab->he_supported);
543 	switch (current_mode->mode) {
544 	case HOSTAPD_MODE_IEEE80211B:
545 		return Generation::WIFI_STANDARD_LEGACY;
546 	case HOSTAPD_MODE_IEEE80211G:
547 		return current_mode->ht_capab == 0 ?
548 		       Generation::WIFI_STANDARD_LEGACY : Generation::WIFI_STANDARD_11N;
549 	case HOSTAPD_MODE_IEEE80211A:
550 		if (current_mode->he_capab->he_supported) {
551 			return Generation::WIFI_STANDARD_11AX;
552 		}
553 		return current_mode->vht_capab == 0 ?
554 		       Generation::WIFI_STANDARD_11N : Generation::WIFI_STANDARD_11AC;
555 	case HOSTAPD_MODE_IEEE80211AD:
556 		return Generation::WIFI_STANDARD_11AD;
557 	default:
558 		return Generation::WIFI_STANDARD_UNKNOWN;
559 	}
560 }
561 
getBandwidth(struct hostapd_config * iconf)562 Bandwidth getBandwidth(struct hostapd_config *iconf)
563 {
564 	wpa_printf(MSG_DEBUG, "getBandwidth %d, isHT=%d, isHT40=%d",
565 		   iconf->vht_oper_chwidth, iconf->ieee80211n,
566 		   iconf->secondary_channel);
567 	switch (iconf->vht_oper_chwidth) {
568 	case CHANWIDTH_80MHZ:
569 		return Bandwidth::WIFI_BANDWIDTH_80;
570 	case CHANWIDTH_80P80MHZ:
571 		return Bandwidth::WIFI_BANDWIDTH_80P80;
572 		break;
573 	case CHANWIDTH_160MHZ:
574 		return Bandwidth::WIFI_BANDWIDTH_160;
575 		break;
576 	case CHANWIDTH_USE_HT:
577 		if (iconf->ieee80211n) {
578 			return iconf->secondary_channel != 0 ?
579 				Bandwidth::WIFI_BANDWIDTH_40 : Bandwidth::WIFI_BANDWIDTH_20;
580 		}
581 		return Bandwidth::WIFI_BANDWIDTH_20_NOHT;
582 	case CHANWIDTH_2160MHZ:
583 		return Bandwidth::WIFI_BANDWIDTH_2160;
584 	case CHANWIDTH_4320MHZ:
585 		return Bandwidth::WIFI_BANDWIDTH_4320;
586 	case CHANWIDTH_6480MHZ:
587 		return Bandwidth::WIFI_BANDWIDTH_6480;
588 	case CHANWIDTH_8640MHZ:
589 		return Bandwidth::WIFI_BANDWIDTH_8640;
590 	default:
591 		return Bandwidth::WIFI_BANDWIDTH_INVALID;
592 	}
593 }
594 
forceStaDisconnection(struct hostapd_data * hapd,const std::array<uint8_t,6> & client_address,const uint16_t reason_code)595 bool forceStaDisconnection(struct hostapd_data* hapd,
596 			   const std::array<uint8_t, 6>& client_address,
597 			   const uint16_t reason_code) {
598 	struct sta_info *sta;
599 	for (sta = hapd->sta_list; sta; sta = sta->next) {
600 		int res;
601 		res = memcmp(sta->addr, client_address.data(), ETH_ALEN);
602 		if (res == 0) {
603 			wpa_printf(MSG_INFO, "Force client:" MACSTR " disconnect with reason: %d",
604 			    MAC2STR(client_address.data()), reason_code);
605 			ap_sta_disconnect(hapd, sta, sta->addr, reason_code);
606 			return true;
607 		}
608 	}
609 	return false;
610 }
611 
612 // hostapd core functions accept "C" style function pointers, so use global
613 // functions to pass to the hostapd core function and store the corresponding
614 // std::function methods to be invoked.
615 //
616 // NOTE: Using the pattern from the vendor HAL (wifi_legacy_hal.cpp).
617 //
618 // Callback to be invoked once setup is complete
619 std::function<void(struct hostapd_data*)> on_setup_complete_internal_callback;
onAsyncSetupCompleteCb(void * ctx)620 void onAsyncSetupCompleteCb(void* ctx)
621 {
622 	struct hostapd_data* iface_hapd = (struct hostapd_data*)ctx;
623 	if (on_setup_complete_internal_callback) {
624 		on_setup_complete_internal_callback(iface_hapd);
625 		// Invalidate this callback since we don't want this firing
626 		// again in single AP mode.
627 		if (strlen(iface_hapd->conf->bridge) > 0) {
628 		    on_setup_complete_internal_callback = nullptr;
629 		}
630 	}
631 }
632 
633 // Callback to be invoked on hotspot client connection/disconnection
634 std::function<void(struct hostapd_data*, const u8 *mac_addr, int authorized,
635 		   const u8 *p2p_dev_addr)> on_sta_authorized_internal_callback;
onAsyncStaAuthorizedCb(void * ctx,const u8 * mac_addr,int authorized,const u8 * p2p_dev_addr)636 void onAsyncStaAuthorizedCb(void* ctx, const u8 *mac_addr, int authorized,
637 			    const u8 *p2p_dev_addr)
638 {
639 	struct hostapd_data* iface_hapd = (struct hostapd_data*)ctx;
640 	if (on_sta_authorized_internal_callback) {
641 		on_sta_authorized_internal_callback(iface_hapd, mac_addr,
642 			authorized, p2p_dev_addr);
643 	}
644 }
645 
646 std::function<void(struct hostapd_data*, int level,
647                    enum wpa_msg_type type, const char *txt,
648                    size_t len)> on_wpa_msg_internal_callback;
649 
onAsyncWpaEventCb(void * ctx,int level,enum wpa_msg_type type,const char * txt,size_t len)650 void onAsyncWpaEventCb(void *ctx, int level,
651                    enum wpa_msg_type type, const char *txt,
652                    size_t len)
653 {
654 	struct hostapd_data* iface_hapd = (struct hostapd_data*)ctx;
655 	if (on_wpa_msg_internal_callback) {
656 		on_wpa_msg_internal_callback(iface_hapd, level,
657 					       type, txt, len);
658 	}
659 }
660 
661 
662 }  // namespace
663 
664 namespace android {
665 namespace hardware {
666 namespace wifi {
667 namespace hostapd {
668 namespace V1_3 {
669 namespace implementation {
670 using hidl_return_util::call;
671 using namespace android::hardware::wifi::hostapd::V1_0;
672 
Hostapd(struct hapd_interfaces * interfaces)673 Hostapd::Hostapd(struct hapd_interfaces* interfaces)
674     : interfaces_(interfaces), death_notifier_(sp<DeathNotifier>::make())
675 {}
676 
addAccessPoint(const V1_0::IHostapd::IfaceParams & iface_params,const V1_0::IHostapd::NetworkParams & nw_params,addAccessPoint_cb _hidl_cb)677 Return<void> Hostapd::addAccessPoint(
678     const V1_0::IHostapd::IfaceParams& iface_params,
679     const V1_0::IHostapd::NetworkParams& nw_params, addAccessPoint_cb _hidl_cb)
680 {
681 	return call(
682 	    this, &Hostapd::addAccessPointInternal, _hidl_cb, iface_params,
683 	    nw_params);
684 }
685 
addAccessPoint_1_1(const V1_1::IHostapd::IfaceParams & iface_params,const V1_0::IHostapd::NetworkParams & nw_params,addAccessPoint_cb _hidl_cb)686 Return<void> Hostapd::addAccessPoint_1_1(
687     const V1_1::IHostapd::IfaceParams& iface_params,
688     const V1_0::IHostapd::NetworkParams& nw_params, addAccessPoint_cb _hidl_cb)
689 {
690 	return call(
691 	    this, &Hostapd::addAccessPointInternal_1_1, _hidl_cb, iface_params,
692 	    nw_params);
693 }
694 
addAccessPoint_1_2(const V1_2::IHostapd::IfaceParams & iface_params,const V1_2::IHostapd::NetworkParams & nw_params,addAccessPoint_1_2_cb _hidl_cb)695 Return<void> Hostapd::addAccessPoint_1_2(
696     const V1_2::IHostapd::IfaceParams& iface_params,
697     const V1_2::IHostapd::NetworkParams& nw_params,
698     addAccessPoint_1_2_cb _hidl_cb)
699 {
700 	return call(
701 	    this, &Hostapd::addAccessPointInternal_1_2, _hidl_cb, iface_params,
702 	    nw_params);
703 }
704 
addAccessPoint_1_3(const V1_3::IHostapd::IfaceParams & iface_params,const V1_3::IHostapd::NetworkParams & nw_params,addAccessPoint_1_3_cb _hidl_cb)705 Return<void> Hostapd::addAccessPoint_1_3(
706     const V1_3::IHostapd::IfaceParams& iface_params,
707     const V1_3::IHostapd::NetworkParams& nw_params,
708     addAccessPoint_1_3_cb _hidl_cb)
709 {
710         return call(
711             this, &Hostapd::addAccessPointInternal_1_3, _hidl_cb, iface_params,
712             nw_params);
713 }
714 
removeAccessPoint(const hidl_string & iface_name,removeAccessPoint_cb _hidl_cb)715 Return<void> Hostapd::removeAccessPoint(
716     const hidl_string& iface_name, removeAccessPoint_cb _hidl_cb)
717 {
718 	return call(
719 	    this, &Hostapd::removeAccessPointInternal, _hidl_cb, iface_name);
720 }
721 
terminate()722 Return<void> Hostapd::terminate()
723 {
724 	wpa_printf(MSG_INFO, "Terminating...");
725 	// Clear the callback to avoid IPCThreadState shutdown during the
726 	// callback event.
727 	callbacks_.clear();
728 	eloop_terminate();
729 	return Void();
730 }
731 
registerCallback(const sp<V1_1::IHostapdCallback> & callback,registerCallback_cb _hidl_cb)732 Return<void> Hostapd::registerCallback(
733     const sp<V1_1::IHostapdCallback>& callback, registerCallback_cb _hidl_cb)
734 {
735 	return call(
736 	    this, &Hostapd::registerCallbackInternal, _hidl_cb, callback);
737 }
738 
registerCallback_1_3(const sp<V1_3::IHostapdCallback> & callback,registerCallback_1_3_cb _hidl_cb)739 Return<void> Hostapd::registerCallback_1_3(
740     const sp<V1_3::IHostapdCallback>& callback, registerCallback_1_3_cb _hidl_cb)
741 {
742 	return call(
743 	    this, &Hostapd::registerCallbackInternal_1_3, _hidl_cb, callback);
744 }
745 
forceClientDisconnect(const hidl_string & iface_name,const hidl_array<uint8_t,6> & client_address,V1_2::Ieee80211ReasonCode reason_code,forceClientDisconnect_cb _hidl_cb)746 Return<void> Hostapd::forceClientDisconnect(
747     const hidl_string& iface_name, const hidl_array<uint8_t, 6>& client_address,
748     V1_2::Ieee80211ReasonCode reason_code, forceClientDisconnect_cb _hidl_cb)
749 {
750 	return call(
751 	    this, &Hostapd::forceClientDisconnectInternal, _hidl_cb, iface_name,
752 	    client_address, reason_code);
753 }
754 
setDebugParams(V1_2::DebugLevel level,setDebugParams_cb _hidl_cb)755 Return<void> Hostapd::setDebugParams(
756      V1_2::DebugLevel level, setDebugParams_cb _hidl_cb)
757 {
758 	return call(
759 	    this, &Hostapd::setDebugParamsInternal, _hidl_cb, level);
760 }
761 
addAccessPointInternal(const V1_0::IHostapd::IfaceParams & iface_params,const V1_0::IHostapd::NetworkParams & nw_params)762 V1_0::HostapdStatus Hostapd::addAccessPointInternal(
763     const V1_0::IHostapd::IfaceParams& iface_params,
764     const V1_0::IHostapd::NetworkParams& nw_params)
765 {
766 	return {V1_0::HostapdStatusCode::FAILURE_UNKNOWN, ""};
767 }
768 
addAccessPointInternal_1_1(const V1_1::IHostapd::IfaceParams & iface_params,const V1_1::IHostapd::NetworkParams & nw_params)769 V1_0::HostapdStatus Hostapd::addAccessPointInternal_1_1(
770     const V1_1::IHostapd::IfaceParams& iface_params,
771     const V1_1::IHostapd::NetworkParams& nw_params)
772 {
773 	return {V1_0::HostapdStatusCode::FAILURE_UNKNOWN, ""};
774 }
775 
addAccessPointInternal_1_2(const V1_2::IHostapd::IfaceParams & iface_params,const V1_2::IHostapd::NetworkParams & nw_params)776 V1_2::HostapdStatus Hostapd::addAccessPointInternal_1_2(
777     const V1_2::IHostapd::IfaceParams& iface_params,
778     const V1_2::IHostapd::NetworkParams& nw_params) {
779 	return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN, ""};
780 }
781 
addAccessPointInternal_1_3(const V1_3::IHostapd::IfaceParams & iface_params,const V1_3::IHostapd::NetworkParams & nw_params)782 V1_2::HostapdStatus Hostapd::addAccessPointInternal_1_3(
783     const V1_3::IHostapd::IfaceParams& iface_params,
784     const V1_3::IHostapd::NetworkParams& nw_params)
785 {
786 	int channelParamsListSize = iface_params.channelParamsList.size();
787 	if (channelParamsListSize == 1) {
788 		// Single AP
789 		wpa_printf(MSG_INFO, "AddSingleAccessPoint, iface=%s",
790 		    iface_params.V1_2.V1_1.V1_0.ifaceName.c_str());
791 		return addSingleAccessPoint(iface_params, iface_params.channelParamsList[0],
792 		    nw_params, "");
793 	} else if (channelParamsListSize == 2) {
794 		// Concurrent APs
795 		wpa_printf(MSG_INFO, "AddDualAccessPoint, iface=%s",
796 		    iface_params.V1_2.V1_1.V1_0.ifaceName.c_str());
797 		return addConcurrentAccessPoints(iface_params, nw_params);
798 	}
799 	return {V1_2::HostapdStatusCode::FAILURE_ARGS_INVALID, ""};
800 }
801 
addConcurrentAccessPoints(const V1_3::IHostapd::IfaceParams & iface_params,const V1_3::IHostapd::NetworkParams & nw_params)802 V1_2::HostapdStatus Hostapd::addConcurrentAccessPoints(
803     const V1_3::IHostapd::IfaceParams& iface_params, const V1_3::IHostapd::NetworkParams& nw_params)
804 {
805 	int channelParamsListSize = iface_params.channelParamsList.size();
806 	// Get available interfaces in bridge
807 	std::vector<std::string> managed_interfaces;
808 	std::string br_name = StringPrintf(
809 	    "%s", iface_params.V1_2.V1_1.V1_0.ifaceName.c_str());
810 	if (!GetInterfacesInBridge(br_name, &managed_interfaces)) {
811 		return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN,
812 		    "Get interfaces in bridge failed."};
813 	}
814 	if (managed_interfaces.size() < channelParamsListSize) {
815 		return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN,
816 		    "Available interfaces less than requested bands"};
817 	}
818 	// start BSS on specified bands
819 	for (std::size_t i = 0; i < channelParamsListSize; i ++) {
820 		V1_3::IHostapd::IfaceParams iface_params_new = iface_params;
821 		iface_params_new.V1_2.V1_1.V1_0.ifaceName = managed_interfaces[i];
822 		V1_2::HostapdStatus status = addSingleAccessPoint(
823 		    iface_params_new, iface_params.channelParamsList[i], nw_params, br_name);
824 		if (status.code != V1_2::HostapdStatusCode::SUCCESS) {
825 			wpa_printf(MSG_ERROR, "Failed to addAccessPoint %s",
826 				   managed_interfaces[i].c_str());
827 			return status;
828 		}
829 	}
830 	// Save bridge interface info
831 	br_interfaces_[br_name] = managed_interfaces;
832 	return {V1_2::HostapdStatusCode::SUCCESS, ""};
833 }
834 
addSingleAccessPoint(const V1_3::IHostapd::IfaceParams & iface_params,const V1_3::IHostapd::ChannelParams & channelParams,const V1_3::IHostapd::NetworkParams & nw_params,const std::string br_name)835 V1_2::HostapdStatus Hostapd::addSingleAccessPoint(
836     const V1_3::IHostapd::IfaceParams& iface_params,
837     const V1_3::IHostapd::ChannelParams& channelParams,
838     const V1_3::IHostapd::NetworkParams& nw_params,
839     const std::string br_name)
840 {
841 	if (hostapd_get_iface(interfaces_, iface_params.V1_2.V1_1.V1_0.ifaceName.c_str())) {
842 		wpa_printf(
843 		    MSG_ERROR, "Interface %s already present",
844 		    iface_params.V1_2.V1_1.V1_0.ifaceName.c_str());
845 		return {V1_2::HostapdStatusCode::FAILURE_IFACE_EXISTS, ""};
846 	}
847 	const auto conf_params = CreateHostapdConfig(iface_params, channelParams, nw_params, br_name);
848 	if (conf_params.empty()) {
849 		wpa_printf(MSG_ERROR, "Failed to create config params");
850 		return {V1_2::HostapdStatusCode::FAILURE_ARGS_INVALID, ""};
851 	}
852 	const auto conf_file_path =
853 	    WriteHostapdConfig(iface_params.V1_2.V1_1.V1_0.ifaceName, conf_params);
854 	if (conf_file_path.empty()) {
855 		wpa_printf(MSG_ERROR, "Failed to write config file");
856 		return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN, ""};
857 	}
858 	std::string add_iface_param_str = StringPrintf(
859 	    "%s config=%s", iface_params.V1_2.V1_1.V1_0.ifaceName.c_str(),
860 	    conf_file_path.c_str());
861 	std::vector<char> add_iface_param_vec(
862 	    add_iface_param_str.begin(), add_iface_param_str.end() + 1);
863 	if (hostapd_add_iface(interfaces_, add_iface_param_vec.data()) < 0) {
864 		wpa_printf(
865 		    MSG_ERROR, "Adding interface %s failed",
866 		    add_iface_param_str.c_str());
867 		return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN, ""};
868 	}
869 	struct hostapd_data* iface_hapd =
870 	    hostapd_get_iface(interfaces_, iface_params.V1_2.V1_1.V1_0.ifaceName.c_str());
871 	WPA_ASSERT(iface_hapd != nullptr && iface_hapd->iface != nullptr);
872 	// Register the setup complete callbacks
873 	on_setup_complete_internal_callback =
874 	    [this](struct hostapd_data* iface_hapd) {
875 		    wpa_printf(
876 			MSG_INFO, "AP interface setup completed - state %s",
877 			hostapd_state_text(iface_hapd->iface->state));
878 		    if (iface_hapd->iface->state == HAPD_IFACE_DISABLED) {
879 			    // Invoke the failure callback on all registered
880 			    // clients.
881 			    for (const auto& callback : callbacks_) {
882 				    callback->onFailure(
883 					iface_hapd->conf->iface);
884 			    }
885 		    }
886 	    };
887 
888 	// Rgegister for new client connect/disconnect indication.
889 	on_sta_authorized_internal_callback =
890 	    [this](struct hostapd_data* iface_hapd, const u8 *mac_addr,
891 		   int authorized, const u8 *p2p_dev_addr) {
892 		wpa_printf(MSG_DEBUG, "notify client " MACSTR " %s",
893 			   MAC2STR(mac_addr),
894 			   (authorized) ? "Connected" : "Disconnected");
895 		for (const auto &callback : callbacks_) {
896 		    callback->onConnectedClientsChanged(strlen(iface_hapd->conf->bridge) > 0 ?
897 			    iface_hapd->conf->bridge : iface_hapd->conf->iface,
898 			    iface_hapd->conf->iface, mac_addr, authorized);
899 		}
900 	    };
901 
902 	// Register for wpa_event which used to get channel switch event
903 	on_wpa_msg_internal_callback =
904 	    [this](struct hostapd_data* iface_hapd, int level,
905 		   enum wpa_msg_type type, const char *txt,
906 		   size_t len) {
907 		wpa_printf(MSG_DEBUG, "Receive wpa msg : %s", txt);
908 		if (os_strncmp(txt, AP_EVENT_ENABLED,
909 			       strlen(AP_EVENT_ENABLED)) == 0 ||
910 		    os_strncmp(txt, WPA_EVENT_CHANNEL_SWITCH,
911 			       strlen(WPA_EVENT_CHANNEL_SWITCH)) == 0) {
912 		    for (const auto &callback : callbacks_) {
913 			callback->onApInstanceInfoChanged(
914 				strlen(iface_hapd->conf->bridge) > 0 ?
915 				iface_hapd->conf->bridge : iface_hapd->conf->iface,
916 				iface_hapd->conf->iface, iface_hapd->iface->freq,
917 				getBandwidth(iface_hapd->iconf),
918 				getGeneration(iface_hapd->iface->current_mode),
919 				iface_hapd->own_addr);
920 		    }
921 		}
922 	    };
923 
924 	// Setup callback
925 	iface_hapd->setup_complete_cb = onAsyncSetupCompleteCb;
926 	iface_hapd->setup_complete_cb_ctx = iface_hapd;
927 	iface_hapd->sta_authorized_cb = onAsyncStaAuthorizedCb;
928 	iface_hapd->sta_authorized_cb_ctx = iface_hapd;
929 	wpa_msg_register_cb(onAsyncWpaEventCb);
930 
931 	if (hostapd_enable_iface(iface_hapd->iface) < 0) {
932 		wpa_printf(
933 		    MSG_ERROR, "Enabling interface %s failed",
934 		    iface_params.V1_2.V1_1.V1_0.ifaceName.c_str());
935 		return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN, ""};
936 	}
937 	return {V1_2::HostapdStatusCode::SUCCESS, ""};
938 }
939 
removeAccessPointInternal(const std::string & iface_name)940 V1_0::HostapdStatus Hostapd::removeAccessPointInternal(const std::string& iface_name)
941 {
942 	// interfaces to be removed
943 	std::vector<std::string> interfaces;
944 	bool is_error = false;
945 
946 	const auto it = br_interfaces_.find(iface_name);
947 	if (it != br_interfaces_.end()) {
948 		// In case bridge, remove managed interfaces
949 		interfaces = it->second;
950 		br_interfaces_.erase(iface_name);
951 	} else {
952 		// else remove current interface
953 		interfaces.push_back(iface_name);
954 	}
955 
956 	for (auto& iface : interfaces) {
957 		std::vector<char> remove_iface_param_vec(
958 		    iface.begin(), iface.end() + 1);
959 		if (hostapd_remove_iface(interfaces_, remove_iface_param_vec.data()) <
960 		    0) {
961 			wpa_printf(MSG_INFO, "Remove interface %s failed",
962 			    iface.c_str());
963 			is_error = true;
964 		}
965 	}
966 	if (is_error) {
967 		return {V1_0::HostapdStatusCode::FAILURE_UNKNOWN, ""};
968 	}
969 	return {V1_0::HostapdStatusCode::SUCCESS, ""};
970 }
971 
registerCallbackInternal(const sp<V1_1::IHostapdCallback> & callback)972 V1_0::HostapdStatus Hostapd::registerCallbackInternal(
973     const sp<V1_1::IHostapdCallback>& callback)
974 {
975 	return {V1_0::HostapdStatusCode::FAILURE_UNKNOWN, ""};
976 }
977 
registerCallbackInternal_1_3(const sp<V1_3::IHostapdCallback> & callback)978 V1_2::HostapdStatus Hostapd::registerCallbackInternal_1_3(
979     const sp<V1_3::IHostapdCallback>& callback)
980 {
981 	if (!callback->linkToDeath(death_notifier_, 0)) {
982 		wpa_printf(
983 		    MSG_ERROR,
984 		    "Error registering for death notification for "
985 		    "hostapd callback object");
986 		return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN, ""};
987 	}
988 	callbacks_.push_back(callback);
989 	return {V1_2::HostapdStatusCode::SUCCESS, ""};
990 }
991 
forceClientDisconnectInternal(const std::string & iface_name,const std::array<uint8_t,6> & client_address,V1_2::Ieee80211ReasonCode reason_code)992 V1_2::HostapdStatus Hostapd::forceClientDisconnectInternal(const std::string& iface_name,
993     const std::array<uint8_t, 6>& client_address, V1_2::Ieee80211ReasonCode reason_code)
994 {
995 	struct hostapd_data *hapd = hostapd_get_iface(interfaces_, iface_name.c_str());
996 	bool result;
997 	if (!hapd) {
998 	    for (auto const& iface : br_interfaces_) {
999 		if (iface.first == iface_name) {
1000 		    for (auto const& instance : iface.second) {
1001 			hapd = hostapd_get_iface(interfaces_, instance.c_str());
1002 			if (hapd) {
1003 				result = forceStaDisconnection(hapd, client_address,
1004 							       (uint16_t) reason_code);
1005 				if (result) break;
1006 			}
1007 		    }
1008 		}
1009 	    }
1010 	} else {
1011 		result = forceStaDisconnection(hapd, client_address, (uint16_t) reason_code);
1012 	}
1013 	if (!hapd) {
1014 		wpa_printf(MSG_ERROR, "Interface %s doesn't exist", iface_name.c_str());
1015 		return {V1_2::HostapdStatusCode::FAILURE_IFACE_UNKNOWN, ""};
1016 	}
1017 	if (result) {
1018 		return {V1_2::HostapdStatusCode::SUCCESS, ""};
1019 	}
1020 	return {V1_2::HostapdStatusCode::FAILURE_CLIENT_UNKNOWN, ""};
1021 }
1022 
setDebugParamsInternal(V1_2::DebugLevel level)1023 V1_2::HostapdStatus Hostapd::setDebugParamsInternal(V1_2::DebugLevel level)
1024 {
1025 	wpa_debug_level = static_cast<uint32_t>(level);
1026 	return {V1_2::HostapdStatusCode::SUCCESS, ""};
1027 }
1028 
1029 }  // namespace implementation
1030 }  // namespace V1_3
1031 }  // namespace hostapd
1032 }  // namespace wifi
1033 }  // namespace hardware
1034 }  // namespace android
1035