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 #ifndef CONFIG_LIBNL20
27 /* libnl 2.0 compatibility code */
29 static inline struct nl_handle
*nl_socket_alloc(void)
31 return nl_handle_alloc();
34 static inline void nl_socket_free(struct nl_sock
*h
)
39 static inline int __genl_ctrl_alloc_cache(struct nl_sock
*h
, struct nl_cache
**cache
)
41 struct nl_cache
*tmp
= genl_ctrl_alloc_cache(h
);
47 #define genl_ctrl_alloc_cache __genl_ctrl_alloc_cache
48 #endif /* CONFIG_LIBNL20 */
52 static int nl80211_init(struct nl80211_state
*state
)
56 state
->nl_sock
= nl_socket_alloc();
57 if (!state
->nl_sock
) {
58 fprintf(stderr
, "Failed to allocate netlink socket.\n");
62 if (genl_connect(state
->nl_sock
)) {
63 fprintf(stderr
, "Failed to connect to generic netlink.\n");
65 goto out_handle_destroy
;
68 if (genl_ctrl_alloc_cache(state
->nl_sock
, &state
->nl_cache
)) {
69 fprintf(stderr
, "Failed to allocate generic netlink cache.\n");
71 goto out_handle_destroy
;
74 state
->nl80211
= genl_ctrl_search_by_name(state
->nl_cache
, "nl80211");
75 if (!state
->nl80211
) {
76 fprintf(stderr
, "nl80211 not found.\n");
84 nl_cache_free(state
->nl_cache
);
86 nl_socket_free(state
->nl_sock
);
90 static void nl80211_cleanup(struct nl80211_state
*state
)
92 genl_family_put(state
->nl80211
);
93 nl_cache_free(state
->nl_cache
);
94 nl_socket_free(state
->nl_sock
);
97 __COMMAND(NULL
, NULL
, "", NULL
, 0, 0, 0, CIB_NONE
, NULL
, NULL
);
98 __COMMAND(NULL
, NULL
, "", NULL
, 1, 0, 0, CIB_NONE
, NULL
, NULL
);
102 static void __usage_cmd(struct cmd
*cmd
, char *indent
, bool full
)
104 const char *start
, *lend
, *end
;
106 fprintf(stderr
, "%s", indent
);
112 fprintf(stderr
, "phy <phyname> ");
115 fprintf(stderr
, "dev <devname> ");
119 fprintf(stderr
, "%s ", cmd
->section
);
120 fprintf(stderr
, "%s", cmd
->name
);
122 fprintf(stderr
, " %s", cmd
->args
);
123 fprintf(stderr
, "\n");
125 if (!full
|| !cmd
->help
)
132 fprintf(stderr
, "\n");
134 /* print line by line */
136 end
= strchr(start
, '\0');
138 lend
= strchr(start
, '\n');
141 fprintf(stderr
, "%s", indent
);
142 fprintf(stderr
, "%.*s\n", (int)(lend
- start
), start
);
144 } while (end
!= lend
);
146 fprintf(stderr
, "\n");
149 static void usage_options(void)
151 fprintf(stderr
, "Options:\n");
152 fprintf(stderr
, "\t--debug\t\tenable netlink debugging\n");
155 static const char *argv0
;
157 static void usage(bool full
)
161 fprintf(stderr
, "Usage:\t%s [options] command\n", argv0
);
163 fprintf(stderr
, "\t--version\tshow version (%s)\n", iw_version
);
164 fprintf(stderr
, "Commands:\n");
165 for (cmd
= &__start___cmd
; cmd
< &__stop___cmd
;
166 cmd
= (struct cmd
*)((char *)cmd
+ cmd_size
)) {
167 if (!cmd
->handler
|| cmd
->hidden
)
169 __usage_cmd(cmd
, "\t", full
);
171 fprintf(stderr
, "\nYou can omit the 'phy' or 'dev' if "
172 "the identification is unique,\n"
173 "e.g. \"iw wlan0 info\" or \"iw phy0 info\". "
174 "(Don't when scripting.)\n\n");
177 static int print_help(struct nl80211_state
*state
,
180 int argc
, char **argv
)
184 TOPLEVEL(help
, NULL
, 0, 0, CIB_NONE
, print_help
,
185 "Print usage for each command.");
187 static void usage_cmd(struct cmd
*cmd
)
189 fprintf(stderr
, "Usage:\t%s [options] ", argv0
);
190 __usage_cmd(cmd
, "", true);
194 static void version(void)
196 printf("iw version %s\n", iw_version
);
199 static int phy_lookup(char *name
)
204 snprintf(buf
, sizeof(buf
), "/sys/class/ieee80211/%s/index", name
);
206 fd
= open(buf
, O_RDONLY
);
209 pos
= read(fd
, buf
, sizeof(buf
) - 1);
216 static int error_handler(struct sockaddr_nl
*nla
, struct nlmsgerr
*err
,
224 static int finish_handler(struct nl_msg
*msg
, void *arg
)
231 static int ack_handler(struct nl_msg
*msg
, void *arg
)
238 static int __handle_cmd(struct nl80211_state
*state
, enum id_input idby
,
239 int argc
, char **argv
, struct cmd
**cmdout
)
241 struct cmd
*cmd
, *match
= NULL
;
246 const char *command
, *section
;
248 enum command_identify_by command_idby
= CIB_NONE
;
250 if (argc
<= 1 && idby
!= II_NONE
)
258 command_idby
= CIB_PHY
;
259 devidx
= strtoul(*argv
+ 4, &tmp
, 0);
266 command_idby
= CIB_PHY
;
267 devidx
= phy_lookup(*argv
);
272 command_idby
= CIB_NETDEV
;
273 devidx
= if_nametoindex(*argv
);
286 section
= command
= *argv
;
290 for (cmd
= &__start___cmd
; cmd
< &__stop___cmd
;
291 cmd
= (struct cmd
*)((char *)cmd
+ cmd_size
)) {
294 if (cmd
->idby
!= command_idby
)
297 if (strcmp(cmd
->section
, section
))
299 /* this is a bit icky ... */
300 if (command
== section
) {
310 } else if (section
!= command
)
312 if (strcmp(cmd
->name
, command
))
314 if (argc
&& !cmd
->args
)
331 return cmd
->handler(state
, NULL
, NULL
, argc
, argv
);
336 fprintf(stderr
, "failed to allocate netlink message\n");
340 cb
= nl_cb_alloc(iw_debug
? NL_CB_DEBUG
: NL_CB_DEFAULT
);
342 fprintf(stderr
, "failed to allocate netlink callbacks\n");
347 genlmsg_put(msg
, 0, 0, genl_family_get_id(state
->nl80211
), 0,
348 cmd
->nl_msg_flags
, cmd
->cmd
, 0);
350 switch (command_idby
) {
352 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY
, devidx
);
355 NLA_PUT_U32(msg
, NL80211_ATTR_IFINDEX
, devidx
);
361 err
= cmd
->handler(state
, cb
, msg
, argc
, argv
);
365 err
= nl_send_auto_complete(state
->nl_sock
, msg
);
371 nl_cb_err(cb
, NL_CB_CUSTOM
, error_handler
, &err
);
372 nl_cb_set(cb
, NL_CB_FINISH
, NL_CB_CUSTOM
, finish_handler
, &err
);
373 nl_cb_set(cb
, NL_CB_ACK
, NL_CB_CUSTOM
, ack_handler
, &err
);
376 nl_recvmsgs(state
->nl_sock
, cb
);
383 fprintf(stderr
, "building message failed\n");
387 int handle_cmd(struct nl80211_state
*state
, enum id_input idby
,
388 int argc
, char **argv
)
390 return __handle_cmd(state
, idby
, argc
, argv
, NULL
);
393 int main(int argc
, char **argv
)
395 struct nl80211_state nlstate
;
397 struct cmd
*cmd
= NULL
;
399 /* calculate command size including padding */
400 cmd_size
= abs((long)&__cmd_NULL_NULL_1_CIB_NONE_0
401 - (long)&__cmd_NULL_NULL_0_CIB_NONE_0
);
406 if (argc
> 0 && strcmp(*argv
, "--debug") == 0) {
412 if (argc
> 0 && strcmp(*argv
, "--version") == 0) {
417 /* need to treat "help" command specially so it works w/o nl80211 */
418 if (argc
== 0 || strcmp(*argv
, "help") == 0) {
423 err
= nl80211_init(&nlstate
);
427 if (strcmp(*argv
, "dev") == 0 && argc
> 1) {
430 err
= __handle_cmd(&nlstate
, II_NETDEV
, argc
, argv
, &cmd
);
431 } else if (strncmp(*argv
, "phy", 3) == 0 && argc
> 1) {
432 if (strlen(*argv
) == 3) {
435 err
= __handle_cmd(&nlstate
, II_PHY_NAME
, argc
, argv
, &cmd
);
436 } else if (*(*argv
+ 3) == '#')
437 err
= __handle_cmd(&nlstate
, II_PHY_IDX
, argc
, argv
, &cmd
);
442 enum id_input idby
= II_NONE
;
444 if ((idx
= if_nametoindex(argv
[0])) != 0)
446 else if ((idx
= phy_lookup(argv
[0])) >= 0)
448 err
= __handle_cmd(&nlstate
, idby
, argc
, argv
, &cmd
);
457 fprintf(stderr
, "command failed: %s (%d)\n", strerror(-err
), err
);
459 nl80211_cleanup(&nlstate
);