• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * hidl interface for wpa_supplicant daemon
3  * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
4  * Copyright (c) 2004-2016, 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 
10 #include "hidl_manager.h"
11 #include "hidl_return_util.h"
12 #include "supplicant.h"
13 #include "p2p_iface.h"
14 
15 #include <android-base/file.h>
16 #include <fcntl.h>
17 #include <sys/stat.h>
18 
19 namespace {
20 
21 // Pre-populated interface params for interfaces controlled by wpa_supplicant.
22 // Note: This may differ for other OEM's. So, modify this accordingly.
23 constexpr char kIfaceDriverName[] = "nl80211";
24 constexpr char kStaIfaceConfPath[] =
25     "/data/vendor/wifi/wpa/wpa_supplicant.conf";
26 constexpr char kStaIfaceConfOverlayPath[] =
27     "/vendor/etc/wifi/wpa_supplicant_overlay.conf";
28 constexpr char kP2pIfaceConfPath[] =
29     "/data/vendor/wifi/wpa/p2p_supplicant.conf";
30 constexpr char kP2pIfaceConfOverlayPath[] =
31     "/vendor/etc/wifi/p2p_supplicant_overlay.conf";
32 // Migrate conf files for existing devices.
33 constexpr char kSystemTemplateConfPath[] =
34     "/system/etc/wifi/wpa_supplicant.conf";
35 constexpr char kVendorTemplateConfPath[] =
36     "/vendor/etc/wifi/wpa_supplicant.conf";
37 constexpr char kOldStaIfaceConfPath[] = "/data/misc/wifi/wpa_supplicant.conf";
38 constexpr char kOldP2pIfaceConfPath[] = "/data/misc/wifi/p2p_supplicant.conf";
39 constexpr mode_t kConfigFileMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
40 
copyFile(const std::string & src_file_path,const std::string & dest_file_path)41 int copyFile(
42     const std::string& src_file_path, const std::string& dest_file_path)
43 {
44 	std::string file_contents;
45 	if (!android::base::ReadFileToString(src_file_path, &file_contents)) {
46 		wpa_printf(
47 		    MSG_ERROR, "Failed to read from %s. Errno: %s",
48 		    src_file_path.c_str(), strerror(errno));
49 		return -1;
50 	}
51 	if (!android::base::WriteStringToFile(
52 		file_contents, dest_file_path, kConfigFileMode, getuid(),
53 		getgid())) {
54 		wpa_printf(
55 		    MSG_ERROR, "Failed to write to %s. Errno: %s",
56 		    dest_file_path.c_str(), strerror(errno));
57 		return -1;
58 	}
59 	return 0;
60 }
61 
62 /**
63  * Copy |src_file_path| to |dest_file_path| if it exists.
64  *
65  * Returns 1 if |src_file_path| does not exist or not accessible,
66  * Returns -1 if the copy fails.
67  * Returns 0 if the copy succeeds.
68  */
copyFileIfItExists(const std::string & src_file_path,const std::string & dest_file_path)69 int copyFileIfItExists(
70     const std::string& src_file_path, const std::string& dest_file_path)
71 {
72 	int ret = access(src_file_path.c_str(), R_OK);
73 	// Sepolicy denial (2018+ device) will return EACCESS instead of ENOENT.
74 	if ((ret != 0) && ((errno == ENOENT) || (errno == EACCES))) {
75 		return 1;
76 	}
77 	ret = copyFile(src_file_path, dest_file_path);
78 	if (ret != 0) {
79 		wpa_printf(
80 		    MSG_ERROR, "Failed copying %s to %s.",
81 		    src_file_path.c_str(), dest_file_path.c_str());
82 		return -1;
83 	}
84 	return 0;
85 }
86 
87 /**
88  * Ensure that the specified config file pointed by |config_file_path| exists.
89  * a) If the |config_file_path| exists with the correct permissions, return.
90  * b) If the |config_file_path| does not exist, but |old_config_file_path|
91  * exists, copy over the contents of the |old_config_file_path| to
92  * |config_file_path|.
93  * c) If the |config_file_path| & |old_config_file_path|
94  * does not exists, copy over the contents of |template_config_file_path|.
95  */
ensureConfigFileExists(const std::string & config_file_path,const std::string & old_config_file_path)96 int ensureConfigFileExists(
97     const std::string& config_file_path,
98     const std::string& old_config_file_path)
99 {
100 	int ret = access(config_file_path.c_str(), R_OK | W_OK);
101 	if (ret == 0) {
102 		return 0;
103 	}
104 	if (errno == EACCES) {
105 		ret = chmod(config_file_path.c_str(), kConfigFileMode);
106 		if (ret == 0) {
107 			return 0;
108 		} else {
109 			wpa_printf(
110 			    MSG_ERROR, "Cannot set RW to %s. Errno: %s",
111 			    config_file_path.c_str(), strerror(errno));
112 			return -1;
113 		}
114 	} else if (errno != ENOENT) {
115 		wpa_printf(
116 		    MSG_ERROR, "Cannot acces %s. Errno: %s",
117 		    config_file_path.c_str(), strerror(errno));
118 		return -1;
119 	}
120 	ret = copyFileIfItExists(old_config_file_path, config_file_path);
121 	if (ret == 0) {
122 		wpa_printf(
123 		    MSG_INFO, "Migrated conf file from %s to %s",
124 		    old_config_file_path.c_str(), config_file_path.c_str());
125 		unlink(old_config_file_path.c_str());
126 		return 0;
127 	} else if (ret == -1) {
128 		unlink(config_file_path.c_str());
129 		return -1;
130 	}
131 	ret = copyFileIfItExists(kVendorTemplateConfPath, config_file_path);
132 	if (ret == 0) {
133 		wpa_printf(
134 		    MSG_INFO, "Copied template conf file from %s to %s",
135 		    kVendorTemplateConfPath, config_file_path.c_str());
136 		return 0;
137 	} else if (ret == -1) {
138 		unlink(config_file_path.c_str());
139 		return -1;
140 	}
141 	ret = copyFileIfItExists(kSystemTemplateConfPath, config_file_path);
142 	if (ret == 0) {
143 		wpa_printf(
144 		    MSG_INFO, "Copied template conf file from %s to %s",
145 		    kSystemTemplateConfPath, config_file_path.c_str());
146 		return 0;
147 	} else if (ret == -1) {
148 		unlink(config_file_path.c_str());
149 		return -1;
150 	}
151 	// Did not create the conf file.
152 	return -1;
153 }
154 }  // namespace
155 
156 namespace android {
157 namespace hardware {
158 namespace wifi {
159 namespace supplicant {
160 namespace V1_4 {
161 namespace implementation {
162 using hidl_return_util::validateAndCall;
163 using V1_0::SupplicantStatusCode;
164 
Supplicant(struct wpa_global * global)165 Supplicant::Supplicant(struct wpa_global* global) : wpa_global_(global) {}
isValid()166 bool Supplicant::isValid()
167 {
168 	// This top level object cannot be invalidated.
169 	return true;
170 }
171 
addInterface(const IfaceInfo & iface_info,addInterface_cb _hidl_cb)172 Return<void> Supplicant::addInterface(
173     const IfaceInfo& iface_info, addInterface_cb _hidl_cb)
174 {
175 	return validateAndCall(
176 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
177 	    &Supplicant::addInterfaceInternal, _hidl_cb, iface_info);
178 }
179 
removeInterface(const IfaceInfo & iface_info,removeInterface_cb _hidl_cb)180 Return<void> Supplicant::removeInterface(
181     const IfaceInfo& iface_info, removeInterface_cb _hidl_cb)
182 {
183 	return validateAndCall(
184 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
185 	    &Supplicant::removeInterfaceInternal, _hidl_cb, iface_info);
186 }
187 
getInterface(const IfaceInfo & iface_info,getInterface_cb _hidl_cb)188 Return<void> Supplicant::getInterface(
189     const IfaceInfo& iface_info, getInterface_cb _hidl_cb)
190 {
191 	return validateAndCall(
192 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
193 	    &Supplicant::getInterfaceInternal, _hidl_cb, iface_info);
194 }
195 
listInterfaces(listInterfaces_cb _hidl_cb)196 Return<void> Supplicant::listInterfaces(listInterfaces_cb _hidl_cb)
197 {
198 	return validateAndCall(
199 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
200 	    &Supplicant::listInterfacesInternal, _hidl_cb);
201 }
202 
registerCallback(const sp<ISupplicantCallback> & callback,registerCallback_cb _hidl_cb)203 Return<void> Supplicant::registerCallback(
204     const sp<ISupplicantCallback>& callback, registerCallback_cb _hidl_cb)
205 {
206 	return validateAndCall(
207 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
208 	    &Supplicant::registerCallbackInternal, _hidl_cb, callback);
209 }
210 
setDebugParams(ISupplicant::DebugLevel level,bool show_timestamp,bool show_keys,setDebugParams_cb _hidl_cb)211 Return<void> Supplicant::setDebugParams(
212     ISupplicant::DebugLevel level, bool show_timestamp, bool show_keys,
213     setDebugParams_cb _hidl_cb)
214 {
215 	return validateAndCall(
216 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
217 	    &Supplicant::setDebugParamsInternal, _hidl_cb, level,
218 	    show_timestamp, show_keys);
219 }
220 
setConcurrencyPriority(IfaceType type,setConcurrencyPriority_cb _hidl_cb)221 Return<void> Supplicant::setConcurrencyPriority(
222     IfaceType type, setConcurrencyPriority_cb _hidl_cb)
223 {
224 	return validateAndCall(
225 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
226 	    &Supplicant::setConcurrencyPriorityInternal, _hidl_cb, type);
227 }
228 
getDebugLevel()229 Return<ISupplicant::DebugLevel> Supplicant::getDebugLevel()
230 {
231 	// TODO: Add SupplicantStatus in this method return for uniformity with
232 	// the other methods in supplicant HIDL interface.
233 	return (ISupplicant::DebugLevel)wpa_debug_level;
234 }
235 
isDebugShowTimestampEnabled()236 Return<bool> Supplicant::isDebugShowTimestampEnabled()
237 {
238 	// TODO: Add SupplicantStatus in this method return for uniformity with
239 	// the other methods in supplicant HIDL interface.
240 	return ((wpa_debug_timestamp != 0) ? true : false);
241 }
242 
isDebugShowKeysEnabled()243 Return<bool> Supplicant::isDebugShowKeysEnabled()
244 {
245 	// TODO: Add SupplicantStatus in this method return for uniformity with
246 	// the other methods in supplicant HIDL interface.
247 	return ((wpa_debug_show_keys != 0) ? true : false);
248 }
249 
terminate()250 Return<void> Supplicant::terminate()
251 {
252 	wpa_printf(MSG_INFO, "Terminating...");
253 	wpa_supplicant_terminate_proc(wpa_global_);
254 	return Void();
255 }
256 
257 std::pair<SupplicantStatus, sp<ISupplicantIface>>
addP2pDevInterface(struct wpa_interface iface_params)258 Supplicant::addP2pDevInterface(struct wpa_interface iface_params)
259 {
260 	char primary_ifname[IFNAMSIZ];
261 	u32 primary_ifname_len =
262 		strlen(iface_params.ifname) - strlen(P2P_MGMT_DEVICE_PREFIX);
263 
264 	if(primary_ifname_len > IFNAMSIZ) {
265 		wpa_printf(MSG_DEBUG, "%s, Invalid primary iface name ", __FUNCTION__);
266 		return {{SupplicantStatusCode::FAILURE_ARGS_INVALID, ""}, {}};
267 	}
268 
269 	strncpy(primary_ifname, iface_params.ifname +
270 		strlen(P2P_MGMT_DEVICE_PREFIX), primary_ifname_len);
271 	wpa_printf(MSG_DEBUG, "%s, Initialize p2p-dev-wlan0 iface with"
272 		"primary_iface = %s", __FUNCTION__, primary_ifname);
273 	struct wpa_supplicant* wpa_s =
274 		wpa_supplicant_get_iface(wpa_global_, primary_ifname);
275 	if (!wpa_s) {
276 		wpa_printf(MSG_DEBUG, "%s,NULL wpa_s for wlan0", __FUNCTION__);
277 		return {{SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""},
278 			nullptr};
279 	}
280 	if (wpas_p2p_add_p2pdev_interface(
281 		wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
282 		wpa_printf(MSG_INFO,
283 			"Failed to enable P2P Device");
284 		return {{SupplicantStatusCode::FAILURE_UNKNOWN,
285 			"Enable P2P Device failed"}, {}};
286 	}
287 	return {{SupplicantStatusCode::SUCCESS,""}, {}};
288 }
289 
290 std::pair<SupplicantStatus, sp<ISupplicantIface>>
addInterfaceInternal(const IfaceInfo & iface_info)291 Supplicant::addInterfaceInternal(const IfaceInfo& iface_info)
292 {
293 	android::sp<ISupplicantIface> iface;
294 
295 	// Check if required |ifname| argument is empty.
296 	if (iface_info.name.empty()) {
297 		return {{SupplicantStatusCode::FAILURE_ARGS_INVALID, ""}, {}};
298 	}
299 	// Try to get the wpa_supplicant record for this iface, return
300 	// the iface object with the appropriate status code if it exists.
301 	SupplicantStatus status;
302 	std::tie(status, iface) = getInterfaceInternal(iface_info);
303 	if (status.code == SupplicantStatusCode::SUCCESS) {
304 		return {{SupplicantStatusCode::FAILURE_IFACE_EXISTS, ""},
305 			iface};
306 	}
307 
308 	struct wpa_interface iface_params = {};
309 	iface_params.driver = kIfaceDriverName;
310 	if (iface_info.type == IfaceType::P2P) {
311 		if (ensureConfigFileExists(
312 			kP2pIfaceConfPath, kOldP2pIfaceConfPath) != 0) {
313 			wpa_printf(
314 			    MSG_ERROR, "Conf file does not exists: %s",
315 			    kP2pIfaceConfPath);
316 			return {{SupplicantStatusCode::FAILURE_UNKNOWN,
317 				 "Conf file does not exist"},
318 				{}};
319 		}
320 		iface_params.confname = kP2pIfaceConfPath;
321 		int ret = access(kP2pIfaceConfOverlayPath, R_OK);
322 		if (ret == 0) {
323 			iface_params.confanother = kP2pIfaceConfOverlayPath;
324 		}
325 	} else {
326 		if (ensureConfigFileExists(
327 			kStaIfaceConfPath, kOldStaIfaceConfPath) != 0) {
328 			wpa_printf(
329 			    MSG_ERROR, "Conf file does not exists: %s",
330 			    kStaIfaceConfPath);
331 			return {{SupplicantStatusCode::FAILURE_UNKNOWN,
332 				 "Conf file does not exist"},
333 				{}};
334 		}
335 		iface_params.confname = kStaIfaceConfPath;
336 		int ret = access(kStaIfaceConfOverlayPath, R_OK);
337 		if (ret == 0) {
338 			iface_params.confanother = kStaIfaceConfOverlayPath;
339 		}
340 	}
341 	iface_params.ifname = iface_info.name.c_str();
342 	if (strncmp(iface_params.ifname, P2P_MGMT_DEVICE_PREFIX,
343 		strlen(P2P_MGMT_DEVICE_PREFIX)) == 0) {
344 		std::tie(status, iface) = addP2pDevInterface(iface_params);
345 		if (status.code != SupplicantStatusCode::SUCCESS) {
346 			return {{status.code,
347 				status.debugMessage.c_str()}, iface};
348 		}
349 	} else {
350 		struct wpa_supplicant* wpa_s =
351 			wpa_supplicant_add_iface(wpa_global_, &iface_params, NULL);
352 		if (!wpa_s) {
353 			return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
354 		}
355 	}
356 	// The supplicant core creates a corresponding hidl object via
357 	// HidlManager when |wpa_supplicant_add_iface| is called.
358 	return getInterfaceInternal(iface_info);
359 }
360 
removeInterfaceInternal(const IfaceInfo & iface_info)361 SupplicantStatus Supplicant::removeInterfaceInternal(
362     const IfaceInfo& iface_info)
363 {
364 	struct wpa_supplicant* wpa_s =
365 	    wpa_supplicant_get_iface(wpa_global_, iface_info.name.c_str());
366 	if (!wpa_s) {
367 		return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
368 	}
369 	if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0)) {
370 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
371 	}
372 	return {SupplicantStatusCode::SUCCESS, ""};
373 }
374 
375 std::pair<SupplicantStatus, sp<ISupplicantIface>>
getInterfaceInternal(const IfaceInfo & iface_info)376 Supplicant::getInterfaceInternal(const IfaceInfo& iface_info)
377 {
378 	struct wpa_supplicant* wpa_s =
379 	    wpa_supplicant_get_iface(wpa_global_, iface_info.name.c_str());
380 	if (!wpa_s) {
381 		return {{SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""},
382 			nullptr};
383 	}
384 	HidlManager* hidl_manager = HidlManager::getInstance();
385 	if (iface_info.type == IfaceType::P2P) {
386 		android::sp<ISupplicantP2pIface> iface;
387 		if (!hidl_manager ||
388 		    hidl_manager->getP2pIfaceHidlObjectByIfname(
389 			wpa_s->ifname, &iface)) {
390 			return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""},
391 				iface};
392 		}
393 		// Set this flag true here, since there is no HIDL initialize
394 		// method for the p2p config, and the supplicant interface is
395 		// not ready when the p2p iface is created.
396 		wpa_s->conf->persistent_reconnect = true;
397 		return {{SupplicantStatusCode::SUCCESS, ""}, iface};
398 	} else {
399 		android::sp<V1_1::ISupplicantStaIface> iface;
400 		if (!hidl_manager ||
401 		    hidl_manager->getStaIfaceHidlObjectByIfname(
402 			wpa_s->ifname, &iface)) {
403 			return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""},
404 				iface};
405 		}
406 		return {{SupplicantStatusCode::SUCCESS, ""}, iface};
407 	}
408 }
409 
410 std::pair<SupplicantStatus, std::vector<ISupplicant::IfaceInfo>>
listInterfacesInternal()411 Supplicant::listInterfacesInternal()
412 {
413 	std::vector<ISupplicant::IfaceInfo> ifaces;
414 	for (struct wpa_supplicant* wpa_s = wpa_global_->ifaces; wpa_s;
415 	     wpa_s = wpa_s->next) {
416 		if (wpa_s->global->p2p_init_wpa_s == wpa_s) {
417 			ifaces.emplace_back(ISupplicant::IfaceInfo{
418 			    IfaceType::P2P, wpa_s->ifname});
419 		} else {
420 			ifaces.emplace_back(ISupplicant::IfaceInfo{
421 			    IfaceType::STA, wpa_s->ifname});
422 		}
423 	}
424 	return {{SupplicantStatusCode::SUCCESS, ""}, std::move(ifaces)};
425 }
426 
registerCallbackInternal(const sp<ISupplicantCallback> & callback)427 SupplicantStatus Supplicant::registerCallbackInternal(
428     const sp<ISupplicantCallback>& callback)
429 {
430 	HidlManager* hidl_manager = HidlManager::getInstance();
431 	if (!hidl_manager ||
432 	    hidl_manager->addSupplicantCallbackHidlObject(callback)) {
433 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
434 	}
435 	return {SupplicantStatusCode::SUCCESS, ""};
436 }
437 
setDebugParamsInternal(ISupplicant::DebugLevel level,bool show_timestamp,bool show_keys)438 SupplicantStatus Supplicant::setDebugParamsInternal(
439     ISupplicant::DebugLevel level, bool show_timestamp, bool show_keys)
440 {
441 	if (wpa_supplicant_set_debug_params(
442 		wpa_global_, static_cast<uint32_t>(level), show_timestamp,
443 		show_keys)) {
444 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
445 	}
446 	return {SupplicantStatusCode::SUCCESS, ""};
447 }
448 
setConcurrencyPriorityInternal(IfaceType type)449 SupplicantStatus Supplicant::setConcurrencyPriorityInternal(IfaceType type)
450 {
451 	if (type == IfaceType::STA) {
452 		wpa_global_->conc_pref =
453 		    wpa_global::wpa_conc_pref::WPA_CONC_PREF_STA;
454 	} else if (type == IfaceType::P2P) {
455 		wpa_global_->conc_pref =
456 		    wpa_global::wpa_conc_pref::WPA_CONC_PREF_P2P;
457 	} else {
458 		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
459 	}
460 	return SupplicantStatus{SupplicantStatusCode::SUCCESS, ""};
461 }
462 }  // namespace implementation
463 }  // namespace V1_4
464 }  // namespace supplicant
465 }  // namespace wifi
466 }  // namespace hardware
467 }  // namespace android
468