/*
 * Copyright (c) 2015-2018 The Linux Foundation. All rights reserved.
 *
 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
 *
 *
 * Permission to use, copy, modify, and/or distribute this software for
 * any purpose with or without fee is hereby granted, provided that the
 * above copyright notice and this permission notice appear in all
 * copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */

/**
 * DOC: wlan_hdd_subnet_detect.c
 *
 * WLAN Host Device Driver subnet detect API implementation
 */

#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <net/cfg80211.h>
#include <ani_global.h>
#include "sme_api.h"
#include "wlan_hdd_main.h"
#include "wlan_hdd_subnet_detect.h"
#include <qca_vendor.h>

/*
 * define short names for the global vendor params
 * used by __wlan_hdd_cfg80211_set_gateway_params()
 */
#define PARAM_MAC_ADDR QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_GW_MAC_ADDR
#define PARAM_IPV4_ADDR QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_IPV4_ADDR
#define PARAM_IPV6_ADDR QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_IPV6_ADDR

static const struct nla_policy
	policy[QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_MAX + 1] = {
		[PARAM_MAC_ADDR] = {
				.type = NLA_UNSPEC,
				.len = QDF_MAC_ADDR_SIZE
		},
		[PARAM_IPV4_ADDR] = {
				.type = NLA_UNSPEC,
				.len = QDF_IPV4_ADDR_SIZE
		},
		[PARAM_IPV6_ADDR] = {
				.type = NLA_UNSPEC,
				.len = QDF_IPV6_ADDR_SIZE
		}
};

/**
 * __wlan_hdd_cfg80211_set_gateway_params() - set gateway params
 * @wiphy: Pointer to wireless phy
 * @wdev: Pointer to wireless device
 * @data: Pointer to data
 * @data_len: Data length
 *
 * Return: 0 on success, negative errno on failure
 */
static int __wlan_hdd_cfg80211_set_gateway_params(struct wiphy *wiphy,
		struct wireless_dev *wdev,
		const void *data,
		int data_len)
{
	struct net_device *dev = wdev->netdev;
	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_MAX + 1];
	struct gateway_param_update_req req = { 0 };
	int ret;
	QDF_STATUS status;

	ENTER_DEV(dev);

	ret = wlan_hdd_validate_context(hdd_ctx);
	if (0 != ret)
		return ret;

	/* user may have disabled the feature in INI */
	if (!hdd_ctx->config->enable_lfr_subnet_detection) {
		hdd_info("LFR Subnet Detection disabled in INI");
		return -ENOTSUPP;
	}

	/* The gateway parameters are only valid in the STA persona
	 * and only in the connected state.
	 */
	if (QDF_STA_MODE != adapter->device_mode) {
		hdd_err("Received GW param update for non-STA mode adapter");
		return -ENOTSUPP;
	}

	if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
		hdd_err("Received GW param update in disconnected state!");
		return -ENOTSUPP;
	}

	/* Extract NL parameters
	 * mac_addr:  6 bytes
	 * ipv4 addr: 4 bytes
	 * ipv6 addr: 16 bytes
	 */
	if (wlan_cfg80211_nla_parse(tb,
				    QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_MAX,
				    data, data_len, policy)) {
		hdd_err("Invalid ATTR list");
		return -EINVAL;
	}

	if (!tb[PARAM_MAC_ADDR]) {
		hdd_err("request mac addr failed");
		return -EINVAL;
	}
	nla_memcpy(req.gw_mac_addr.bytes, tb[PARAM_MAC_ADDR],
			QDF_MAC_ADDR_SIZE);

	/* req ipv4_addr_type and ipv6_addr_type are initially false due
	 * to zeroing the struct
	 */
	if (tb[PARAM_IPV4_ADDR]) {
		nla_memcpy(req.ipv4_addr, tb[PARAM_IPV4_ADDR],
			QDF_IPV4_ADDR_SIZE);
		req.ipv4_addr_type = true;
	}

	if (tb[PARAM_IPV6_ADDR]) {
		nla_memcpy(&req.ipv6_addr, tb[PARAM_IPV6_ADDR],
			QDF_IPV6_ADDR_SIZE);
		req.ipv6_addr_type = true;
	}

	if (!req.ipv4_addr_type && !req.ipv6_addr_type) {
		hdd_err("invalid ipv4 or ipv6 gateway address");
		return -EINVAL;
	}

	req.max_retries = 3;
	req.timeout = 100;   /* in milliseconds */
	req.session_id = adapter->session_id;

	hdd_info("**** Gateway Parameters: ****");
	hdd_info("session id: %d", req.session_id);
	hdd_info("ipv4 addr type: %d", req.ipv4_addr_type);
	hdd_info("ipv6 addr type: %d", req.ipv6_addr_type);
	hdd_info("gw mac addr: %pM", req.gw_mac_addr.bytes);
	hdd_info("ipv4 addr: %pI4", req.ipv4_addr);
	hdd_info("ipv6 addr: %pI6c", req.ipv6_addr);

	status = sme_gateway_param_update(hdd_ctx->hHal, &req);
	if (!QDF_IS_STATUS_SUCCESS(status)) {
		hdd_err("sme_gateway_param_update failed(err=%d)", status);
		ret = -EINVAL;
	}

	EXIT();
	return ret;
}

/**
 * wlan_hdd_cfg80211_set_gateway_params() - set gateway parameters
 * @wiphy:    wiphy structure pointer
 * @wdev:     Wireless device structure pointer
 * @data:     Pointer to the data received
 * @data_len: Length of @data
 *
 * The API is invoked by the user space to set the gateway parameters
 * such as mac address and the IP address which is used for detecting
 * the IP subnet change
 *
 * Return: 0 on success; errno on failure
 */
int wlan_hdd_cfg80211_set_gateway_params(struct wiphy *wiphy,
		struct wireless_dev *wdev, const void *data, int data_len)
{
	int ret;

	cds_ssr_protect(__func__);

	ret = __wlan_hdd_cfg80211_set_gateway_params(
				wiphy, wdev, data, data_len);
	cds_ssr_unprotect(__func__);
	return ret;
}
#undef PARAM_MAC_ADDR
#undef PARAM_IPV4_ADDR
#undef PARAM_IPV6_ADDR
