blob: 2f17e1184d529741cf2cae00daf5e7ba46847606 [file] [log] [blame]
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001/*
Dustin Brown4ea21db2018-01-05 14:13:17 -08002 * Copyright (c) 2015-2018 The Linux Foundation. All rights reserved.
Ravi Joshideb5a8d2015-11-09 19:11:43 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/**
23 * DOC: wlan_hdd_subnet_detect.c
24 *
25 * WLAN Host Device Driver subnet detect API implementation
26 */
27
28#include <linux/version.h>
29#include <linux/module.h>
30#include <linux/kernel.h>
31#include <net/cfg80211.h>
32#include <ani_global.h>
33#include "sme_api.h"
34#include "wlan_hdd_main.h"
35#include "wlan_hdd_subnet_detect.h"
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080036#include <qca_vendor.h>
Ravi Joshideb5a8d2015-11-09 19:11:43 -080037
38/*
39 * define short names for the global vendor params
40 * used by __wlan_hdd_cfg80211_set_gateway_params()
41 */
42#define PARAM_MAC_ADDR QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_GW_MAC_ADDR
43#define PARAM_IPV4_ADDR QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_IPV4_ADDR
44#define PARAM_IPV6_ADDR QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_IPV6_ADDR
45
46static const struct nla_policy
47 policy[QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_MAX + 1] = {
48 [PARAM_MAC_ADDR] = {
Zhang Qian63393102017-08-14 15:04:05 +080049 .type = NLA_UNSPEC,
Anurag Chouhan6d760662016-02-20 16:05:43 +053050 .len = QDF_MAC_ADDR_SIZE
Ravi Joshideb5a8d2015-11-09 19:11:43 -080051 },
52 [PARAM_IPV4_ADDR] = {
Zhang Qian63393102017-08-14 15:04:05 +080053 .type = NLA_UNSPEC,
Anurag Chouhan6d760662016-02-20 16:05:43 +053054 .len = QDF_IPV4_ADDR_SIZE
Ravi Joshideb5a8d2015-11-09 19:11:43 -080055 },
56 [PARAM_IPV6_ADDR] = {
Zhang Qian63393102017-08-14 15:04:05 +080057 .type = NLA_UNSPEC,
Anurag Chouhan6d760662016-02-20 16:05:43 +053058 .len = QDF_IPV6_ADDR_SIZE
Ravi Joshideb5a8d2015-11-09 19:11:43 -080059 }
60};
61
62/**
63 * __wlan_hdd_cfg80211_set_gateway_params() - set gateway params
64 * @wiphy: Pointer to wireless phy
65 * @wdev: Pointer to wireless device
66 * @data: Pointer to data
67 * @data_len: Data length
68 *
69 * Return: 0 on success, negative errno on failure
70 */
71static int __wlan_hdd_cfg80211_set_gateway_params(struct wiphy *wiphy,
72 struct wireless_dev *wdev,
73 const void *data,
74 int data_len)
75{
76 struct net_device *dev = wdev->netdev;
Jeff Johnsonb4fc39b2017-08-29 14:20:50 -070077 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson714fb032017-08-28 11:41:29 -070078 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Ravi Joshideb5a8d2015-11-09 19:11:43 -080079 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_MAX + 1];
80 struct gateway_param_update_req req = { 0 };
81 int ret;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053082 QDF_STATUS status;
Ravi Joshideb5a8d2015-11-09 19:11:43 -080083
Jeff Johnson1f61b612016-02-12 16:28:33 -080084 ENTER_DEV(dev);
Ravi Joshideb5a8d2015-11-09 19:11:43 -080085
86 ret = wlan_hdd_validate_context(hdd_ctx);
87 if (0 != ret)
88 return ret;
89
90 /* user may have disabled the feature in INI */
91 if (!hdd_ctx->config->enable_lfr_subnet_detection) {
92 hdd_info("LFR Subnet Detection disabled in INI");
93 return -ENOTSUPP;
94 }
95
96 /* The gateway parameters are only valid in the STA persona
97 * and only in the connected state.
98 */
Krunal Sonif07bb382016-03-10 13:02:11 -080099 if (QDF_STA_MODE != adapter->device_mode) {
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800100 hdd_err("Received GW param update for non-STA mode adapter");
101 return -ENOTSUPP;
102 }
103
104 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
105 hdd_err("Received GW param update in disconnected state!");
106 return -ENOTSUPP;
107 }
108
109 /* Extract NL parameters
110 * mac_addr: 6 bytes
111 * ipv4 addr: 4 bytes
112 * ipv6 addr: 16 bytes
113 */
Dustin Brown4ea21db2018-01-05 14:13:17 -0800114 if (wlan_cfg80211_nla_parse(tb,
115 QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_MAX,
116 data, data_len, policy)) {
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800117 hdd_err("Invalid ATTR list");
118 return -EINVAL;
119 }
120
121 if (!tb[PARAM_MAC_ADDR]) {
122 hdd_err("request mac addr failed");
123 return -EINVAL;
124 }
125 nla_memcpy(req.gw_mac_addr.bytes, tb[PARAM_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +0530126 QDF_MAC_ADDR_SIZE);
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800127
128 /* req ipv4_addr_type and ipv6_addr_type are initially false due
129 * to zeroing the struct
130 */
131 if (tb[PARAM_IPV4_ADDR]) {
132 nla_memcpy(req.ipv4_addr, tb[PARAM_IPV4_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +0530133 QDF_IPV4_ADDR_SIZE);
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800134 req.ipv4_addr_type = true;
135 }
136
137 if (tb[PARAM_IPV6_ADDR]) {
138 nla_memcpy(&req.ipv6_addr, tb[PARAM_IPV6_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +0530139 QDF_IPV6_ADDR_SIZE);
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800140 req.ipv6_addr_type = true;
141 }
142
143 if (!req.ipv4_addr_type && !req.ipv6_addr_type) {
144 hdd_err("invalid ipv4 or ipv6 gateway address");
145 return -EINVAL;
146 }
147
148 req.max_retries = 3;
149 req.timeout = 100; /* in milliseconds */
Jeff Johnson1b780e42017-10-31 14:11:45 -0700150 req.session_id = adapter->session_id;
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800151
152 hdd_info("**** Gateway Parameters: ****");
153 hdd_info("session id: %d", req.session_id);
154 hdd_info("ipv4 addr type: %d", req.ipv4_addr_type);
155 hdd_info("ipv6 addr type: %d", req.ipv6_addr_type);
156 hdd_info("gw mac addr: %pM", req.gw_mac_addr.bytes);
157 hdd_info("ipv4 addr: %pI4", req.ipv4_addr);
158 hdd_info("ipv6 addr: %pI6c", req.ipv6_addr);
159
160 status = sme_gateway_param_update(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530161 if (!QDF_IS_STATUS_SUCCESS(status)) {
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800162 hdd_err("sme_gateway_param_update failed(err=%d)", status);
163 ret = -EINVAL;
164 }
165
166 EXIT();
167 return ret;
168}
169
170/**
171 * wlan_hdd_cfg80211_set_gateway_params() - set gateway parameters
172 * @wiphy: wiphy structure pointer
173 * @wdev: Wireless device structure pointer
174 * @data: Pointer to the data received
175 * @data_len: Length of @data
176 *
177 * The API is invoked by the user space to set the gateway parameters
178 * such as mac address and the IP address which is used for detecting
179 * the IP subnet change
180 *
181 * Return: 0 on success; errno on failure
182 */
183int wlan_hdd_cfg80211_set_gateway_params(struct wiphy *wiphy,
184 struct wireless_dev *wdev, const void *data, int data_len)
185{
186 int ret;
187
188 cds_ssr_protect(__func__);
189
190 ret = __wlan_hdd_cfg80211_set_gateway_params(
191 wiphy, wdev, data, data_len);
192 cds_ssr_unprotect(__func__);
193 return ret;
194}
195#undef PARAM_MAC_ADDR
196#undef PARAM_IPV4_ADDR
197#undef PARAM_IPV6_ADDR