1*92022041SSam Saccone /*
2*92022041SSam Saccone * nl80211 userspace tool
3*92022041SSam Saccone *
4*92022041SSam Saccone * Copyright 2007, 2008 Johannes Berg <[email protected]>
5*92022041SSam Saccone */
6*92022041SSam Saccone
7*92022041SSam Saccone #include <errno.h>
8*92022041SSam Saccone #include <stdio.h>
9*92022041SSam Saccone #include <string.h>
10*92022041SSam Saccone #include <net/if.h>
11*92022041SSam Saccone #include <sys/types.h>
12*92022041SSam Saccone #include <sys/stat.h>
13*92022041SSam Saccone #include <fcntl.h>
14*92022041SSam Saccone #include <unistd.h>
15*92022041SSam Saccone #include <stdbool.h>
16*92022041SSam Saccone #include <linux/netlink.h>
17*92022041SSam Saccone
18*92022041SSam Saccone #include <netlink/genl/genl.h>
19*92022041SSam Saccone #include <netlink/genl/family.h>
20*92022041SSam Saccone #include <netlink/genl/ctrl.h>
21*92022041SSam Saccone #include <netlink/msg.h>
22*92022041SSam Saccone #include <netlink/attr.h>
23*92022041SSam Saccone
24*92022041SSam Saccone #include "nl80211.h"
25*92022041SSam Saccone #include "iw.h"
26*92022041SSam Saccone
27*92022041SSam Saccone /* libnl 1.x compatibility code */
28*92022041SSam Saccone #if !defined(CONFIG_LIBNL20) && !defined(CONFIG_LIBNL30)
nl_socket_alloc(void)29*92022041SSam Saccone static inline struct nl_handle *nl_socket_alloc(void)
30*92022041SSam Saccone {
31*92022041SSam Saccone return nl_handle_alloc();
32*92022041SSam Saccone }
33*92022041SSam Saccone
nl_socket_free(struct nl_sock * h)34*92022041SSam Saccone static inline void nl_socket_free(struct nl_sock *h)
35*92022041SSam Saccone {
36*92022041SSam Saccone nl_handle_destroy(h);
37*92022041SSam Saccone }
38*92022041SSam Saccone
nl_socket_set_buffer_size(struct nl_sock * sk,int rxbuf,int txbuf)39*92022041SSam Saccone static inline int nl_socket_set_buffer_size(struct nl_sock *sk,
40*92022041SSam Saccone int rxbuf, int txbuf)
41*92022041SSam Saccone {
42*92022041SSam Saccone return nl_set_buffer_size(sk, rxbuf, txbuf);
43*92022041SSam Saccone }
44*92022041SSam Saccone #endif /* CONFIG_LIBNL20 && CONFIG_LIBNL30 */
45*92022041SSam Saccone
46*92022041SSam Saccone int iw_debug = 0;
47*92022041SSam Saccone
nl80211_init(struct nl80211_state * state)48*92022041SSam Saccone static int nl80211_init(struct nl80211_state *state)
49*92022041SSam Saccone {
50*92022041SSam Saccone int err;
51*92022041SSam Saccone
52*92022041SSam Saccone state->nl_sock = nl_socket_alloc();
53*92022041SSam Saccone if (!state->nl_sock) {
54*92022041SSam Saccone fprintf(stderr, "Failed to allocate netlink socket.\n");
55*92022041SSam Saccone return -ENOMEM;
56*92022041SSam Saccone }
57*92022041SSam Saccone
58*92022041SSam Saccone if (genl_connect(state->nl_sock)) {
59*92022041SSam Saccone fprintf(stderr, "Failed to connect to generic netlink.\n");
60*92022041SSam Saccone err = -ENOLINK;
61*92022041SSam Saccone goto out_handle_destroy;
62*92022041SSam Saccone }
63*92022041SSam Saccone
64*92022041SSam Saccone nl_socket_set_buffer_size(state->nl_sock, 8192, 8192);
65*92022041SSam Saccone
66*92022041SSam Saccone /* try to set NETLINK_EXT_ACK to 1, ignoring errors */
67*92022041SSam Saccone err = 1;
68*92022041SSam Saccone setsockopt(nl_socket_get_fd(state->nl_sock), SOL_NETLINK,
69*92022041SSam Saccone NETLINK_EXT_ACK, &err, sizeof(err));
70*92022041SSam Saccone
71*92022041SSam Saccone state->nl80211_id = genl_ctrl_resolve(state->nl_sock, "nl80211");
72*92022041SSam Saccone if (state->nl80211_id < 0) {
73*92022041SSam Saccone fprintf(stderr, "nl80211 not found.\n");
74*92022041SSam Saccone err = -ENOENT;
75*92022041SSam Saccone goto out_handle_destroy;
76*92022041SSam Saccone }
77*92022041SSam Saccone
78*92022041SSam Saccone return 0;
79*92022041SSam Saccone
80*92022041SSam Saccone out_handle_destroy:
81*92022041SSam Saccone nl_socket_free(state->nl_sock);
82*92022041SSam Saccone return err;
83*92022041SSam Saccone }
84*92022041SSam Saccone
nl80211_cleanup(struct nl80211_state * state)85*92022041SSam Saccone static void nl80211_cleanup(struct nl80211_state *state)
86*92022041SSam Saccone {
87*92022041SSam Saccone nl_socket_free(state->nl_sock);
88*92022041SSam Saccone }
89*92022041SSam Saccone
90*92022041SSam Saccone static int cmd_size;
91*92022041SSam Saccone
92*92022041SSam Saccone extern struct cmd *__start___cmd[];
93*92022041SSam Saccone extern struct cmd *__stop___cmd;
94*92022041SSam Saccone
95*92022041SSam Saccone #define for_each_cmd(_cmd, i) \
96*92022041SSam Saccone for (i = 0; i < &__stop___cmd - __start___cmd; i++) \
97*92022041SSam Saccone if ((_cmd = __start___cmd[i]))
98*92022041SSam Saccone
99*92022041SSam Saccone
__usage_cmd(const struct cmd * cmd,char * indent,bool full)100*92022041SSam Saccone static void __usage_cmd(const struct cmd *cmd, char *indent, bool full)
101*92022041SSam Saccone {
102*92022041SSam Saccone const char *start, *lend, *end;
103*92022041SSam Saccone
104*92022041SSam Saccone printf("%s", indent);
105*92022041SSam Saccone
106*92022041SSam Saccone switch (cmd->idby) {
107*92022041SSam Saccone case CIB_NONE:
108*92022041SSam Saccone break;
109*92022041SSam Saccone case CIB_PHY:
110*92022041SSam Saccone printf("phy <phyname> ");
111*92022041SSam Saccone break;
112*92022041SSam Saccone case CIB_NETDEV:
113*92022041SSam Saccone printf("dev <devname> ");
114*92022041SSam Saccone break;
115*92022041SSam Saccone case CIB_WDEV:
116*92022041SSam Saccone printf("wdev <idx> ");
117*92022041SSam Saccone break;
118*92022041SSam Saccone }
119*92022041SSam Saccone if (cmd->parent && cmd->parent->name)
120*92022041SSam Saccone printf("%s ", cmd->parent->name);
121*92022041SSam Saccone printf("%s", cmd->name);
122*92022041SSam Saccone
123*92022041SSam Saccone if (cmd->args) {
124*92022041SSam Saccone /* print line by line */
125*92022041SSam Saccone start = cmd->args;
126*92022041SSam Saccone end = strchr(start, '\0');
127*92022041SSam Saccone printf(" ");
128*92022041SSam Saccone do {
129*92022041SSam Saccone lend = strchr(start, '\n');
130*92022041SSam Saccone if (!lend)
131*92022041SSam Saccone lend = end;
132*92022041SSam Saccone if (start != cmd->args) {
133*92022041SSam Saccone printf("\t");
134*92022041SSam Saccone switch (cmd->idby) {
135*92022041SSam Saccone case CIB_NONE:
136*92022041SSam Saccone break;
137*92022041SSam Saccone case CIB_PHY:
138*92022041SSam Saccone printf("phy <phyname> ");
139*92022041SSam Saccone break;
140*92022041SSam Saccone case CIB_NETDEV:
141*92022041SSam Saccone printf("dev <devname> ");
142*92022041SSam Saccone break;
143*92022041SSam Saccone case CIB_WDEV:
144*92022041SSam Saccone printf("wdev <idx> ");
145*92022041SSam Saccone break;
146*92022041SSam Saccone }
147*92022041SSam Saccone if (cmd->parent && cmd->parent->name)
148*92022041SSam Saccone printf("%s ", cmd->parent->name);
149*92022041SSam Saccone printf("%s ", cmd->name);
150*92022041SSam Saccone }
151*92022041SSam Saccone printf("%.*s\n", (int)(lend - start), start);
152*92022041SSam Saccone start = lend + 1;
153*92022041SSam Saccone } while (end != lend);
154*92022041SSam Saccone } else
155*92022041SSam Saccone printf("\n");
156*92022041SSam Saccone
157*92022041SSam Saccone if (!full || !cmd->help)
158*92022041SSam Saccone return;
159*92022041SSam Saccone
160*92022041SSam Saccone /* hack */
161*92022041SSam Saccone if (strlen(indent))
162*92022041SSam Saccone indent = "\t\t";
163*92022041SSam Saccone else
164*92022041SSam Saccone printf("\n");
165*92022041SSam Saccone
166*92022041SSam Saccone /* print line by line */
167*92022041SSam Saccone start = cmd->help;
168*92022041SSam Saccone end = strchr(start, '\0');
169*92022041SSam Saccone do {
170*92022041SSam Saccone lend = strchr(start, '\n');
171*92022041SSam Saccone if (!lend)
172*92022041SSam Saccone lend = end;
173*92022041SSam Saccone printf("%s", indent);
174*92022041SSam Saccone printf("%.*s\n", (int)(lend - start), start);
175*92022041SSam Saccone start = lend + 1;
176*92022041SSam Saccone } while (end != lend);
177*92022041SSam Saccone
178*92022041SSam Saccone printf("\n");
179*92022041SSam Saccone }
180*92022041SSam Saccone
usage_options(void)181*92022041SSam Saccone static void usage_options(void)
182*92022041SSam Saccone {
183*92022041SSam Saccone printf("Options:\n");
184*92022041SSam Saccone printf("\t--debug\t\tenable netlink debugging\n");
185*92022041SSam Saccone }
186*92022041SSam Saccone
187*92022041SSam Saccone static const char *argv0;
188*92022041SSam Saccone
usage(int argc,char ** argv)189*92022041SSam Saccone static void usage(int argc, char **argv)
190*92022041SSam Saccone {
191*92022041SSam Saccone const struct cmd *section, *cmd;
192*92022041SSam Saccone bool full = argc >= 0;
193*92022041SSam Saccone const char *sect_filt = NULL;
194*92022041SSam Saccone const char *cmd_filt = NULL;
195*92022041SSam Saccone unsigned int i, j;
196*92022041SSam Saccone
197*92022041SSam Saccone if (argc > 0)
198*92022041SSam Saccone sect_filt = argv[0];
199*92022041SSam Saccone
200*92022041SSam Saccone if (argc > 1)
201*92022041SSam Saccone cmd_filt = argv[1];
202*92022041SSam Saccone
203*92022041SSam Saccone printf("Usage:\t%s [options] command\n", argv0);
204*92022041SSam Saccone usage_options();
205*92022041SSam Saccone printf("\t--version\tshow version (%s)\n", iw_version);
206*92022041SSam Saccone printf("Commands:\n");
207*92022041SSam Saccone for_each_cmd(section, i) {
208*92022041SSam Saccone if (section->parent)
209*92022041SSam Saccone continue;
210*92022041SSam Saccone
211*92022041SSam Saccone if (sect_filt && strcmp(section->name, sect_filt))
212*92022041SSam Saccone continue;
213*92022041SSam Saccone
214*92022041SSam Saccone if (section->handler && !section->hidden)
215*92022041SSam Saccone __usage_cmd(section, "\t", full);
216*92022041SSam Saccone
217*92022041SSam Saccone for_each_cmd(cmd, j) {
218*92022041SSam Saccone if (section != cmd->parent)
219*92022041SSam Saccone continue;
220*92022041SSam Saccone if (!cmd->handler || cmd->hidden)
221*92022041SSam Saccone continue;
222*92022041SSam Saccone if (cmd_filt && strcmp(cmd->name, cmd_filt))
223*92022041SSam Saccone continue;
224*92022041SSam Saccone __usage_cmd(cmd, "\t", full);
225*92022041SSam Saccone }
226*92022041SSam Saccone }
227*92022041SSam Saccone printf("\nCommands that use the netdev ('dev') can also be given the\n"
228*92022041SSam Saccone "'wdev' instead to identify the device.\n");
229*92022041SSam Saccone printf("\nYou can omit the 'phy' or 'dev' if "
230*92022041SSam Saccone "the identification is unique,\n"
231*92022041SSam Saccone "e.g. \"iw wlan0 info\" or \"iw phy0 info\". "
232*92022041SSam Saccone "(Don't when scripting.)\n\n"
233*92022041SSam Saccone "Do NOT screenscrape this tool, we don't "
234*92022041SSam Saccone "consider its output stable.\n\n");
235*92022041SSam Saccone }
236*92022041SSam Saccone
print_help(struct nl80211_state * state,struct nl_msg * msg,int argc,char ** argv,enum id_input id)237*92022041SSam Saccone static int print_help(struct nl80211_state *state,
238*92022041SSam Saccone struct nl_msg *msg,
239*92022041SSam Saccone int argc, char **argv,
240*92022041SSam Saccone enum id_input id)
241*92022041SSam Saccone {
242*92022041SSam Saccone exit(3);
243*92022041SSam Saccone }
244*92022041SSam Saccone TOPLEVEL(help, "[command]", 0, 0, CIB_NONE, print_help,
245*92022041SSam Saccone "Print usage for all or a specific command, e.g.\n"
246*92022041SSam Saccone "\"help wowlan\" or \"help wowlan enable\".");
247*92022041SSam Saccone
usage_cmd(const struct cmd * cmd)248*92022041SSam Saccone static void usage_cmd(const struct cmd *cmd)
249*92022041SSam Saccone {
250*92022041SSam Saccone printf("Usage:\t%s [options] ", argv0);
251*92022041SSam Saccone __usage_cmd(cmd, "", true);
252*92022041SSam Saccone usage_options();
253*92022041SSam Saccone }
254*92022041SSam Saccone
version(void)255*92022041SSam Saccone static void version(void)
256*92022041SSam Saccone {
257*92022041SSam Saccone printf("iw version %s\n", iw_version);
258*92022041SSam Saccone }
259*92022041SSam Saccone
phy_lookup(char * name)260*92022041SSam Saccone static int phy_lookup(char *name)
261*92022041SSam Saccone {
262*92022041SSam Saccone char buf[200];
263*92022041SSam Saccone int fd, pos;
264*92022041SSam Saccone
265*92022041SSam Saccone snprintf(buf, sizeof(buf), "/sys/class/ieee80211/%s/index", name);
266*92022041SSam Saccone
267*92022041SSam Saccone fd = open(buf, O_RDONLY);
268*92022041SSam Saccone if (fd < 0)
269*92022041SSam Saccone return -1;
270*92022041SSam Saccone pos = read(fd, buf, sizeof(buf) - 1);
271*92022041SSam Saccone if (pos < 0) {
272*92022041SSam Saccone close(fd);
273*92022041SSam Saccone return -1;
274*92022041SSam Saccone }
275*92022041SSam Saccone buf[pos] = '\0';
276*92022041SSam Saccone close(fd);
277*92022041SSam Saccone return atoi(buf);
278*92022041SSam Saccone }
279*92022041SSam Saccone
error_handler(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)280*92022041SSam Saccone static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
281*92022041SSam Saccone void *arg)
282*92022041SSam Saccone {
283*92022041SSam Saccone struct nlmsghdr *nlh = (struct nlmsghdr *)err - 1;
284*92022041SSam Saccone int len = nlh->nlmsg_len;
285*92022041SSam Saccone struct nlattr *attrs;
286*92022041SSam Saccone struct nlattr *tb[NLMSGERR_ATTR_MAX + 1];
287*92022041SSam Saccone int *ret = arg;
288*92022041SSam Saccone int ack_len = sizeof(*nlh) + sizeof(int) + sizeof(*nlh);
289*92022041SSam Saccone
290*92022041SSam Saccone if (err->error > 0) {
291*92022041SSam Saccone /*
292*92022041SSam Saccone * This is illegal, per netlink(7), but not impossible (think
293*92022041SSam Saccone * "vendor commands"). Callers really expect negative error
294*92022041SSam Saccone * codes, so make that happen.
295*92022041SSam Saccone */
296*92022041SSam Saccone fprintf(stderr,
297*92022041SSam Saccone "ERROR: received positive netlink error code %d\n",
298*92022041SSam Saccone err->error);
299*92022041SSam Saccone *ret = -EPROTO;
300*92022041SSam Saccone } else {
301*92022041SSam Saccone *ret = err->error;
302*92022041SSam Saccone }
303*92022041SSam Saccone
304*92022041SSam Saccone if (!(nlh->nlmsg_flags & NLM_F_ACK_TLVS))
305*92022041SSam Saccone return NL_STOP;
306*92022041SSam Saccone
307*92022041SSam Saccone if (!(nlh->nlmsg_flags & NLM_F_CAPPED))
308*92022041SSam Saccone ack_len += err->msg.nlmsg_len - sizeof(*nlh);
309*92022041SSam Saccone
310*92022041SSam Saccone if (len <= ack_len)
311*92022041SSam Saccone return NL_STOP;
312*92022041SSam Saccone
313*92022041SSam Saccone attrs = (void *)((unsigned char *)nlh + ack_len);
314*92022041SSam Saccone len -= ack_len;
315*92022041SSam Saccone
316*92022041SSam Saccone nla_parse(tb, NLMSGERR_ATTR_MAX, attrs, len, NULL);
317*92022041SSam Saccone if (tb[NLMSGERR_ATTR_MSG]) {
318*92022041SSam Saccone len = strnlen((char *)nla_data(tb[NLMSGERR_ATTR_MSG]),
319*92022041SSam Saccone nla_len(tb[NLMSGERR_ATTR_MSG]));
320*92022041SSam Saccone fprintf(stderr, "kernel reports: %*s\n", len,
321*92022041SSam Saccone (char *)nla_data(tb[NLMSGERR_ATTR_MSG]));
322*92022041SSam Saccone }
323*92022041SSam Saccone
324*92022041SSam Saccone return NL_STOP;
325*92022041SSam Saccone }
326*92022041SSam Saccone
finish_handler(struct nl_msg * msg,void * arg)327*92022041SSam Saccone static int finish_handler(struct nl_msg *msg, void *arg)
328*92022041SSam Saccone {
329*92022041SSam Saccone int *ret = arg;
330*92022041SSam Saccone *ret = 0;
331*92022041SSam Saccone return NL_SKIP;
332*92022041SSam Saccone }
333*92022041SSam Saccone
ack_handler(struct nl_msg * msg,void * arg)334*92022041SSam Saccone static int ack_handler(struct nl_msg *msg, void *arg)
335*92022041SSam Saccone {
336*92022041SSam Saccone int *ret = arg;
337*92022041SSam Saccone *ret = 0;
338*92022041SSam Saccone return NL_STOP;
339*92022041SSam Saccone }
340*92022041SSam Saccone
341*92022041SSam Saccone static int (*registered_handler)(struct nl_msg *, void *);
342*92022041SSam Saccone static void *registered_handler_data;
343*92022041SSam Saccone
register_handler(int (* handler)(struct nl_msg *,void *),void * data)344*92022041SSam Saccone void register_handler(int (*handler)(struct nl_msg *, void *), void *data)
345*92022041SSam Saccone {
346*92022041SSam Saccone registered_handler = handler;
347*92022041SSam Saccone registered_handler_data = data;
348*92022041SSam Saccone }
349*92022041SSam Saccone
valid_handler(struct nl_msg * msg,void * arg)350*92022041SSam Saccone int valid_handler(struct nl_msg *msg, void *arg)
351*92022041SSam Saccone {
352*92022041SSam Saccone if (registered_handler)
353*92022041SSam Saccone return registered_handler(msg, registered_handler_data);
354*92022041SSam Saccone
355*92022041SSam Saccone return NL_OK;
356*92022041SSam Saccone }
357*92022041SSam Saccone
__handle_cmd(struct nl80211_state * state,enum id_input idby,int argc,char ** argv,const struct cmd ** cmdout)358*92022041SSam Saccone static int __handle_cmd(struct nl80211_state *state, enum id_input idby,
359*92022041SSam Saccone int argc, char **argv, const struct cmd **cmdout)
360*92022041SSam Saccone {
361*92022041SSam Saccone const struct cmd *cmd, *match = NULL, *sectcmd;
362*92022041SSam Saccone struct nl_cb *cb;
363*92022041SSam Saccone struct nl_cb *s_cb;
364*92022041SSam Saccone struct nl_msg *msg;
365*92022041SSam Saccone signed long long devidx = 0;
366*92022041SSam Saccone int err, o_argc, i;
367*92022041SSam Saccone const char *command, *section;
368*92022041SSam Saccone char *tmp, **o_argv;
369*92022041SSam Saccone enum command_identify_by command_idby = CIB_NONE;
370*92022041SSam Saccone
371*92022041SSam Saccone if (argc <= 1 && idby != II_NONE)
372*92022041SSam Saccone return 1;
373*92022041SSam Saccone
374*92022041SSam Saccone o_argc = argc;
375*92022041SSam Saccone o_argv = argv;
376*92022041SSam Saccone
377*92022041SSam Saccone switch (idby) {
378*92022041SSam Saccone case II_PHY_IDX:
379*92022041SSam Saccone command_idby = CIB_PHY;
380*92022041SSam Saccone devidx = strtoul(*argv + 4, &tmp, 0);
381*92022041SSam Saccone if (*tmp != '\0')
382*92022041SSam Saccone return 1;
383*92022041SSam Saccone argc--;
384*92022041SSam Saccone argv++;
385*92022041SSam Saccone break;
386*92022041SSam Saccone case II_PHY_NAME:
387*92022041SSam Saccone command_idby = CIB_PHY;
388*92022041SSam Saccone devidx = phy_lookup(*argv);
389*92022041SSam Saccone argc--;
390*92022041SSam Saccone argv++;
391*92022041SSam Saccone break;
392*92022041SSam Saccone case II_NETDEV:
393*92022041SSam Saccone command_idby = CIB_NETDEV;
394*92022041SSam Saccone devidx = if_nametoindex(*argv);
395*92022041SSam Saccone if (devidx == 0)
396*92022041SSam Saccone devidx = -1;
397*92022041SSam Saccone argc--;
398*92022041SSam Saccone argv++;
399*92022041SSam Saccone break;
400*92022041SSam Saccone case II_WDEV:
401*92022041SSam Saccone command_idby = CIB_WDEV;
402*92022041SSam Saccone devidx = strtoll(*argv, &tmp, 0);
403*92022041SSam Saccone if (*tmp != '\0')
404*92022041SSam Saccone return 1;
405*92022041SSam Saccone argc--;
406*92022041SSam Saccone argv++;
407*92022041SSam Saccone default:
408*92022041SSam Saccone break;
409*92022041SSam Saccone }
410*92022041SSam Saccone
411*92022041SSam Saccone if (devidx < 0)
412*92022041SSam Saccone return -errno;
413*92022041SSam Saccone
414*92022041SSam Saccone section = *argv;
415*92022041SSam Saccone argc--;
416*92022041SSam Saccone argv++;
417*92022041SSam Saccone
418*92022041SSam Saccone for_each_cmd(sectcmd, i) {
419*92022041SSam Saccone if (sectcmd->parent)
420*92022041SSam Saccone continue;
421*92022041SSam Saccone /* ok ... bit of a hack for the dupe 'info' section */
422*92022041SSam Saccone if (match && sectcmd->idby != command_idby)
423*92022041SSam Saccone continue;
424*92022041SSam Saccone if (strcmp(sectcmd->name, section) == 0)
425*92022041SSam Saccone match = sectcmd;
426*92022041SSam Saccone }
427*92022041SSam Saccone
428*92022041SSam Saccone sectcmd = match;
429*92022041SSam Saccone match = NULL;
430*92022041SSam Saccone if (!sectcmd)
431*92022041SSam Saccone return 1;
432*92022041SSam Saccone
433*92022041SSam Saccone if (argc > 0) {
434*92022041SSam Saccone command = *argv;
435*92022041SSam Saccone
436*92022041SSam Saccone for_each_cmd(cmd, i) {
437*92022041SSam Saccone if (!cmd->handler)
438*92022041SSam Saccone continue;
439*92022041SSam Saccone if (cmd->parent != sectcmd)
440*92022041SSam Saccone continue;
441*92022041SSam Saccone /*
442*92022041SSam Saccone * ignore mismatch id by, but allow WDEV
443*92022041SSam Saccone * in place of NETDEV
444*92022041SSam Saccone */
445*92022041SSam Saccone if (cmd->idby != command_idby &&
446*92022041SSam Saccone !(cmd->idby == CIB_NETDEV &&
447*92022041SSam Saccone command_idby == CIB_WDEV))
448*92022041SSam Saccone continue;
449*92022041SSam Saccone if (strcmp(cmd->name, command))
450*92022041SSam Saccone continue;
451*92022041SSam Saccone if (argc > 1 && !cmd->args)
452*92022041SSam Saccone continue;
453*92022041SSam Saccone match = cmd;
454*92022041SSam Saccone break;
455*92022041SSam Saccone }
456*92022041SSam Saccone
457*92022041SSam Saccone if (match) {
458*92022041SSam Saccone argc--;
459*92022041SSam Saccone argv++;
460*92022041SSam Saccone }
461*92022041SSam Saccone }
462*92022041SSam Saccone
463*92022041SSam Saccone if (match)
464*92022041SSam Saccone cmd = match;
465*92022041SSam Saccone else {
466*92022041SSam Saccone /* Use the section itself, if possible. */
467*92022041SSam Saccone cmd = sectcmd;
468*92022041SSam Saccone if (argc && !cmd->args)
469*92022041SSam Saccone return 1;
470*92022041SSam Saccone if (cmd->idby != command_idby &&
471*92022041SSam Saccone !(cmd->idby == CIB_NETDEV && command_idby == CIB_WDEV))
472*92022041SSam Saccone return 1;
473*92022041SSam Saccone if (!cmd->handler)
474*92022041SSam Saccone return 1;
475*92022041SSam Saccone }
476*92022041SSam Saccone
477*92022041SSam Saccone if (cmd->selector) {
478*92022041SSam Saccone cmd = cmd->selector(argc, argv);
479*92022041SSam Saccone if (!cmd)
480*92022041SSam Saccone return 1;
481*92022041SSam Saccone }
482*92022041SSam Saccone
483*92022041SSam Saccone if (cmdout)
484*92022041SSam Saccone *cmdout = cmd;
485*92022041SSam Saccone
486*92022041SSam Saccone if (!cmd->cmd) {
487*92022041SSam Saccone argc = o_argc;
488*92022041SSam Saccone argv = o_argv;
489*92022041SSam Saccone return cmd->handler(state, NULL, argc, argv, idby);
490*92022041SSam Saccone }
491*92022041SSam Saccone
492*92022041SSam Saccone msg = nlmsg_alloc();
493*92022041SSam Saccone if (!msg) {
494*92022041SSam Saccone fprintf(stderr, "failed to allocate netlink message\n");
495*92022041SSam Saccone return 2;
496*92022041SSam Saccone }
497*92022041SSam Saccone
498*92022041SSam Saccone cb = nl_cb_alloc(iw_debug ? NL_CB_DEBUG : NL_CB_DEFAULT);
499*92022041SSam Saccone s_cb = nl_cb_alloc(iw_debug ? NL_CB_DEBUG : NL_CB_DEFAULT);
500*92022041SSam Saccone if (!cb || !s_cb) {
501*92022041SSam Saccone fprintf(stderr, "failed to allocate netlink callbacks\n");
502*92022041SSam Saccone err = 2;
503*92022041SSam Saccone goto out;
504*92022041SSam Saccone }
505*92022041SSam Saccone
506*92022041SSam Saccone genlmsg_put(msg, 0, 0, state->nl80211_id, 0,
507*92022041SSam Saccone cmd->nl_msg_flags, cmd->cmd, 0);
508*92022041SSam Saccone
509*92022041SSam Saccone switch (command_idby) {
510*92022041SSam Saccone case CIB_PHY:
511*92022041SSam Saccone NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, devidx);
512*92022041SSam Saccone break;
513*92022041SSam Saccone case CIB_NETDEV:
514*92022041SSam Saccone NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, devidx);
515*92022041SSam Saccone break;
516*92022041SSam Saccone case CIB_WDEV:
517*92022041SSam Saccone NLA_PUT_U64(msg, NL80211_ATTR_WDEV, devidx);
518*92022041SSam Saccone break;
519*92022041SSam Saccone default:
520*92022041SSam Saccone break;
521*92022041SSam Saccone }
522*92022041SSam Saccone
523*92022041SSam Saccone err = cmd->handler(state, msg, argc, argv, idby);
524*92022041SSam Saccone if (err)
525*92022041SSam Saccone goto out;
526*92022041SSam Saccone
527*92022041SSam Saccone nl_socket_set_cb(state->nl_sock, s_cb);
528*92022041SSam Saccone
529*92022041SSam Saccone err = nl_send_auto_complete(state->nl_sock, msg);
530*92022041SSam Saccone if (err < 0)
531*92022041SSam Saccone goto out;
532*92022041SSam Saccone
533*92022041SSam Saccone err = 1;
534*92022041SSam Saccone
535*92022041SSam Saccone nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
536*92022041SSam Saccone nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
537*92022041SSam Saccone nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
538*92022041SSam Saccone nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, valid_handler, NULL);
539*92022041SSam Saccone
540*92022041SSam Saccone while (err > 0)
541*92022041SSam Saccone nl_recvmsgs(state->nl_sock, cb);
542*92022041SSam Saccone out:
543*92022041SSam Saccone nl_cb_put(cb);
544*92022041SSam Saccone nl_cb_put(s_cb);
545*92022041SSam Saccone nlmsg_free(msg);
546*92022041SSam Saccone return err;
547*92022041SSam Saccone nla_put_failure:
548*92022041SSam Saccone fprintf(stderr, "building message failed\n");
549*92022041SSam Saccone return 2;
550*92022041SSam Saccone }
551*92022041SSam Saccone
handle_cmd(struct nl80211_state * state,enum id_input idby,int argc,char ** argv)552*92022041SSam Saccone int handle_cmd(struct nl80211_state *state, enum id_input idby,
553*92022041SSam Saccone int argc, char **argv)
554*92022041SSam Saccone {
555*92022041SSam Saccone return __handle_cmd(state, idby, argc, argv, NULL);
556*92022041SSam Saccone }
557*92022041SSam Saccone
558*92022041SSam Saccone /*
559*92022041SSam Saccone * Unfortunately, I don't know how densely the linker packs the struct cmd.
560*92022041SSam Saccone * For example, if you have a 72-byte struct cmd, the linker will pad each
561*92022041SSam Saccone * out to 96 bytes before putting them together in the section. There must
562*92022041SSam Saccone * be some algorithm, but I haven't found it yet.
563*92022041SSam Saccone *
564*92022041SSam Saccone * We used to calculate this by taking the (abs value of) the difference
565*92022041SSam Saccone * between __section_get and __section_set, but if LTO is enabled then this
566*92022041SSam Saccone * stops working because the entries of the "__cmd" section get rearranged
567*92022041SSam Saccone * freely by the compiler/linker.
568*92022041SSam Saccone *
569*92022041SSam Saccone * Fix this by using yet another "__sizer" section that only contains these
570*92022041SSam Saccone * two entries - then the (abs value of) the difference between them will
571*92022041SSam Saccone * be how they get packed and that can be used to iterate the __cmd section
572*92022041SSam Saccone * as well.
573*92022041SSam Saccone */
574*92022041SSam Saccone static struct cmd sizer1 __attribute__((section("__sizer"))) = {};
575*92022041SSam Saccone static struct cmd sizer2 __attribute__((section("__sizer"))) = {};
576*92022041SSam Saccone
main(int argc,char ** argv)577*92022041SSam Saccone int main(int argc, char **argv)
578*92022041SSam Saccone {
579*92022041SSam Saccone struct nl80211_state nlstate;
580*92022041SSam Saccone int err;
581*92022041SSam Saccone const struct cmd *cmd = NULL;
582*92022041SSam Saccone
583*92022041SSam Saccone /* calculate command size including padding */
584*92022041SSam Saccone cmd_size = labs((long)&sizer2 - (long)&sizer1);
585*92022041SSam Saccone /* strip off self */
586*92022041SSam Saccone argc--;
587*92022041SSam Saccone argv0 = *argv++;
588*92022041SSam Saccone
589*92022041SSam Saccone if (argc > 0 && strcmp(*argv, "--debug") == 0) {
590*92022041SSam Saccone iw_debug = 1;
591*92022041SSam Saccone argc--;
592*92022041SSam Saccone argv++;
593*92022041SSam Saccone }
594*92022041SSam Saccone
595*92022041SSam Saccone if (argc > 0 && strcmp(*argv, "--version") == 0) {
596*92022041SSam Saccone version();
597*92022041SSam Saccone return 0;
598*92022041SSam Saccone }
599*92022041SSam Saccone
600*92022041SSam Saccone /* need to treat "help" command specially so it works w/o nl80211 */
601*92022041SSam Saccone if (argc == 0 || strcmp(*argv, "help") == 0) {
602*92022041SSam Saccone usage(argc - 1, argv + 1);
603*92022041SSam Saccone return 0;
604*92022041SSam Saccone }
605*92022041SSam Saccone
606*92022041SSam Saccone err = nl80211_init(&nlstate);
607*92022041SSam Saccone if (err)
608*92022041SSam Saccone return 1;
609*92022041SSam Saccone
610*92022041SSam Saccone if (strcmp(*argv, "dev") == 0 && argc > 1) {
611*92022041SSam Saccone argc--;
612*92022041SSam Saccone argv++;
613*92022041SSam Saccone err = __handle_cmd(&nlstate, II_NETDEV, argc, argv, &cmd);
614*92022041SSam Saccone } else if (strncmp(*argv, "phy", 3) == 0 && argc > 1) {
615*92022041SSam Saccone if (strlen(*argv) == 3) {
616*92022041SSam Saccone argc--;
617*92022041SSam Saccone argv++;
618*92022041SSam Saccone err = __handle_cmd(&nlstate, II_PHY_NAME, argc, argv, &cmd);
619*92022041SSam Saccone } else if (*(*argv + 3) == '#')
620*92022041SSam Saccone err = __handle_cmd(&nlstate, II_PHY_IDX, argc, argv, &cmd);
621*92022041SSam Saccone else
622*92022041SSam Saccone goto detect;
623*92022041SSam Saccone } else if (strcmp(*argv, "wdev") == 0 && argc > 1) {
624*92022041SSam Saccone argc--;
625*92022041SSam Saccone argv++;
626*92022041SSam Saccone err = __handle_cmd(&nlstate, II_WDEV, argc, argv, &cmd);
627*92022041SSam Saccone } else {
628*92022041SSam Saccone int idx;
629*92022041SSam Saccone enum id_input idby;
630*92022041SSam Saccone detect:
631*92022041SSam Saccone idby = II_NONE;
632*92022041SSam Saccone if ((idx = if_nametoindex(argv[0])) != 0)
633*92022041SSam Saccone idby = II_NETDEV;
634*92022041SSam Saccone else if ((idx = phy_lookup(argv[0])) >= 0)
635*92022041SSam Saccone idby = II_PHY_NAME;
636*92022041SSam Saccone err = __handle_cmd(&nlstate, idby, argc, argv, &cmd);
637*92022041SSam Saccone }
638*92022041SSam Saccone
639*92022041SSam Saccone if (err == HANDLER_RET_USAGE) {
640*92022041SSam Saccone if (cmd)
641*92022041SSam Saccone usage_cmd(cmd);
642*92022041SSam Saccone else
643*92022041SSam Saccone usage(0, NULL);
644*92022041SSam Saccone } else if (err == HANDLER_RET_DONE) {
645*92022041SSam Saccone err = 0;
646*92022041SSam Saccone } else if (err < 0)
647*92022041SSam Saccone fprintf(stderr, "command failed: %s (%d)\n", strerror(-err), err);
648*92022041SSam Saccone
649*92022041SSam Saccone nl80211_cleanup(&nlstate);
650*92022041SSam Saccone
651*92022041SSam Saccone return err;
652*92022041SSam Saccone }
653