Home | History | Annotate | Download | only in 1.0
      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 constexpr char kStaIfaceConfPath[] =
     20     "/data/misc/wifi/wpa_supplicant.conf";
     21 constexpr char kP2pIfaceConfPath[] =
     22     "/data/misc/wifi/p2p_supplicant.conf";
     23 // Migrate conf files for existing devices.
     24 constexpr char kTemplateConfPath[] =
     25     "/vendor/etc/wifi/wpa_supplicant.conf";
     26 constexpr mode_t kConfigFileMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
     27 
     28 int copyFile(
     29     const std::string& src_file_path, const std::string& dest_file_path)
     30 {
     31 	std::string file_contents;
     32 	if (!android::base::ReadFileToString(src_file_path, &file_contents)) {
     33 		wpa_printf(
     34 		    MSG_ERROR, "Failed to read from %s. Errno: %s",
     35 		    src_file_path.c_str(), strerror(errno));
     36 		return -1;
     37 	}
     38 	if (!android::base::WriteStringToFile(
     39 		file_contents, dest_file_path, kConfigFileMode, getuid(),
     40 		getgid())) {
     41 		wpa_printf(
     42 		    MSG_ERROR, "Failed to write to %s. Errno: %s",
     43 		    dest_file_path.c_str(), strerror(errno));
     44 		return -1;
     45 	}
     46 	return 0;
     47 }
     48 
     49 /**
     50  * Copy |src_file_path| to |dest_file_path| if it exists.
     51  *
     52  * Returns 1 if |src_file_path| does not exists,
     53  * Returns -1 if the copy fails.
     54  * Returns 0 if the copy succeeds.
     55  */
     56 int copyFileIfItExists(
     57     const std::string& src_file_path, const std::string& dest_file_path)
     58 {
     59 	int ret = access(src_file_path.c_str(), R_OK);
     60 	if ((ret != 0) && (errno == ENOENT)) {
     61 		return 1;
     62 	}
     63 	ret = copyFile(src_file_path, dest_file_path);
     64 	if (ret != 0) {
     65 		wpa_printf(
     66 		    MSG_ERROR, "Failed copying %s to %s.",
     67 		    src_file_path.c_str(), dest_file_path.c_str());
     68 		return -1;
     69 	}
     70 	return 0;
     71 }
     72 
     73 /**
     74  * Ensure that the specified config file pointed by |config_file_path| exists.
     75  * a) If the |config_file_path| exists with the correct permissions, return.
     76  * b) If the |config_file_path| does not exists, copy over the contents of
     77  * |template_config_file_path|.
     78  */
     79 int copyTemplateConfigFileIfNotExists(
     80     const std::string& config_file_path,
     81     const std::string& template_config_file_path)
     82 {
     83 	int ret = access(config_file_path.c_str(), R_OK | W_OK);
     84 	if (ret == 0) {
     85 		return 0;
     86 	}
     87 	if (errno == EACCES) {
     88 		ret = chmod(config_file_path.c_str(), kConfigFileMode);
     89 		if (ret == 0) {
     90 			return 0;
     91 		} else {
     92 			wpa_printf(
     93 			    MSG_ERROR, "Cannot set RW to %s. Errno: %s",
     94 			    config_file_path.c_str(), strerror(errno));
     95 			return -1;
     96 		}
     97 	} else if (errno != ENOENT) {
     98 		wpa_printf(
     99 		    MSG_ERROR, "Cannot acces %s. Errno: %s",
    100 		    config_file_path.c_str(), strerror(errno));
    101 		return -1;
    102 	}
    103 	ret = copyFileIfItExists(template_config_file_path, config_file_path);
    104 	if (ret == 0) {
    105 		wpa_printf(
    106 		    MSG_INFO, "Copied template conf file from %s to %s",
    107 		    template_config_file_path.c_str(), config_file_path.c_str());
    108 		return 0;
    109 	} else if (ret == -1) {
    110 		unlink(config_file_path.c_str());
    111 		return -1;
    112 	}
    113 	// Did not create the conf file.
    114 	return -1;
    115 }
    116 }  // namespace
    117 
    118 namespace android {
    119 namespace hardware {
    120 namespace wifi {
    121 namespace supplicant {
    122 namespace V1_0 {
    123 namespace implementation {
    124 using hidl_return_util::validateAndCall;
    125 
    126 // These are hardcoded for android.
    127 const char Supplicant::kDriverName[] = "nl80211";
    128 const char Supplicant::kConfigFilePath[] =
    129     "/data/misc/wifi/wpa_supplicant.conf";
    130 
    131 Supplicant::Supplicant(struct wpa_global* global) : wpa_global_(global) {}
    132 bool Supplicant::isValid()
    133 {
    134 	// This top level object cannot be invalidated.
    135 	return true;
    136 }
    137 
    138 bool Supplicant::ensureConfigFileExists()
    139 {
    140 	// To support Android P Wifi framework, make sure the config file exists.
    141 	if (copyTemplateConfigFileIfNotExists(
    142 		kStaIfaceConfPath, kTemplateConfPath) != 0) {
    143 		wpa_printf(MSG_ERROR, "Conf file does not exists: %s",
    144 		    kStaIfaceConfPath);
    145 		return false;
    146 	}
    147 	// P2P configuration file is not madatory but required for some devices.
    148 	if (copyTemplateConfigFileIfNotExists(
    149 		kP2pIfaceConfPath, kTemplateConfPath) != 0) {
    150 		wpa_printf(MSG_INFO, "Conf file does not exists: %s",
    151 		    kP2pIfaceConfPath);
    152 	}
    153 	return true;
    154 }
    155 
    156 Return<void> Supplicant::getInterface(
    157     const IfaceInfo& iface_info, getInterface_cb _hidl_cb)
    158 {
    159 	return validateAndCall(
    160 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    161 	    &Supplicant::getInterfaceInternal, _hidl_cb, iface_info);
    162 }
    163 
    164 Return<void> Supplicant::listInterfaces(listInterfaces_cb _hidl_cb)
    165 {
    166 	return validateAndCall(
    167 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    168 	    &Supplicant::listInterfacesInternal, _hidl_cb);
    169 }
    170 
    171 Return<void> Supplicant::registerCallback(
    172     const sp<ISupplicantCallback>& callback, registerCallback_cb _hidl_cb)
    173 {
    174 	return validateAndCall(
    175 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    176 	    &Supplicant::registerCallbackInternal, _hidl_cb, callback);
    177 }
    178 
    179 Return<void> Supplicant::setDebugParams(
    180     ISupplicant::DebugLevel level, bool show_timestamp, bool show_keys,
    181     setDebugParams_cb _hidl_cb)
    182 {
    183 	return validateAndCall(
    184 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    185 	    &Supplicant::setDebugParamsInternal, _hidl_cb, level,
    186 	    show_timestamp, show_keys);
    187 }
    188 
    189 Return<void> Supplicant::setConcurrencyPriority(
    190     IfaceType type, setConcurrencyPriority_cb _hidl_cb)
    191 {
    192 	return validateAndCall(
    193 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
    194 	    &Supplicant::setConcurrencyPriorityInternal, _hidl_cb, type);
    195 }
    196 
    197 Return<ISupplicant::DebugLevel> Supplicant::getDebugLevel()
    198 {
    199 	// TODO: Add SupplicantStatus in this method return for uniformity with
    200 	// the other methods in supplicant HIDL interface.
    201 	return (ISupplicant::DebugLevel)wpa_debug_level;
    202 }
    203 
    204 Return<bool> Supplicant::isDebugShowTimestampEnabled()
    205 {
    206 	// TODO: Add SupplicantStatus in this method return for uniformity with
    207 	// the other methods in supplicant HIDL interface.
    208 	return ((wpa_debug_timestamp != 0) ? true : false);
    209 }
    210 
    211 Return<bool> Supplicant::isDebugShowKeysEnabled()
    212 {
    213 	// TODO: Add SupplicantStatus in this method return for uniformity with
    214 	// the other methods in supplicant HIDL interface.
    215 	return ((wpa_debug_show_keys != 0) ? true : false);
    216 }
    217 
    218 std::pair<SupplicantStatus, sp<ISupplicantIface>>
    219 Supplicant::getInterfaceInternal(const IfaceInfo& iface_info)
    220 {
    221 	struct wpa_supplicant* wpa_s =
    222 	    wpa_supplicant_get_iface(wpa_global_, iface_info.name.c_str());
    223 	if (!wpa_s) {
    224 		return {{SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""},
    225 			nullptr};
    226 	}
    227 	HidlManager* hidl_manager = HidlManager::getInstance();
    228 	if (iface_info.type == IfaceType::P2P) {
    229 		android::sp<ISupplicantP2pIface> iface;
    230 		if (!hidl_manager ||
    231 		    hidl_manager->getP2pIfaceHidlObjectByIfname(
    232 			wpa_s->ifname, &iface)) {
    233 			return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""},
    234 				iface};
    235 		}
    236 		// Set this flag true here, since there is no HIDL initialize method for the p2p
    237 		// config, and the supplicant interface is not ready when the p2p iface is created.
    238 		wpa_s->conf->persistent_reconnect = true;
    239 		return {{SupplicantStatusCode::SUCCESS, ""}, iface};
    240 	} else {
    241 		android::sp<ISupplicantStaIface> iface;
    242 		if (!hidl_manager ||
    243 		    hidl_manager->getStaIfaceHidlObjectByIfname(
    244 			wpa_s->ifname, &iface)) {
    245 			return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""},
    246 				iface};
    247 		}
    248 		return {{SupplicantStatusCode::SUCCESS, ""}, iface};
    249 	}
    250 }
    251 
    252 std::pair<SupplicantStatus, std::vector<ISupplicant::IfaceInfo>>
    253 Supplicant::listInterfacesInternal()
    254 {
    255 	std::vector<ISupplicant::IfaceInfo> ifaces;
    256 	for (struct wpa_supplicant* wpa_s = wpa_global_->ifaces; wpa_s;
    257 	     wpa_s = wpa_s->next) {
    258 		if (wpa_s->global->p2p_init_wpa_s == wpa_s) {
    259 			ifaces.emplace_back(ISupplicant::IfaceInfo{
    260 			    IfaceType::P2P, wpa_s->ifname});
    261 		} else {
    262 			ifaces.emplace_back(ISupplicant::IfaceInfo{
    263 			    IfaceType::STA, wpa_s->ifname});
    264 		}
    265 	}
    266 	return {{SupplicantStatusCode::SUCCESS, ""}, std::move(ifaces)};
    267 }
    268 
    269 SupplicantStatus Supplicant::registerCallbackInternal(
    270     const sp<ISupplicantCallback>& callback)
    271 {
    272 	HidlManager* hidl_manager = HidlManager::getInstance();
    273 	if (!hidl_manager ||
    274 	    hidl_manager->addSupplicantCallbackHidlObject(callback)) {
    275 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
    276 	}
    277 	return {SupplicantStatusCode::SUCCESS, ""};
    278 }
    279 
    280 SupplicantStatus Supplicant::setDebugParamsInternal(
    281     ISupplicant::DebugLevel level, bool show_timestamp, bool show_keys)
    282 {
    283 	if (wpa_supplicant_set_debug_params(
    284 		wpa_global_, static_cast<uint32_t>(level), show_timestamp,
    285 		show_keys)) {
    286 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
    287 	}
    288 	return {SupplicantStatusCode::SUCCESS, ""};
    289 }
    290 
    291 SupplicantStatus Supplicant::setConcurrencyPriorityInternal(IfaceType type)
    292 {
    293 	if (type == IfaceType::STA) {
    294 		wpa_global_->conc_pref =
    295 		    wpa_global::wpa_conc_pref::WPA_CONC_PREF_STA;
    296 	} else if (type == IfaceType::P2P) {
    297 		wpa_global_->conc_pref =
    298 		    wpa_global::wpa_conc_pref::WPA_CONC_PREF_P2P;
    299 	} else {
    300 		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
    301 	}
    302 	return SupplicantStatus{SupplicantStatusCode::SUCCESS, ""};
    303 }
    304 }  // namespace implementation
    305 }  // namespace V1_0
    306 }  // namespace wifi
    307 }  // namespace supplicant
    308 }  // namespace hardware
    309 }  // namespace android
    310