2 * nl80211 userspace tool
4 * Copyright 2007, 2008 Johannes Berg <johannes@sipsolutions.net>
11 #include <sys/types.h>
17 #include <netlink/genl/genl.h>
18 #include <netlink/genl/family.h>
19 #include <netlink/genl/ctrl.h>
20 #include <netlink/msg.h>
21 #include <netlink/attr.h>
26 /* libnl 1.x compatibility code */
27 #if !defined(CONFIG_LIBNL20) && !defined(CONFIG_LIBNL30)
28 static inline struct nl_handle
*nl_socket_alloc(void)
30 return nl_handle_alloc();
33 static inline void nl_socket_free(struct nl_sock
*h
)
38 static inline int nl_socket_set_buffer_size(struct nl_sock
*sk
,
41 return nl_set_buffer_size(sk
, rxbuf
, txbuf
);
43 #endif /* CONFIG_LIBNL20 && CONFIG_LIBNL30 */
47 static int nl80211_init(struct nl80211_state
*state
)
51 state
->nl_sock
= nl_socket_alloc();
52 if (!state
->nl_sock
) {
53 fprintf(stderr
, "Failed to allocate netlink socket.\n");
57 nl_socket_set_buffer_size(state
->nl_sock
, 8192, 8192);
59 if (genl_connect(state
->nl_sock
)) {
60 fprintf(stderr
, "Failed to connect to generic netlink.\n");
62 goto out_handle_destroy
;
65 state
->nl80211_id
= genl_ctrl_resolve(state
->nl_sock
, "nl80211");
66 if (state
->nl80211_id
< 0) {
67 fprintf(stderr
, "nl80211 not found.\n");
69 goto out_handle_destroy
;
75 nl_socket_free(state
->nl_sock
);
79 static void nl80211_cleanup(struct nl80211_state
*state
)
81 nl_socket_free(state
->nl_sock
);
86 extern struct cmd __start___cmd
;
87 extern struct cmd __stop___cmd
;
89 #define for_each_cmd(_cmd) \
90 for (_cmd = &__start___cmd; _cmd < &__stop___cmd; \
91 _cmd = (const struct cmd *)((char *)_cmd + cmd_size))
94 static void __usage_cmd(const struct cmd
*cmd
, char *indent
, bool full
)
96 const char *start
, *lend
, *end
;
104 printf("phy <phyname> ");
107 printf("dev <devname> ");
110 printf("wdev <idx> ");
113 if (cmd
->parent
&& cmd
->parent
->name
)
114 printf("%s ", cmd
->parent
->name
);
115 printf("%s", cmd
->name
);
118 /* print line by line */
120 end
= strchr(start
, '\0');
123 lend
= strchr(start
, '\n');
126 if (start
!= cmd
->args
) {
132 printf("phy <phyname> ");
135 printf("dev <devname> ");
138 printf("wdev <idx> ");
141 if (cmd
->parent
&& cmd
->parent
->name
)
142 printf("%s ", cmd
->parent
->name
);
143 printf("%s ", cmd
->name
);
145 printf("%.*s\n", (int)(lend
- start
), start
);
147 } while (end
!= lend
);
151 if (!full
|| !cmd
->help
)
160 /* print line by line */
162 end
= strchr(start
, '\0');
164 lend
= strchr(start
, '\n');
167 printf("%s", indent
);
168 printf("%.*s\n", (int)(lend
- start
), start
);
170 } while (end
!= lend
);
175 static void usage_options(void)
177 printf("Options:\n");
178 printf("\t--debug\t\tenable netlink debugging\n");
181 static const char *argv0
;
183 static void usage(int argc
, char **argv
)
185 const struct cmd
*section
, *cmd
;
186 bool full
= argc
>= 0;
187 const char *sect_filt
= NULL
;
188 const char *cmd_filt
= NULL
;
196 printf("Usage:\t%s [options] command\n", argv0
);
198 printf("\t--version\tshow version (%s)\n", iw_version
);
199 printf("Commands:\n");
200 for_each_cmd(section
) {
204 if (sect_filt
&& strcmp(section
->name
, sect_filt
))
207 if (section
->handler
&& !section
->hidden
)
208 __usage_cmd(section
, "\t", full
);
211 if (section
!= cmd
->parent
)
213 if (!cmd
->handler
|| cmd
->hidden
)
215 if (cmd_filt
&& strcmp(cmd
->name
, cmd_filt
))
217 __usage_cmd(cmd
, "\t", full
);
220 printf("\nCommands that use the netdev ('dev') can also be given the\n"
221 "'wdev' instead to identify the device.\n");
222 printf("\nYou can omit the 'phy' or 'dev' if "
223 "the identification is unique,\n"
224 "e.g. \"iw wlan0 info\" or \"iw phy0 info\". "
225 "(Don't when scripting.)\n\n"
226 "Do NOT screenscrape this tool, we don't "
227 "consider its output stable.\n\n");
230 static int print_help(struct nl80211_state
*state
,
233 int argc
, char **argv
,
238 TOPLEVEL(help
, "[command]", 0, 0, CIB_NONE
, print_help
,
239 "Print usage for all or a specific command, e.g.\n"
240 "\"help wowlan\" or \"help wowlan enable\".");
242 static void usage_cmd(const struct cmd
*cmd
)
244 printf("Usage:\t%s [options] ", argv0
);
245 __usage_cmd(cmd
, "", true);
249 static void version(void)
251 printf("iw version %s\n", iw_version
);
254 static int phy_lookup(char *name
)
259 snprintf(buf
, sizeof(buf
), "/sys/class/ieee80211/%s/index", name
);
261 fd
= open(buf
, O_RDONLY
);
264 pos
= read(fd
, buf
, sizeof(buf
) - 1);
274 static int error_handler(struct sockaddr_nl
*nla
, struct nlmsgerr
*err
,
282 static int finish_handler(struct nl_msg
*msg
, void *arg
)
289 static int ack_handler(struct nl_msg
*msg
, void *arg
)
296 static int __handle_cmd(struct nl80211_state
*state
, enum id_input idby
,
297 int argc
, char **argv
, const struct cmd
**cmdout
)
299 const struct cmd
*cmd
, *match
= NULL
, *sectcmd
;
303 signed long long devidx
= 0;
305 const char *command
, *section
;
307 enum command_identify_by command_idby
= CIB_NONE
;
309 if (argc
<= 1 && idby
!= II_NONE
)
317 command_idby
= CIB_PHY
;
318 devidx
= strtoul(*argv
+ 4, &tmp
, 0);
325 command_idby
= CIB_PHY
;
326 devidx
= phy_lookup(*argv
);
331 command_idby
= CIB_NETDEV
;
332 devidx
= if_nametoindex(*argv
);
339 command_idby
= CIB_WDEV
;
340 devidx
= strtoll(*argv
, &tmp
, 0);
356 for_each_cmd(sectcmd
) {
359 /* ok ... bit of a hack for the dupe 'info' section */
360 if (match
&& sectcmd
->idby
!= command_idby
)
362 if (strcmp(sectcmd
->name
, section
) == 0)
377 if (cmd
->parent
!= sectcmd
)
380 * ignore mismatch id by, but allow WDEV
383 if (cmd
->idby
!= command_idby
&&
384 !(cmd
->idby
== CIB_NETDEV
&&
385 command_idby
== CIB_WDEV
))
387 if (strcmp(cmd
->name
, command
))
389 if (argc
> 1 && !cmd
->args
)
404 /* Use the section itself, if possible. */
406 if (argc
&& !cmd
->args
)
408 if (cmd
->idby
!= command_idby
&&
409 !(cmd
->idby
== CIB_NETDEV
&& command_idby
== CIB_WDEV
))
416 cmd
= cmd
->selector(argc
, argv
);
427 return cmd
->handler(state
, NULL
, NULL
, argc
, argv
, idby
);
432 fprintf(stderr
, "failed to allocate netlink message\n");
436 cb
= nl_cb_alloc(iw_debug
? NL_CB_DEBUG
: NL_CB_DEFAULT
);
437 s_cb
= nl_cb_alloc(iw_debug
? NL_CB_DEBUG
: NL_CB_DEFAULT
);
439 fprintf(stderr
, "failed to allocate netlink callbacks\n");
444 genlmsg_put(msg
, 0, 0, state
->nl80211_id
, 0,
445 cmd
->nl_msg_flags
, cmd
->cmd
, 0);
447 switch (command_idby
) {
449 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY
, devidx
);
452 NLA_PUT_U32(msg
, NL80211_ATTR_IFINDEX
, devidx
);
455 NLA_PUT_U64(msg
, NL80211_ATTR_WDEV
, devidx
);
461 err
= cmd
->handler(state
, cb
, msg
, argc
, argv
, idby
);
465 nl_socket_set_cb(state
->nl_sock
, s_cb
);
467 err
= nl_send_auto_complete(state
->nl_sock
, msg
);
473 nl_cb_err(cb
, NL_CB_CUSTOM
, error_handler
, &err
);
474 nl_cb_set(cb
, NL_CB_FINISH
, NL_CB_CUSTOM
, finish_handler
, &err
);
475 nl_cb_set(cb
, NL_CB_ACK
, NL_CB_CUSTOM
, ack_handler
, &err
);
478 nl_recvmsgs(state
->nl_sock
, cb
);
485 fprintf(stderr
, "building message failed\n");
489 int handle_cmd(struct nl80211_state
*state
, enum id_input idby
,
490 int argc
, char **argv
)
492 return __handle_cmd(state
, idby
, argc
, argv
, NULL
);
495 int main(int argc
, char **argv
)
497 struct nl80211_state nlstate
;
499 const struct cmd
*cmd
= NULL
;
501 /* calculate command size including padding */
502 cmd_size
= abs((long)&__section_set
- (long)&__section_get
);
507 if (argc
> 0 && strcmp(*argv
, "--debug") == 0) {
513 if (argc
> 0 && strcmp(*argv
, "--version") == 0) {
518 /* need to treat "help" command specially so it works w/o nl80211 */
519 if (argc
== 0 || strcmp(*argv
, "help") == 0) {
520 usage(argc
- 1, argv
+ 1);
524 err
= nl80211_init(&nlstate
);
528 if (strcmp(*argv
, "dev") == 0 && argc
> 1) {
531 err
= __handle_cmd(&nlstate
, II_NETDEV
, argc
, argv
, &cmd
);
532 } else if (strncmp(*argv
, "phy", 3) == 0 && argc
> 1) {
533 if (strlen(*argv
) == 3) {
536 err
= __handle_cmd(&nlstate
, II_PHY_NAME
, argc
, argv
, &cmd
);
537 } else if (*(*argv
+ 3) == '#')
538 err
= __handle_cmd(&nlstate
, II_PHY_IDX
, argc
, argv
, &cmd
);
541 } else if (strcmp(*argv
, "wdev") == 0 && argc
> 1) {
544 err
= __handle_cmd(&nlstate
, II_WDEV
, argc
, argv
, &cmd
);
547 enum id_input idby
= II_NONE
;
549 if ((idx
= if_nametoindex(argv
[0])) != 0)
551 else if ((idx
= phy_lookup(argv
[0])) >= 0)
553 err
= __handle_cmd(&nlstate
, idby
, argc
, argv
, &cmd
);
562 fprintf(stderr
, "command failed: %s (%d)\n", strerror(-err
), err
);
564 nl80211_cleanup(&nlstate
);