diff options
-rw-r--r-- | wpa_supplicant/hidl/1.0/hidl_manager.cpp | 4 | ||||
-rw-r--r-- | wpa_supplicant/hidl/1.0/supplicant.cpp | 122 | ||||
-rw-r--r-- | wpa_supplicant/hidl/1.0/supplicant.h | 1 |
3 files changed, 127 insertions, 0 deletions
diff --git a/wpa_supplicant/hidl/1.0/hidl_manager.cpp b/wpa_supplicant/hidl/1.0/hidl_manager.cpp index 152203c9..4655da2c 100644 --- a/wpa_supplicant/hidl/1.0/hidl_manager.cpp +++ b/wpa_supplicant/hidl/1.0/hidl_manager.cpp @@ -395,6 +395,10 @@ int HidlManager::registerHidlService(struct wpa_global *global) if (supplicant_object_->registerAsService() != android::NO_ERROR) { return 1; } + if (!supplicant_object_->ensureConfigFileExists()) { + // If config file does not exist, we cannot start supplicant. + return 1; + } return 0; } diff --git a/wpa_supplicant/hidl/1.0/supplicant.cpp b/wpa_supplicant/hidl/1.0/supplicant.cpp index a3815116..bf009b52 100644 --- a/wpa_supplicant/hidl/1.0/supplicant.cpp +++ b/wpa_supplicant/hidl/1.0/supplicant.cpp @@ -11,6 +11,110 @@ #include "hidl_return_util.h" #include "supplicant.h" +#include <android-base/file.h> +#include <fcntl.h> +#include <sys/stat.h> + +namespace { +constexpr char kStaIfaceConfPath[] = + "/data/misc/wifi/wpa_supplicant.conf"; +constexpr char kP2pIfaceConfPath[] = + "/data/misc/wifi/p2p_supplicant.conf"; +// Migrate conf files for existing devices. +constexpr char kTemplateConfPath[] = + "/vendor/etc/wifi/wpa_supplicant.conf"; +constexpr mode_t kConfigFileMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; + +int copyFile( + const std::string& src_file_path, const std::string& dest_file_path) +{ + std::string file_contents; + if (!android::base::ReadFileToString(src_file_path, &file_contents)) { + wpa_printf( + MSG_ERROR, "Failed to read from %s. Errno: %s", + src_file_path.c_str(), strerror(errno)); + return -1; + } + if (!android::base::WriteStringToFile( + file_contents, dest_file_path, kConfigFileMode, getuid(), + getgid())) { + wpa_printf( + MSG_ERROR, "Failed to write to %s. Errno: %s", + dest_file_path.c_str(), strerror(errno)); + return -1; + } + return 0; +} + +/** + * Copy |src_file_path| to |dest_file_path| if it exists. + * + * Returns 1 if |src_file_path| does not exists, + * Returns -1 if the copy fails. + * Returns 0 if the copy succeeds. + */ +int copyFileIfItExists( + const std::string& src_file_path, const std::string& dest_file_path) +{ + int ret = access(src_file_path.c_str(), R_OK); + if ((ret != 0) && (errno == ENOENT)) { + return 1; + } + ret = copyFile(src_file_path, dest_file_path); + if (ret != 0) { + wpa_printf( + MSG_ERROR, "Failed copying %s to %s.", + src_file_path.c_str(), dest_file_path.c_str()); + return -1; + } + return 0; +} + +/** + * Ensure that the specified config file pointed by |config_file_path| exists. + * a) If the |config_file_path| exists with the correct permissions, return. + * b) If the |config_file_path| does not exists, copy over the contents of + * |template_config_file_path|. + */ +int copyTemplateConfigFileIfNotExists( + const std::string& config_file_path, + const std::string& template_config_file_path) +{ + int ret = access(config_file_path.c_str(), R_OK | W_OK); + if (ret == 0) { + return 0; + } + if (errno == EACCES) { + ret = chmod(config_file_path.c_str(), kConfigFileMode); + if (ret == 0) { + return 0; + } else { + wpa_printf( + MSG_ERROR, "Cannot set RW to %s. Errno: %s", + config_file_path.c_str(), strerror(errno)); + return -1; + } + } else if (errno != ENOENT) { + wpa_printf( + MSG_ERROR, "Cannot acces %s. Errno: %s", + config_file_path.c_str(), strerror(errno)); + return -1; + } + ret = copyFileIfItExists(template_config_file_path, config_file_path); + if (ret == 0) { + wpa_printf( + MSG_INFO, "Copied template conf file from %s to %s", + template_config_file_path.c_str(), config_file_path.c_str()); + return 0; + } else if (ret == -1) { + unlink(config_file_path.c_str()); + return -1; + } + // Did not create the conf file. + return -1; +} +} // namespace + namespace android { namespace hardware { namespace wifi { @@ -31,6 +135,24 @@ bool Supplicant::isValid() return true; } +bool Supplicant::ensureConfigFileExists() +{ + // To support Android P Wifi framework, make sure the config file exists. + if (copyTemplateConfigFileIfNotExists( + kStaIfaceConfPath, kTemplateConfPath) != 0) { + wpa_printf(MSG_ERROR, "Conf file does not exists: %s", + kStaIfaceConfPath); + return false; + } + // P2P configuration file is not madatory but required for some devices. + if (copyTemplateConfigFileIfNotExists( + kP2pIfaceConfPath, kTemplateConfPath) != 0) { + wpa_printf(MSG_INFO, "Conf file does not exists: %s", + kP2pIfaceConfPath); + } + return true; +} + Return<void> Supplicant::getInterface( const IfaceInfo& iface_info, getInterface_cb _hidl_cb) { diff --git a/wpa_supplicant/hidl/1.0/supplicant.h b/wpa_supplicant/hidl/1.0/supplicant.h index 1ad84024..04d1ae17 100644 --- a/wpa_supplicant/hidl/1.0/supplicant.h +++ b/wpa_supplicant/hidl/1.0/supplicant.h @@ -40,6 +40,7 @@ public: Supplicant(struct wpa_global* global); ~Supplicant() override = default; bool isValid(); + bool ensureConfigFileExists(); // Hidl methods exposed. Return<void> getInterface( |