blob: 22a8dccb8af9455c0a20d669cf0250b8a67b8dc7 [file] [log] [blame]
developer8fb759f2022-02-21 16:39:38 +08001/* Copyright (C) 2021 Mediatek Inc. */
2#define _GNU_SOURCE
3
4#include "mtk_vendor_nl80211.h"
5#include "mt76-vendor.h"
6#include "mwctl.h"
7
8static unsigned char ascii2hex(char *in, unsigned int *out)
9{
10 unsigned int hex_val, val;
11 char *p, asc_val;
12
13 hex_val = 0;
14 p = (char *)in;
15
16 while ((*p) != 0) {
17 val = 0;
18 asc_val = *p;
19
20 if ((asc_val >= 'a') && (asc_val <= 'f'))
21 val = asc_val - 87;
22 else if ((*p >= 'A') && (asc_val <= 'F'))
23 val = asc_val - 55;
24 else if ((asc_val >= '0') && (asc_val <= '9'))
25 val = asc_val - 48;
26 else
27 return 0;
28
29 hex_val = (hex_val << 4) + val;
30 p++;
31 }
32
33 *out = hex_val;
34 return 1;
35}
36
37static int handle_common_command(struct nl_msg *msg,
38 int argc, char **argv, int attr)
39{
40 void *data;
41 size_t len = 0;
42 char *cmd_str;
43
44 data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
45 if (!data)
46 return -ENOMEM;
47
48 if (argc > 0) {
49 cmd_str = argv[0];
50
51 len = strlen(cmd_str);
52 if (len) {
53 if (nla_put(msg, attr, len, (unsigned char*)cmd_str))
54 return -EMSGSIZE;
55 }
56 }
57 nla_nest_end(msg, data);
58
59 return 0;
60}
61
62int handle_set_command(struct nl_msg *msg, int argc,
63 char **argv, void *ctx)
64{
65 return handle_common_command(msg, argc, argv, MTK_NL80211_VENDOR_ATTR_VENDOR_SET_CMD_STR);
66}
67
68TOPLEVEL(set, "[param]=[value]", MTK_NL80211_VENDOR_SUBCMD_VENDOR_SET, 0, CIB_NETDEV, handle_set_command,
69 "this command is used to be compatible with old iwpriv set command, e.g iwpriv ra0 set channel=36");
70
71int show_callback(struct nl_msg *msg, void *cb)
72{
73 struct nlattr *tb[NL80211_ATTR_MAX + 1];
74 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_ATTR_VENDOR_SHOW_ATTR_MAX + 1];
75 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
76 char *show_str = NULL;
77 int err = 0;
78
79 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
80 genlmsg_attrlen(gnlh, 0), NULL);
81 if (err < 0)
82 return err;
83
84 if (tb[NL80211_ATTR_VENDOR_DATA]) {
85 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_ATTR_VENDOR_SHOW_ATTR_MAX,
86 tb[NL80211_ATTR_VENDOR_DATA], NULL);
87 if (err < 0)
88 return err;
89
90 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_VENDOR_SHOW_RSP_STR]) {
91 show_str = nla_data(vndr_tb[MTK_NL80211_VENDOR_ATTR_VENDOR_SHOW_RSP_STR]);
92 printf("%s\n", show_str);
93 }
94 } else
95 printf("no any show rsp string from driver\n");
96
97 return 0;
98}
99
100static int handle_show_command(struct nl_msg *msg, int argc,
101 char **argv, void *ctx)
102{
103 register_handler(show_callback, NULL);
104 return handle_common_command(msg, argc, argv, MTK_NL80211_VENDOR_ATTR_VENDOR_SHOW_CMD_STR);
105}
106
107TOPLEVEL(show, "param", MTK_NL80211_VENDOR_SUBCMD_VENDOR_SHOW, 0, CIB_NETDEV, handle_show_command,
108 "this command is used to be compatible with old iwpriv show command, e.g iwpriv ra0 show stainfo");
109
110int stat_callback(struct nl_msg *msg, void *cb)
111{
112 struct nlattr *tb[NL80211_ATTR_MAX + 1];
113 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_ATTR_STATISTICS_ATTR_MAX + 1];
114 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
115 char *show_str = NULL;
116 int err = 0;
117
118 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
119 genlmsg_attrlen(gnlh, 0), NULL);
120 if (err < 0)
121 return err;
122
123 if (tb[NL80211_ATTR_VENDOR_DATA]) {
124 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_ATTR_STATISTICS_ATTR_MAX,
125 tb[NL80211_ATTR_VENDOR_DATA], NULL);
126 if (err < 0)
127 return err;
128
129 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_STATISTICS_STR]) {
130 show_str = nla_data(vndr_tb[MTK_NL80211_VENDOR_ATTR_STATISTICS_STR]);
131 printf("%s\n", show_str);
132 }
133 } else
134 printf("no any statistic string from driver\n");
135
136 return 0;
137}
138
139static int handle_stat_command(struct nl_msg *msg, int argc,
140 char **argv, void *ctx)
141{
142 register_handler(stat_callback, NULL);
143 return handle_common_command(msg, 0, NULL, 0);
144}
145
146TOPLEVEL(stat, NULL, MTK_NL80211_VENDOR_SUBCMD_STATISTICS, 0, CIB_NETDEV, handle_stat_command,
147 "this command is used to be compatible with old iwpriv stat command, e.g iwpriv ra0 stat");
148
149
150int mac_callback(struct nl_msg *msg, void *cb)
151{
152 struct nlattr *tb[NL80211_ATTR_MAX + 1];
153 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_ATTR_MAC_ATTR_MAX + 1];
154 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
155 char *show_str = NULL;
156 int err = 0;
157
158 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
159 genlmsg_attrlen(gnlh, 0), NULL);
160 if (err < 0)
161 return err;
162
163 if (tb[NL80211_ATTR_VENDOR_DATA]) {
164 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_ATTR_MAC_ATTR_MAX,
165 tb[NL80211_ATTR_VENDOR_DATA], NULL);
166 if (err < 0)
167 return err;
168
169 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_MAC_RSP_STR]) {
170 show_str = nla_data(vndr_tb[MTK_NL80211_VENDOR_ATTR_MAC_RSP_STR]);
171 printf("%s\n", show_str);
172 }
173 } else
174 printf("no any statistic string from driver\n");
175
176 return 0;
177}
178
179
180static int handle_mac_command(struct nl_msg *msg, int argc,
181 char **argv, void *ctx)
182{
183 void *data;
184 char *ptr, *seg_str, *addr_str, *val_str, *range_str;
185 unsigned char is_write, is_range;
186 unsigned int mac_s = 0, mac_e = 0;
187 unsigned int macVal = 0;
188 struct mac_param param;
189
190 if (!argc)
191 return -EINVAL;
192
193 data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
194 if (!data)
195 return -ENOMEM;
196
197 ptr = argv[0];
198
199 while ((seg_str = strsep((char **)&ptr, ",")) != NULL) {
200 is_write = 0;
201 addr_str = seg_str;
202 val_str = NULL;
203 val_str = strchr(seg_str, '=');
204
205 if (val_str != NULL) {
206 *val_str++ = 0;
207 is_write = 1;
208 } else
209 is_write = 0;
210
211 if (addr_str) {
212 range_str = strchr(addr_str, '-');
213
214 if (range_str != NULL) {
215 *range_str++ = 0;
216 is_range = 1;
217 } else
218 is_range = 0;
219
220 if ((ascii2hex(addr_str, &mac_s) == 0)) {
221 printf("Invalid MAC CR Addr, str=%s\n", addr_str);
222 break;
223 }
224
225 if (is_range) {
226 if (ascii2hex(range_str, &mac_e) == 0) {
227 printf("Invalid Range End MAC CR Addr[0x%x], str=%s\n",
228 mac_e, range_str);
229 break;
230 }
231
232 if (mac_e < mac_s) {
233 printf("Invalid Range MAC Addr[%s - %s] => [0x%x - 0x%x]\n",
234 addr_str, range_str, mac_s, mac_e);
235 break;
236 }
237 } else
238 mac_e = mac_s;
239 }
240
241 if (val_str) {
242 if ((strlen(val_str) == 0) || ascii2hex(val_str, &macVal) == 0) {
243 printf("Invalid MAC value[0x%s]\n", val_str);
244 break;
245 }
246 }
247
248 memset(&param, 0, sizeof(param));
249 param.start = mac_s;
250 param.value = macVal;
251 param.end = mac_e;
252 if (is_write) {
253 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_MAC_WRITE_PARAM, sizeof(param), &param))
254 return -EMSGSIZE;
255 } else {
256 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_MAC_SHOW_PARAM, sizeof(param), &param))
257 return -EMSGSIZE;
258 }
259 }
260
261 nla_nest_end(msg, data);
262 register_handler(mac_callback, NULL);
263 return 0;
264}
265
266
267TOPLEVEL(mac, "addr=hex/addr-addr/addr=hex,addr=hex", MTK_NL80211_VENDOR_SUBCMD_MAC, 0,
268 CIB_NETDEV, handle_mac_command,
269 "this command is used to be compatible with old iwpriv mac, e.g iwpriv ra0 mac 2345");
270