Home | History | Annotate | Download | only in 1.2
      1 /*
      2  * hidl interface for wpa_supplicant daemon
      3  * Copyright (c) 2004-2016, Jouni Malinen <j (at) w1.fi>
      4  * Copyright (c) 2004-2016, Roshan Pius <rpius (at) 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 
     14 #include <android-base/file.h>
     15 #include <fcntl.h>
     16 #include <sys/stat.h>
     17 
     18 namespace {
     19 using namespace android::hardware::wifi::supplicant::V1_2;
     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 
     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  */
     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  */
     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_2 {
    161 namespace implementation {
    162 using hidl_return_util::validateAndCall;
    163 
    164 Supplicant::Supplicant(struct wpa_global* global) : wpa_global_(global) {}
    165 bool Supplicant::isValid()
    166 {
    167 	// This top level object cannot be invalidated.
    168 	return true;
    169 }
    170 
    171 Return<void> Supplicant::addInterface(
    172     const IfaceInfo& iface_info, addInterface_cb _hidl_cb)
    173 {
    174 	return validateAndCall(
    175 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    176 	    &Supplicant::addInterfaceInternal, _hidl_cb, iface_info);
    177 }
    178 
    179 Return<void> Supplicant::removeInterface(
    180     const IfaceInfo& iface_info, removeInterface_cb _hidl_cb)
    181 {
    182 	return validateAndCall(
    183 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    184 	    &Supplicant::removeInterfaceInternal, _hidl_cb, iface_info);
    185 }
    186 
    187 Return<void> Supplicant::getInterface(
    188     const IfaceInfo& iface_info, getInterface_cb _hidl_cb)
    189 {
    190 	return validateAndCall(
    191 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    192 	    &Supplicant::getInterfaceInternal, _hidl_cb, iface_info);
    193 }
    194 
    195 Return<void> Supplicant::listInterfaces(listInterfaces_cb _hidl_cb)
    196 {
    197 	return validateAndCall(
    198 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    199 	    &Supplicant::listInterfacesInternal, _hidl_cb);
    200 }
    201 
    202 Return<void> Supplicant::registerCallback(
    203     const sp<ISupplicantCallback>& callback, registerCallback_cb _hidl_cb)
    204 {
    205 	return validateAndCall(
    206 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    207 	    &Supplicant::registerCallbackInternal, _hidl_cb, callback);
    208 }
    209 
    210 Return<void> Supplicant::setDebugParams(
    211     ISupplicant::DebugLevel level, bool show_timestamp, bool show_keys,
    212     setDebugParams_cb _hidl_cb)
    213 {
    214 	return validateAndCall(
    215 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    216 	    &Supplicant::setDebugParamsInternal, _hidl_cb, level,
    217 	    show_timestamp, show_keys);
    218 }
    219 
    220 Return<void> Supplicant::setConcurrencyPriority(
    221     IfaceType type, setConcurrencyPriority_cb _hidl_cb)
    222 {
    223 	return validateAndCall(
    224 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    225 	    &Supplicant::setConcurrencyPriorityInternal, _hidl_cb, type);
    226 }
    227 
    228 Return<ISupplicant::DebugLevel> Supplicant::getDebugLevel()
    229 {
    230 	// TODO: Add SupplicantStatus in this method return for uniformity with
    231 	// the other methods in supplicant HIDL interface.
    232 	return (ISupplicant::DebugLevel)wpa_debug_level;
    233 }
    234 
    235 Return<bool> Supplicant::isDebugShowTimestampEnabled()
    236 {
    237 	// TODO: Add SupplicantStatus in this method return for uniformity with
    238 	// the other methods in supplicant HIDL interface.
    239 	return ((wpa_debug_timestamp != 0) ? true : false);
    240 }
    241 
    242 Return<bool> Supplicant::isDebugShowKeysEnabled()
    243 {
    244 	// TODO: Add SupplicantStatus in this method return for uniformity with
    245 	// the other methods in supplicant HIDL interface.
    246 	return ((wpa_debug_show_keys != 0) ? true : false);
    247 }
    248 
    249 Return<void> Supplicant::terminate()
    250 {
    251 	wpa_printf(MSG_INFO, "Terminating...");
    252 	wpa_supplicant_terminate_proc(wpa_global_);
    253 	return Void();
    254 }
    255 
    256 std::pair<SupplicantStatus, sp<ISupplicantIface>>
    257 Supplicant::addInterfaceInternal(const IfaceInfo& iface_info)
    258 {
    259 	android::sp<ISupplicantIface> iface;
    260 
    261 	// Check if required |ifname| argument is empty.
    262 	if (iface_info.name.empty()) {
    263 		return {{SupplicantStatusCode::FAILURE_ARGS_INVALID, ""}, {}};
    264 	}
    265 	// Try to get the wpa_supplicant record for this iface, return
    266 	// the iface object with the appropriate status code if it exists.
    267 	SupplicantStatus status;
    268 	std::tie(status, iface) = getInterfaceInternal(iface_info);
    269 	if (status.code == SupplicantStatusCode::SUCCESS) {
    270 		return {{SupplicantStatusCode::FAILURE_IFACE_EXISTS, ""},
    271 			iface};
    272 	}
    273 
    274 	struct wpa_interface iface_params = {};
    275 	iface_params.driver = kIfaceDriverName;
    276 	if (iface_info.type == IfaceType::P2P) {
    277 		if (ensureConfigFileExists(
    278 			kP2pIfaceConfPath, kOldP2pIfaceConfPath) != 0) {
    279 			wpa_printf(
    280 			    MSG_ERROR, "Conf file does not exists: %s",
    281 			    kP2pIfaceConfPath);
    282 			return {{SupplicantStatusCode::FAILURE_UNKNOWN,
    283 				 "Conf file does not exist"},
    284 				{}};
    285 		}
    286 		iface_params.confname = kP2pIfaceConfPath;
    287 		int ret = access(kP2pIfaceConfOverlayPath, R_OK);
    288 		if (ret == 0) {
    289 			iface_params.confanother = kP2pIfaceConfOverlayPath;
    290 		}
    291 	} else {
    292 		if (ensureConfigFileExists(
    293 			kStaIfaceConfPath, kOldStaIfaceConfPath) != 0) {
    294 			wpa_printf(
    295 			    MSG_ERROR, "Conf file does not exists: %s",
    296 			    kStaIfaceConfPath);
    297 			return {{SupplicantStatusCode::FAILURE_UNKNOWN,
    298 				 "Conf file does not exist"},
    299 				{}};
    300 		}
    301 		iface_params.confname = kStaIfaceConfPath;
    302 		int ret = access(kStaIfaceConfOverlayPath, R_OK);
    303 		if (ret == 0) {
    304 			iface_params.confanother = kStaIfaceConfOverlayPath;
    305 		}
    306 	}
    307 	iface_params.ifname = iface_info.name.c_str();
    308 	struct wpa_supplicant* wpa_s =
    309 	    wpa_supplicant_add_iface(wpa_global_, &iface_params, NULL);
    310 	if (!wpa_s) {
    311 		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
    312 	}
    313 	// The supplicant core creates a corresponding hidl object via
    314 	// HidlManager when |wpa_supplicant_add_iface| is called.
    315 	return getInterfaceInternal(iface_info);
    316 }
    317 
    318 SupplicantStatus Supplicant::removeInterfaceInternal(
    319     const IfaceInfo& iface_info)
    320 {
    321 	struct wpa_supplicant* wpa_s =
    322 	    wpa_supplicant_get_iface(wpa_global_, iface_info.name.c_str());
    323 	if (!wpa_s) {
    324 		return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
    325 	}
    326 	if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0)) {
    327 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
    328 	}
    329 	return {SupplicantStatusCode::SUCCESS, ""};
    330 }
    331 
    332 std::pair<SupplicantStatus, sp<ISupplicantIface>>
    333 Supplicant::getInterfaceInternal(const IfaceInfo& iface_info)
    334 {
    335 	struct wpa_supplicant* wpa_s =
    336 	    wpa_supplicant_get_iface(wpa_global_, iface_info.name.c_str());
    337 	if (!wpa_s) {
    338 		return {{SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""},
    339 			nullptr};
    340 	}
    341 	HidlManager* hidl_manager = HidlManager::getInstance();
    342 	if (iface_info.type == IfaceType::P2P) {
    343 		android::sp<ISupplicantP2pIface> iface;
    344 		if (!hidl_manager ||
    345 		    hidl_manager->getP2pIfaceHidlObjectByIfname(
    346 			wpa_s->ifname, &iface)) {
    347 			return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""},
    348 				iface};
    349 		}
    350 		// Set this flag true here, since there is no HIDL initialize
    351 		// method for the p2p config, and the supplicant interface is
    352 		// not ready when the p2p iface is created.
    353 		wpa_s->conf->persistent_reconnect = true;
    354 		return {{SupplicantStatusCode::SUCCESS, ""}, iface};
    355 	} else {
    356 		android::sp<ISupplicantStaIface> iface;
    357 		if (!hidl_manager ||
    358 		    hidl_manager->getStaIfaceHidlObjectByIfname(
    359 			wpa_s->ifname, &iface)) {
    360 			return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""},
    361 				iface};
    362 		}
    363 		return {{SupplicantStatusCode::SUCCESS, ""}, iface};
    364 	}
    365 }
    366 
    367 std::pair<SupplicantStatus, std::vector<ISupplicant::IfaceInfo>>
    368 Supplicant::listInterfacesInternal()
    369 {
    370 	std::vector<ISupplicant::IfaceInfo> ifaces;
    371 	for (struct wpa_supplicant* wpa_s = wpa_global_->ifaces; wpa_s;
    372 	     wpa_s = wpa_s->next) {
    373 		if (wpa_s->global->p2p_init_wpa_s == wpa_s) {
    374 			ifaces.emplace_back(ISupplicant::IfaceInfo{
    375 			    IfaceType::P2P, wpa_s->ifname});
    376 		} else {
    377 			ifaces.emplace_back(ISupplicant::IfaceInfo{
    378 			    IfaceType::STA, wpa_s->ifname});
    379 		}
    380 	}
    381 	return {{SupplicantStatusCode::SUCCESS, ""}, std::move(ifaces)};
    382 }
    383 
    384 SupplicantStatus Supplicant::registerCallbackInternal(
    385     const sp<ISupplicantCallback>& callback)
    386 {
    387 	HidlManager* hidl_manager = HidlManager::getInstance();
    388 	if (!hidl_manager ||
    389 	    hidl_manager->addSupplicantCallbackHidlObject(callback)) {
    390 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
    391 	}
    392 	return {SupplicantStatusCode::SUCCESS, ""};
    393 }
    394 
    395 SupplicantStatus Supplicant::setDebugParamsInternal(
    396     ISupplicant::DebugLevel level, bool show_timestamp, bool show_keys)
    397 {
    398 	if (wpa_supplicant_set_debug_params(
    399 		wpa_global_, static_cast<uint32_t>(level), show_timestamp,
    400 		show_keys)) {
    401 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
    402 	}
    403 	return {SupplicantStatusCode::SUCCESS, ""};
    404 }
    405 
    406 SupplicantStatus Supplicant::setConcurrencyPriorityInternal(IfaceType type)
    407 {
    408 	if (type == IfaceType::STA) {
    409 		wpa_global_->conc_pref =
    410 		    wpa_global::wpa_conc_pref::WPA_CONC_PREF_STA;
    411 	} else if (type == IfaceType::P2P) {
    412 		wpa_global_->conc_pref =
    413 		    wpa_global::wpa_conc_pref::WPA_CONC_PREF_P2P;
    414 	} else {
    415 		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
    416 	}
    417 	return SupplicantStatus{SupplicantStatusCode::SUCCESS, ""};
    418 }
    419 }  // namespace implementation
    420 }  // namespace V1_2
    421 }  // namespace supplicant
    422 }  // namespace wifi
    423 }  // namespace hardware
    424 }  // namespace android
    425