]> git.ipfire.org Git - thirdparty/iw.git/blame - interface.c
help for 'set name'
[thirdparty/iw.git] / interface.c
CommitLineData
2ef1be68 1#include <net/if.h>
45c7212c 2#include <errno.h>
d5ac8ad3 3#include <string.h>
d17fe27e 4#include <stdbool.h>
2ef1be68 5
45c7212c
JB
6#include <netlink/genl/genl.h>
7#include <netlink/genl/family.h>
8#include <netlink/genl/ctrl.h>
9#include <netlink/msg.h>
10#include <netlink/attr.h>
45c7212c 11
f408e01b 12#include "nl80211.h"
45c7212c
JB
13#include "iw.h"
14
cd293761 15static char *mntr_flags[NL80211_MNTR_FLAG_MAX + 1] = {
dd65496b 16 "none",
cd293761
JB
17 "fcsfail",
18 "plcpfail",
19 "control",
20 "otherbss",
21 "cook",
22};
23
dd65496b
JB
24static int parse_mntr_flags(int *_argc, char ***_argv,
25 struct nl_msg *msg)
26{
27 struct nl_msg *flags;
28 int err = -ENOBUFS;
29 enum nl80211_mntr_flags flag;
30 int argc = *_argc;
31 char **argv = *_argv;
32
33 flags = nlmsg_alloc();
34 if (!flags)
35 return -ENOMEM;
36
37 while (argc) {
38 int ok = 0;
39 for (flag = __NL80211_MNTR_FLAG_INVALID;
e14cc99e 40 flag <= NL80211_MNTR_FLAG_MAX; flag++) {
dd65496b
JB
41 if (strcmp(*argv, mntr_flags[flag]) == 0) {
42 ok = 1;
4a3bf753
JB
43 /*
44 * This shouldn't be adding "flag" if that is
45 * zero, but due to a problem in the kernel's
46 * nl80211 code (using NLA_NESTED policy) it
47 * will reject an empty nested attribute but
48 * not one that contains an invalid attribute
49 */
dd65496b
JB
50 NLA_PUT_FLAG(flags, flag);
51 break;
52 }
53 }
54 if (!ok) {
55 err = -EINVAL;
56 goto out;
57 }
58 argc--;
59 argv++;
60 }
61
62 nla_put_nested(msg, NL80211_ATTR_MNTR_FLAGS, flags);
63 err = 0;
64 nla_put_failure:
65 out:
66 nlmsg_free(flags);
67
68 *_argc = argc;
69 *_argv = argv;
70
71 return err;
72}
73
d17fe27e
JB
74/* return 0 if ok, internal error otherwise */
75static int get_if_type(int *argc, char ***argv, enum nl80211_iftype *type,
76 bool need_type)
45c7212c
JB
77{
78 char *tpstr;
79
d17fe27e
JB
80 if (*argc < 1 + !!need_type)
81 return 1;
45c7212c 82
d17fe27e
JB
83 if (need_type && strcmp((*argv)[0], "type"))
84 return 1;
45c7212c 85
d17fe27e
JB
86 tpstr = (*argv)[!!need_type];
87 *argc -= 1 + !!need_type;
88 *argv += 1 + !!need_type;
45c7212c
JB
89
90 if (strcmp(tpstr, "adhoc") == 0 ||
91 strcmp(tpstr, "ibss") == 0) {
92 *type = NL80211_IFTYPE_ADHOC;
d17fe27e 93 return 0;
45c7212c
JB
94 } else if (strcmp(tpstr, "monitor") == 0) {
95 *type = NL80211_IFTYPE_MONITOR;
d17fe27e 96 return 0;
c1d44a6c
JB
97 } else if (strcmp(tpstr, "master") == 0) {
98 *type = NL80211_IFTYPE_UNSPECIFIED;
99 fprintf(stderr, "See http://wireless.kernel.org/RTFM-AP.\n");
100 return 2;
101 } else if (strcmp(tpstr, "ap") == 0) {
102 *type = NL80211_IFTYPE_UNSPECIFIED;
103 fprintf(stderr, "See http://wireless.kernel.org/RTFM-AP.\n");
104 return 2;
4d3a72da 105 } else if (strcmp(tpstr, "__ap") == 0) {
45c7212c 106 *type = NL80211_IFTYPE_AP;
d17fe27e 107 return 0;
4d3a72da 108 } else if (strcmp(tpstr, "__ap_vlan") == 0) {
45c7212c 109 *type = NL80211_IFTYPE_AP_VLAN;
d17fe27e 110 return 0;
45c7212c
JB
111 } else if (strcmp(tpstr, "wds") == 0) {
112 *type = NL80211_IFTYPE_WDS;
d17fe27e 113 return 0;
a65df165
JB
114 } else if (strcmp(tpstr, "managed") == 0 ||
115 strcmp(tpstr, "mgd") == 0 ||
116 strcmp(tpstr, "station") == 0) {
45c7212c 117 *type = NL80211_IFTYPE_STATION;
d17fe27e 118 return 0;
3d1e8704 119 } else if (strcmp(tpstr, "mp") == 0 ||
a65df165 120 strcmp(tpstr, "mesh") == 0) {
3d1e8704 121 *type = NL80211_IFTYPE_MESH_POINT;
d17fe27e 122 return 0;
45c7212c
JB
123 }
124
45c7212c 125 fprintf(stderr, "invalid interface type %s\n", tpstr);
d17fe27e 126 return 2;
45c7212c
JB
127}
128
7c37a24d
JB
129static int handle_interface_add(struct nl80211_state *state,
130 struct nl_cb *cb,
bd396f2a
JB
131 struct nl_msg *msg,
132 int argc, char **argv)
45c7212c 133{
2dfd6bfa 134 char *name;
3d1e8704 135 char *mesh_id = NULL;
45c7212c 136 enum nl80211_iftype type;
70391ccf 137 int tpset;
45c7212c 138
bd396f2a 139 if (argc < 1)
5e75fd04 140 return 1;
45c7212c 141
2dfd6bfa 142 name = argv[0];
45c7212c
JB
143 argc--;
144 argv++;
145
d17fe27e
JB
146 tpset = get_if_type(&argc, &argv, &type, true);
147 if (tpset)
c1d44a6c 148 return tpset;
45c7212c 149
3d1e8704 150 if (argc) {
dd65496b
JB
151 if (strcmp(argv[0], "mesh_id") == 0) {
152 argc--;
153 argv++;
154
155 if (!argc)
156 return 1;
157 mesh_id = argv[0];
158 argc--;
159 argv++;
160 } else if (strcmp(argv[0], "flags") == 0) {
161 argc--;
162 argv++;
163 if (parse_mntr_flags(&argc, &argv, msg)) {
164 fprintf(stderr, "flags error\n");
165 return 2;
166 }
167 } else {
5e75fd04 168 return 1;
dd65496b 169 }
3d1e8704
LCC
170 }
171
5e75fd04
JB
172 if (argc)
173 return 1;
45c7212c 174
45c7212c 175 NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, name);
6d28ce25 176 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, type);
3d1e8704
LCC
177 if (mesh_id)
178 NLA_PUT(msg, NL80211_ATTR_MESH_ID, strlen(mesh_id), mesh_id);
45c7212c 179
70391ccf 180 return 0;
5e75fd04 181 nla_put_failure:
70391ccf 182 return -ENOBUFS;
45c7212c 183}
dd65496b 184COMMAND(interface, add, "<name> type <type> [mesh_id <meshid>] [flags ...]",
01ae06f9 185 NL80211_CMD_NEW_INTERFACE, 0, CIB_PHY, handle_interface_add, NULL);
dd65496b 186COMMAND(interface, add, "<name> type <type> [mesh_id <meshid>] [flags ...]",
01ae06f9 187 NL80211_CMD_NEW_INTERFACE, 0, CIB_NETDEV, handle_interface_add, NULL);
45c7212c 188
7c37a24d
JB
189static int handle_interface_del(struct nl80211_state *state,
190 struct nl_cb *cb,
bd396f2a
JB
191 struct nl_msg *msg,
192 int argc, char **argv)
3fcfe40e 193{
70391ccf 194 return 0;
3fcfe40e 195}
01ae06f9 196TOPLEVEL(del, NULL, NL80211_CMD_DEL_INTERFACE, 0, CIB_NETDEV, handle_interface_del, NULL);
ce5af55c 197HIDDEN(interface, del, NULL, NL80211_CMD_DEL_INTERFACE, 0, CIB_NETDEV, handle_interface_del);
3fcfe40e 198
541ef425
JB
199static int print_iface_handler(struct nl_msg *msg, void *arg)
200{
201 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
202 struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
674567b8
JB
203 unsigned int *wiphy = arg;
204 const char *indent = "";
541ef425
JB
205
206 nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
207 genlmsg_attrlen(gnlh, 0), NULL);
208
674567b8
JB
209 if (wiphy && tb_msg[NL80211_ATTR_WIPHY]) {
210 unsigned int thiswiphy = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY]);
211 indent = "\t";
212 if (*wiphy != thiswiphy)
213 printf("phy#%d\n", thiswiphy);
214 *wiphy = thiswiphy;
215 }
216
541ef425 217 if (tb_msg[NL80211_ATTR_IFNAME])
674567b8 218 printf("%sInterface %s\n", indent, nla_get_string(tb_msg[NL80211_ATTR_IFNAME]));
541ef425 219 if (tb_msg[NL80211_ATTR_IFINDEX])
674567b8 220 printf("%s\tifindex %d\n", indent, nla_get_u32(tb_msg[NL80211_ATTR_IFINDEX]));
541ef425 221 if (tb_msg[NL80211_ATTR_IFTYPE])
674567b8 222 printf("%s\ttype %s\n", indent, iftype_name(nla_get_u32(tb_msg[NL80211_ATTR_IFTYPE])));
541ef425
JB
223
224 return NL_SKIP;
225}
226
7c37a24d
JB
227static int handle_interface_info(struct nl80211_state *state,
228 struct nl_cb *cb,
bd396f2a
JB
229 struct nl_msg *msg,
230 int argc, char **argv)
541ef425 231{
541ef425 232 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_iface_handler, NULL);
70391ccf 233 return 0;
541ef425 234}
01ae06f9 235TOPLEVEL(info, NULL, NL80211_CMD_GET_INTERFACE, 0, CIB_NETDEV, handle_interface_info, NULL);
cd293761 236
7c37a24d
JB
237static int handle_interface_set(struct nl80211_state *state,
238 struct nl_cb *cb,
cd293761
JB
239 struct nl_msg *msg,
240 int argc, char **argv)
241{
cd293761
JB
242 if (!argc)
243 return 1;
244
cd293761
JB
245 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_MONITOR);
246
dd65496b
JB
247 switch (parse_mntr_flags(&argc, &argv, msg)) {
248 case 0:
249 return 0;
250 case -ENOMEM:
251 fprintf(stderr, "failed to allocate flags\n");
252 return 2;
253 case -EINVAL:
254 fprintf(stderr, "unknown flag %s\n", *argv);
255 return 2;
256 default:
257 return 2;
cd293761 258 }
cd293761 259 nla_put_failure:
dd65496b 260 return -ENOBUFS;
cd293761
JB
261}
262COMMAND(set, monitor, "<flag> [...]",
01ae06f9 263 NL80211_CMD_SET_INTERFACE, 0, CIB_NETDEV, handle_interface_set, NULL);
82d028d0 264
7c37a24d
JB
265static int handle_interface_meshid(struct nl80211_state *state,
266 struct nl_cb *cb,
82d028d0
JB
267 struct nl_msg *msg,
268 int argc, char **argv)
269{
270 char *mesh_id = NULL;
271
272 if (argc != 1)
273 return 1;
274
275 mesh_id = argv[0];
276
277 NLA_PUT(msg, NL80211_ATTR_MESH_ID, strlen(mesh_id), mesh_id);
278
279 return 0;
280 nla_put_failure:
281 return -ENOBUFS;
282}
283COMMAND(set, meshid, "<meshid>",
01ae06f9 284 NL80211_CMD_SET_INTERFACE, 0, CIB_NETDEV, handle_interface_meshid, NULL);
674567b8
JB
285
286static unsigned int dev_dump_wiphy;
287
288static int handle_dev_dump(struct nl80211_state *state,
289 struct nl_cb *cb,
290 struct nl_msg *msg,
291 int argc, char **argv)
292{
293 dev_dump_wiphy = -1;
294 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_iface_handler, &dev_dump_wiphy);
295 return 0;
296}
01ae06f9 297TOPLEVEL(dev, NULL, NL80211_CMD_GET_INTERFACE, NLM_F_DUMP, CIB_NONE, handle_dev_dump, NULL);
d17fe27e
JB
298
299static int handle_interface_type(struct nl80211_state *state,
300 struct nl_cb *cb,
301 struct nl_msg *msg,
302 int argc, char **argv)
303{
304 enum nl80211_iftype type;
305 int tpset;
306
307 tpset = get_if_type(&argc, &argv, &type, false);
308 if (tpset)
309 return tpset;
310
311 if (argc)
312 return 1;
313
314 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, type);
315
316 return 0;
317 nla_put_failure:
318 return -ENOBUFS;
319}
320COMMAND(set, type, "<type>",
01ae06f9 321 NL80211_CMD_SET_INTERFACE, 0, CIB_NETDEV, handle_interface_type, NULL);