]> git.ipfire.org Git - thirdparty/iw.git/blame - mesh.c
Revert "iw: Add antenna configuration commands"
[thirdparty/iw.git] / mesh.c
CommitLineData
46c1ad1f 1#include <net/if.h>
2#include <errno.h>
3#include <string.h>
4
5#include <netlink/genl/genl.h>
6#include <netlink/genl/family.h>
7#include <netlink/genl/ctrl.h>
8#include <netlink/msg.h>
9#include <netlink/attr.h>
10
11#include "nl80211.h"
12#include "iw.h"
13
14typedef struct _any_t {
15 union {
16 uint32_t as_32;
17 uint16_t as_16;
18 uint8_t as_8;
19 } u;
20} _any;
21
22/* describes a mesh parameter */
23struct mesh_param_descr {
24 const char *name;
25 enum nl80211_meshconf_params mesh_param_num;
26 int (*nla_put_fn)(struct nl_msg*, int, _any*);
27 uint32_t (*parse_fn)(const char*, _any*);
28 void (*nla_print_fn)(struct nlattr *);
29};
30
31/* utility functions for manipulating and printing u8/u16/u32 values and
32 * timesouts. */
33static int _my_nla_put_u8(struct nl_msg *n, int mesh_param_num, _any *value)
34{
35 return nla_put(n, mesh_param_num, sizeof(uint8_t), &value->u.as_8);
36}
37
38static int _my_nla_put_u16(struct nl_msg *n, int mesh_param_num, _any *value)
39{
40 return nla_put(n, mesh_param_num, sizeof(uint16_t), &value->u.as_16);
41}
42
43static int _my_nla_put_u32(struct nl_msg *n, int mesh_param_num, _any *value)
44{
45 return nla_put(n, mesh_param_num, sizeof(uint32_t), &value->u.as_32);
46}
47
48static uint32_t _parse_u8(const char *str, _any *ret)
49{
50 char *endptr = NULL;
51 unsigned long int v = strtoul(str, &endptr, 10);
52 if (*endptr != '\0')
53 return 0xff;
54 if (v > 0xff)
55 return 0xff;
56 ret->u.as_8 = (uint8_t)v;
57 return 0;
58}
59
60static uint32_t _parse_u8_as_bool(const char *str, _any *ret)
61{
62 char *endptr = NULL;
63 unsigned long int v = strtoul(str, &endptr, 10);
64 if (*endptr != '\0')
65 return 0x1;
66 if (v > 0x1)
67 return 0x1;
68 ret->u.as_8 = (uint8_t)v;
69 return 0;
70}
71
72static uint32_t _parse_u16(const char *str, _any *ret)
73{
74 char *endptr = NULL;
75 long int v = strtol(str, &endptr, 10);
76 if (*endptr != '\0')
77 return 0xffff;
78 if ((v < 0) || (v > 0xffff))
79 return 0xffff;
80 ret->u.as_16 = (uint16_t)v;
81 return 0;
82}
83
84static uint32_t _parse_u32(const char *str, _any *ret)
85{
86 char *endptr = NULL;
87 long long int v = strtoll(str, &endptr, 10);
88 if (*endptr != '\0')
89 return 0xffffffff;
90 if ((v < 0) || (v > 0xffffffff))
91 return 0xffffffff;
92 ret->u.as_32 = (uint32_t)v;
93 return 0;
94}
95
656aa246 96static void _print_u8(struct nlattr *a)
46c1ad1f 97{
98 printf("%d", nla_get_u8(a));
99}
100
656aa246 101static void _print_u16(struct nlattr *a)
46c1ad1f 102{
103 printf("%d", nla_get_u16(a));
104}
105
656aa246 106static void _print_u16_timeout(struct nlattr *a)
46c1ad1f 107{
108 printf("%d milliseconds", nla_get_u16(a));
109}
110
656aa246 111static void _print_u16_in_TUs(struct nlattr *a)
46c1ad1f 112{
113 printf("%d TUs", nla_get_u16(a));
114}
115
656aa246 116static void _print_u32_timeout(struct nlattr *a)
46c1ad1f 117{
118 printf("%u milliseconds", nla_get_u32(a));
119}
120
656aa246 121static void _print_u32_in_TUs(struct nlattr *a)
46c1ad1f 122{
123 printf("%d TUs", nla_get_u32(a));
124}
125
126/* The current mesh parameters */
127const static struct mesh_param_descr _mesh_param_descrs[] =
128{
129 {"mesh_retry_timeout",
130 NL80211_MESHCONF_RETRY_TIMEOUT,
131 _my_nla_put_u16, _parse_u16, _print_u16_timeout},
132 {"mesh_confirm_timeout",
133 NL80211_MESHCONF_CONFIRM_TIMEOUT,
134 _my_nla_put_u16, _parse_u16, _print_u16_timeout},
135 {"mesh_holding_timeout",
136 NL80211_MESHCONF_HOLDING_TIMEOUT,
137 _my_nla_put_u16, _parse_u16, _print_u16_timeout},
138 {"mesh_max_peer_links",
139 NL80211_MESHCONF_MAX_PEER_LINKS,
140 _my_nla_put_u16, _parse_u16, _print_u16},
141 {"mesh_max_retries",
142 NL80211_MESHCONF_MAX_RETRIES,
143 _my_nla_put_u8, _parse_u8, _print_u8},
144 {"mesh_ttl",
145 NL80211_MESHCONF_TTL,
146 _my_nla_put_u8, _parse_u8, _print_u8},
147 {"mesh_auto_open_plinks",
148 NL80211_MESHCONF_AUTO_OPEN_PLINKS,
149 _my_nla_put_u8, _parse_u8_as_bool, _print_u8},
150 {"mesh_hwmp_max_preq_retries",
151 NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
152 _my_nla_put_u8, _parse_u8, _print_u8},
153 {"mesh_path_refresh_time",
154 NL80211_MESHCONF_PATH_REFRESH_TIME,
155 _my_nla_put_u32, _parse_u32, _print_u32_timeout},
156 {"mesh_min_discovery_timeout",
157 NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
158 _my_nla_put_u16, _parse_u16, _print_u16_timeout},
159 {"mesh_hwmp_active_path_timeout",
160 NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
161 _my_nla_put_u32, _parse_u32, _print_u32_in_TUs},
162 {"mesh_hwmp_preq_min_interval",
163 NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
164 _my_nla_put_u16, _parse_u16, _print_u16_in_TUs},
165 {"mesh_hwmp_net_diameter_traversal_time",
166 NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
167 _my_nla_put_u16, _parse_u16, _print_u16_in_TUs},
cc37218f
RP
168 {"mesh_hwmp_rootmode", NL80211_MESHCONF_HWMP_ROOTMODE,
169 _my_nla_put_u8, _parse_u8, _print_u8},
46c1ad1f 170};
171
172static void print_all_mesh_param_descr(void)
173{
174 int i;
46c1ad1f 175
f089471a
JB
176 printf("Possible mesh parameters are:\n");
177
178 for (i = 0; i < ARRAY_SIZE(_mesh_param_descrs); i++)
179 printf(" - %s\n", _mesh_param_descrs[i].name);
46c1ad1f 180}
181
182static const struct mesh_param_descr* find_mesh_param(int argc, char **argv,
183 const char *action_name)
184{
185 int i;
186 const struct mesh_param_descr *mdescr;
187
188 if (argc < 1) {
189 printf("You must specify which mesh parameter to %s.\n",
190 action_name);
f089471a 191 print_all_mesh_param_descr();
46c1ad1f 192 return NULL;
193 }
194
195 /* Find out what mesh parameter we want to change. */
196 mdescr = NULL;
4d0d2ea7 197 for (i = 0; i < ARRAY_SIZE(_mesh_param_descrs); i++) {
46c1ad1f 198 if (!strcmp(_mesh_param_descrs[i].name, argv[0]))
199 return _mesh_param_descrs + i;
4d0d2ea7 200 }
46c1ad1f 201
202 if (!mdescr) {
46c1ad1f 203 print_all_mesh_param_descr();
46c1ad1f 204 return NULL;
205 }
206 return mdescr;
207}
208
209/* Setter */
7c37a24d
JB
210static int set_interface_meshparam(struct nl80211_state *state,
211 struct nl_cb *cb,
212 struct nl_msg *msg,
213 int argc, char **argv)
46c1ad1f 214{
215 int err;
216 uint32_t ret;
217 const struct mesh_param_descr *mdescr;
656aa246 218 struct nlattr *container;
46c1ad1f 219 _any any;
220
221 mdescr = find_mesh_param(argc, argv, "change");
222 if (!mdescr)
223 return 2;
224 if (argc != 2) {
225 printf("Must specify a value for %s.\n", mdescr->name);
226 return 2;
227 }
228
229 /* Parse the new value */
230 memset(&any, 0, sizeof(_any));
231 ret = mdescr->parse_fn(argv[1], &any);
232 if (ret != 0) {
233 printf("%s must be set to a number "
234 "between 0 and %u\n", mdescr->name, ret);
235 return 2;
236 }
237
238 /* Construct a netlink message */
656aa246 239 container = nla_nest_start(msg, NL80211_ATTR_MESH_PARAMS);
46c1ad1f 240 if (!container)
241 return -ENOBUFS;
242 err = mdescr->nla_put_fn(msg, mdescr->mesh_param_num, &any);
243 nla_nest_end(msg, container);
244
245 return err;
246}
247
248COMMAND(set, mesh_param, "<param> <value>",
70cf4544
JB
249 NL80211_CMD_SET_MESH_PARAMS, 0, CIB_NETDEV, set_interface_meshparam,
250 "Set mesh parameter (run command without any to see available ones).");
46c1ad1f 251
252/* Getter */
253static int print_mesh_param_handler(struct nl_msg *msg, void *arg)
254{
255 const struct mesh_param_descr *mdescr = arg;
256 struct nlattr *attrs[NL80211_ATTR_MAX + 1];
257 struct nlattr *parent_attr;
258 struct nlattr *mesh_params[NL80211_MESHCONF_ATTR_MAX + 1];
259 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
260
261 /* locate NL80211_ATTR_MESH_PARAMS */
262 nla_parse(attrs, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
263 genlmsg_attrlen(gnlh, 0), NULL);
264 parent_attr = attrs[NL80211_ATTR_MESH_PARAMS];
265 if (!parent_attr)
266 return -EINVAL;
267
268 /* unpack the mesh parameters */
269 if (nla_parse_nested(mesh_params, NL80211_MESHCONF_ATTR_MAX,
270 parent_attr, NULL))
271 return -EINVAL;
272
273 /* print out the mesh parameter */
274 mdescr->nla_print_fn(mesh_params[mdescr->mesh_param_num]);
275 printf("\n");
276 return NL_SKIP;
277}
278
7c37a24d
JB
279static int get_interface_meshparam(struct nl80211_state *state,
280 struct nl_cb *cb,
281 struct nl_msg *msg,
282 int argc, char **argv)
46c1ad1f 283{
284 const struct mesh_param_descr *mdescr;
285
286 mdescr = find_mesh_param(argc, argv, "get");
287 if (!mdescr)
288 return 2;
289
290 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
291 print_mesh_param_handler, (void *)mdescr);
292 return 0;
293}
294
295COMMAND(get, mesh_param, "<param>",
70cf4544
JB
296 NL80211_CMD_GET_MESH_PARAMS, 0, CIB_NETDEV, get_interface_meshparam,
297 "Retrieve mesh parameter (run command without any to see available ones).");