/*
 * hidl interface for wpa_supplicant daemon
 * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
 * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
 *
 * This software may be distributed under the terms of the BSD license.
 * See README for more details.
 */

#include "hidl_manager.h"
#include "hidl_return_util.h"
#include "supplicant.h"

#include <android-base/file.h>
#include <fcntl.h>
#include <sys/stat.h>

namespace {
using namespace android::hardware::wifi::supplicant::V1_2;

// Pre-populated interface params for interfaces controlled by wpa_supplicant.
// Note: This may differ for other OEM's. So, modify this accordingly.
constexpr char kIfaceDriverName[] = "nl80211";
constexpr char kStaIfaceConfPath[] =
    "/data/vendor/wifi/wpa/wpa_supplicant.conf";
constexpr char kStaIfaceConfOverlayPath[] =
    "/vendor/etc/wifi/wpa_supplicant_overlay.conf";
constexpr char kP2pIfaceConfPath[] =
    "/data/vendor/wifi/wpa/p2p_supplicant.conf";
constexpr char kP2pIfaceConfOverlayPath[] =
    "/vendor/etc/wifi/p2p_supplicant_overlay.conf";
// Migrate conf files for existing devices.
constexpr char kSystemTemplateConfPath[] =
    "/system/etc/wifi/wpa_supplicant.conf";
constexpr char kVendorTemplateConfPath[] =
    "/vendor/etc/wifi/wpa_supplicant.conf";
constexpr char kOldStaIfaceConfPath[] = "/data/misc/wifi/wpa_supplicant.conf";
constexpr char kOldP2pIfaceConfPath[] = "/data/misc/wifi/p2p_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 exist or not accessible,
 * 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);
	// Sepolicy denial (2018+ device) will return EACCESS instead of ENOENT.
	if ((ret != 0) && ((errno == ENOENT) || (errno == EACCES))) {
		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 exist, but |old_config_file_path|
 * exists, copy over the contents of the |old_config_file_path| to
 * |config_file_path|.
 * c) If the |config_file_path| & |old_config_file_path|
 * does not exists, copy over the contents of |template_config_file_path|.
 */
int ensureConfigFileExists(
    const std::string& config_file_path,
    const std::string& old_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(old_config_file_path, config_file_path);
	if (ret == 0) {
		wpa_printf(
		    MSG_INFO, "Migrated conf file from %s to %s",
		    old_config_file_path.c_str(), config_file_path.c_str());
		unlink(old_config_file_path.c_str());
		return 0;
	} else if (ret == -1) {
		unlink(config_file_path.c_str());
		return -1;
	}
	ret = copyFileIfItExists(kVendorTemplateConfPath, config_file_path);
	if (ret == 0) {
		wpa_printf(
		    MSG_INFO, "Copied template conf file from %s to %s",
		    kVendorTemplateConfPath, config_file_path.c_str());
		return 0;
	} else if (ret == -1) {
		unlink(config_file_path.c_str());
		return -1;
	}
	ret = copyFileIfItExists(kSystemTemplateConfPath, config_file_path);
	if (ret == 0) {
		wpa_printf(
		    MSG_INFO, "Copied template conf file from %s to %s",
		    kSystemTemplateConfPath, 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 {
namespace supplicant {
namespace V1_2 {
namespace implementation {
using hidl_return_util::validateAndCall;

Supplicant::Supplicant(struct wpa_global* global) : wpa_global_(global) {}
bool Supplicant::isValid()
{
	// This top level object cannot be invalidated.
	return true;
}

Return<void> Supplicant::addInterface(
    const IfaceInfo& iface_info, addInterface_cb _hidl_cb)
{
	return validateAndCall(
	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
	    &Supplicant::addInterfaceInternal, _hidl_cb, iface_info);
}

Return<void> Supplicant::removeInterface(
    const IfaceInfo& iface_info, removeInterface_cb _hidl_cb)
{
	return validateAndCall(
	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
	    &Supplicant::removeInterfaceInternal, _hidl_cb, iface_info);
}

Return<void> Supplicant::getInterface(
    const IfaceInfo& iface_info, getInterface_cb _hidl_cb)
{
	return validateAndCall(
	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
	    &Supplicant::getInterfaceInternal, _hidl_cb, iface_info);
}

Return<void> Supplicant::listInterfaces(listInterfaces_cb _hidl_cb)
{
	return validateAndCall(
	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
	    &Supplicant::listInterfacesInternal, _hidl_cb);
}

Return<void> Supplicant::registerCallback(
    const sp<ISupplicantCallback>& callback, registerCallback_cb _hidl_cb)
{
	return validateAndCall(
	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
	    &Supplicant::registerCallbackInternal, _hidl_cb, callback);
}

Return<void> Supplicant::setDebugParams(
    ISupplicant::DebugLevel level, bool show_timestamp, bool show_keys,
    setDebugParams_cb _hidl_cb)
{
	return validateAndCall(
	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
	    &Supplicant::setDebugParamsInternal, _hidl_cb, level,
	    show_timestamp, show_keys);
}

Return<void> Supplicant::setConcurrencyPriority(
    IfaceType type, setConcurrencyPriority_cb _hidl_cb)
{
	return validateAndCall(
	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
	    &Supplicant::setConcurrencyPriorityInternal, _hidl_cb, type);
}

Return<ISupplicant::DebugLevel> Supplicant::getDebugLevel()
{
	// TODO: Add SupplicantStatus in this method return for uniformity with
	// the other methods in supplicant HIDL interface.
	return (ISupplicant::DebugLevel)wpa_debug_level;
}

Return<bool> Supplicant::isDebugShowTimestampEnabled()
{
	// TODO: Add SupplicantStatus in this method return for uniformity with
	// the other methods in supplicant HIDL interface.
	return ((wpa_debug_timestamp != 0) ? true : false);
}

Return<bool> Supplicant::isDebugShowKeysEnabled()
{
	// TODO: Add SupplicantStatus in this method return for uniformity with
	// the other methods in supplicant HIDL interface.
	return ((wpa_debug_show_keys != 0) ? true : false);
}

Return<void> Supplicant::terminate()
{
	wpa_printf(MSG_INFO, "Terminating...");
	wpa_supplicant_terminate_proc(wpa_global_);
	return Void();
}

std::pair<SupplicantStatus, sp<ISupplicantIface>>
Supplicant::addInterfaceInternal(const IfaceInfo& iface_info)
{
	android::sp<ISupplicantIface> iface;

	// Check if required |ifname| argument is empty.
	if (iface_info.name.empty()) {
		return {{SupplicantStatusCode::FAILURE_ARGS_INVALID, ""}, {}};
	}
	// Try to get the wpa_supplicant record for this iface, return
	// the iface object with the appropriate status code if it exists.
	SupplicantStatus status;
	std::tie(status, iface) = getInterfaceInternal(iface_info);
	if (status.code == SupplicantStatusCode::SUCCESS) {
		return {{SupplicantStatusCode::FAILURE_IFACE_EXISTS, ""},
			iface};
	}

	struct wpa_interface iface_params = {};
	iface_params.driver = kIfaceDriverName;
	if (iface_info.type == IfaceType::P2P) {
		if (ensureConfigFileExists(
			kP2pIfaceConfPath, kOldP2pIfaceConfPath) != 0) {
			wpa_printf(
			    MSG_ERROR, "Conf file does not exists: %s",
			    kP2pIfaceConfPath);
			return {{SupplicantStatusCode::FAILURE_UNKNOWN,
				 "Conf file does not exist"},
				{}};
		}
		iface_params.confname = kP2pIfaceConfPath;
		int ret = access(kP2pIfaceConfOverlayPath, R_OK);
		if (ret == 0) {
			iface_params.confanother = kP2pIfaceConfOverlayPath;
		}
	} else {
		if (ensureConfigFileExists(
			kStaIfaceConfPath, kOldStaIfaceConfPath) != 0) {
			wpa_printf(
			    MSG_ERROR, "Conf file does not exists: %s",
			    kStaIfaceConfPath);
			return {{SupplicantStatusCode::FAILURE_UNKNOWN,
				 "Conf file does not exist"},
				{}};
		}
		iface_params.confname = kStaIfaceConfPath;
		int ret = access(kStaIfaceConfOverlayPath, R_OK);
		if (ret == 0) {
			iface_params.confanother = kStaIfaceConfOverlayPath;
		}
	}
	iface_params.ifname = iface_info.name.c_str();
	struct wpa_supplicant* wpa_s =
	    wpa_supplicant_add_iface(wpa_global_, &iface_params, NULL);
	if (!wpa_s) {
		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
	}
	// The supplicant core creates a corresponding hidl object via
	// HidlManager when |wpa_supplicant_add_iface| is called.
	return getInterfaceInternal(iface_info);
}

SupplicantStatus Supplicant::removeInterfaceInternal(
    const IfaceInfo& iface_info)
{
	struct wpa_supplicant* wpa_s =
	    wpa_supplicant_get_iface(wpa_global_, iface_info.name.c_str());
	if (!wpa_s) {
		return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
	}
	if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0)) {
		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
	}
	return {SupplicantStatusCode::SUCCESS, ""};
}

std::pair<SupplicantStatus, sp<ISupplicantIface>>
Supplicant::getInterfaceInternal(const IfaceInfo& iface_info)
{
	struct wpa_supplicant* wpa_s =
	    wpa_supplicant_get_iface(wpa_global_, iface_info.name.c_str());
	if (!wpa_s) {
		return {{SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""},
			nullptr};
	}
	HidlManager* hidl_manager = HidlManager::getInstance();
	if (iface_info.type == IfaceType::P2P) {
		android::sp<ISupplicantP2pIface> iface;
		if (!hidl_manager ||
		    hidl_manager->getP2pIfaceHidlObjectByIfname(
			wpa_s->ifname, &iface)) {
			return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""},
				iface};
		}
		// Set this flag true here, since there is no HIDL initialize
		// method for the p2p config, and the supplicant interface is
		// not ready when the p2p iface is created.
		wpa_s->conf->persistent_reconnect = true;
		return {{SupplicantStatusCode::SUCCESS, ""}, iface};
	} else {
		android::sp<ISupplicantStaIface> iface;
		if (!hidl_manager ||
		    hidl_manager->getStaIfaceHidlObjectByIfname(
			wpa_s->ifname, &iface)) {
			return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""},
				iface};
		}
		return {{SupplicantStatusCode::SUCCESS, ""}, iface};
	}
}

std::pair<SupplicantStatus, std::vector<ISupplicant::IfaceInfo>>
Supplicant::listInterfacesInternal()
{
	std::vector<ISupplicant::IfaceInfo> ifaces;
	for (struct wpa_supplicant* wpa_s = wpa_global_->ifaces; wpa_s;
	     wpa_s = wpa_s->next) {
		if (wpa_s->global->p2p_init_wpa_s == wpa_s) {
			ifaces.emplace_back(ISupplicant::IfaceInfo{
			    IfaceType::P2P, wpa_s->ifname});
		} else {
			ifaces.emplace_back(ISupplicant::IfaceInfo{
			    IfaceType::STA, wpa_s->ifname});
		}
	}
	return {{SupplicantStatusCode::SUCCESS, ""}, std::move(ifaces)};
}

SupplicantStatus Supplicant::registerCallbackInternal(
    const sp<ISupplicantCallback>& callback)
{
	HidlManager* hidl_manager = HidlManager::getInstance();
	if (!hidl_manager ||
	    hidl_manager->addSupplicantCallbackHidlObject(callback)) {
		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
	}
	return {SupplicantStatusCode::SUCCESS, ""};
}

SupplicantStatus Supplicant::setDebugParamsInternal(
    ISupplicant::DebugLevel level, bool show_timestamp, bool show_keys)
{
	if (wpa_supplicant_set_debug_params(
		wpa_global_, static_cast<uint32_t>(level), show_timestamp,
		show_keys)) {
		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
	}
	return {SupplicantStatusCode::SUCCESS, ""};
}

SupplicantStatus Supplicant::setConcurrencyPriorityInternal(IfaceType type)
{
	if (type == IfaceType::STA) {
		wpa_global_->conc_pref =
		    wpa_global::wpa_conc_pref::WPA_CONC_PREF_STA;
	} else if (type == IfaceType::P2P) {
		wpa_global_->conc_pref =
		    wpa_global::wpa_conc_pref::WPA_CONC_PREF_P2P;
	} else {
		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
	}
	return SupplicantStatus{SupplicantStatusCode::SUCCESS, ""};
}
}  // namespace implementation
}  // namespace V1_2
}  // namespace supplicant
}  // namespace wifi
}  // namespace hardware
}  // namespace android
