Codebase list iw / 7374d62
Import Debian changes 0.9.19-1 iw (0.9.19-1) unstable; urgency=low * New upstream release. - iw moves from /usr/bin to /usr/sbin * Switch to source format 3.0 (quilt). * Bump Standards-Version to 3.8.4, no other changes required. * Remove Reinhard Tartler from uploaders as per request. Thanks for past contributions. * Remove uupdate command from debian/watch, bz2 orig tarballs can now be used. * Ensure DEB_BUILD_OPTIONS=noopt is respected by exporting default CFLAGS in debian/rules. * Export V=1 in debian/rules so that the upstream build system is verbose. * Update debian/copyright. Kel Modderman authored 14 years ago Paride Legovini committed 5 years ago
27 changed file(s) with 1865 addition(s) and 328 deletion(s). Raw diff Collapse all Expand all
22 MAKEFLAGS += --no-print-directory
33
44 PREFIX ?= /usr
5 BINDIR ?= $(PREFIX)/bin
5 SBINDIR ?= $(PREFIX)/sbin
66 MANDIR ?= $(PREFIX)/share/man
7 PKG_CONFIG ?= pkg-config
78
89 MKDIR ?= mkdir -p
910 INSTALL ?= install
1213 CFLAGS ?= -O2 -g
1314 CFLAGS += -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration
1415
15 OBJS = iw.o genl.o event.o info.o phy.o interface.o ibss.o station.o util.o mesh.o mpath.o scan.o reg.o version.o reason.o status.o
16 OBJS = iw.o genl.o event.o info.o phy.o \
17 interface.o ibss.o station.o survey.o util.o \
18 mesh.o mpath.o scan.o reg.o version.o \
19 reason.o status.o connect.o link.o
20 OBJS += sections.o
1621 ALL = iw
1722
18 NL1FOUND := $(shell pkg-config --atleast-version=1 libnl-1 && echo Y)
19 NL2FOUND := $(shell pkg-config --atleast-version=2 libnl-2.0 && echo Y)
23 NL1FOUND := $(shell $(PKG_CONFIG) --atleast-version=1 libnl-1 && echo Y)
24 NL2FOUND := $(shell $(PKG_CONFIG) --atleast-version=2 libnl-2.0 && echo Y)
2025
2126 ifeq ($(NL1FOUND),Y)
2227 NLLIBNAME = libnl-1
3237 $(error Cannot find development files for any supported version of libnl)
3338 endif
3439
35 LIBS += $(shell pkg-config --libs $(NLLIBNAME))
36 CFLAGS += $(shell pkg-config --cflags $(NLLIBNAME))
40 LIBS += $(shell $(PKG_CONFIG) --libs $(NLLIBNAME))
41 CFLAGS += $(shell $(PKG_CONFIG) --cflags $(NLLIBNAME))
3742
3843 ifeq ($(V),1)
3944 Q=
7984
8085 install: iw iw.8.gz
8186 @$(NQ) ' INST iw'
82 $(Q)$(MKDIR) $(DESTDIR)$(BINDIR)
83 $(Q)$(INSTALL) -m 755 -t $(DESTDIR)$(BINDIR) iw
87 $(Q)$(MKDIR) $(DESTDIR)$(SBINDIR)
88 $(Q)$(INSTALL) -m 755 -t $(DESTDIR)$(SBINDIR) iw
8489 @$(NQ) ' INST iw.8'
8590 $(Q)$(MKDIR) $(DESTDIR)$(MANDIR)/man8/
8691 $(Q)$(INSTALL) -m 644 -t $(DESTDIR)$(MANDIR)/man8/ iw.8.gz
0 #include <errno.h>
1
2 #include <netlink/genl/genl.h>
3 #include <netlink/genl/family.h>
4 #include <netlink/genl/ctrl.h>
5 #include <netlink/msg.h>
6 #include <netlink/attr.h>
7
8 #include "nl80211.h"
9 #include "iw.h"
10
11 static int iw_conn(struct nl80211_state *state, struct nl_cb *cb,
12 struct nl_msg *msg, int argc, char **argv)
13 {
14 char *end;
15 unsigned char bssid[6];
16 int freq;
17
18 if (argc < 1)
19 return 1;
20
21 /* SSID */
22 NLA_PUT(msg, NL80211_ATTR_SSID, strlen(argv[0]), argv[0]);
23 argv++;
24 argc--;
25
26 /* freq */
27 if (argc) {
28 freq = strtoul(argv[0], &end, 10);
29 if (*end == '\0') {
30 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
31 argv++;
32 argc--;
33 }
34 }
35
36 /* bssid */
37 if (argc) {
38 if (mac_addr_a2n(bssid, argv[0]) == 0) {
39 NLA_PUT(msg, NL80211_ATTR_MAC, 6, bssid);
40 argv++;
41 argc--;
42 }
43 }
44
45 if (!argc)
46 return 0;
47
48 if (strcmp(*argv, "key") != 0 && strcmp(*argv, "keys") != 0)
49 return 1;
50
51 argv++;
52 argc--;
53
54 return parse_keys(msg, argv, argc);
55 nla_put_failure:
56 return -ENOSPC;
57 }
58
59 static int disconnect(struct nl80211_state *state,
60 struct nl_cb *cb,
61 struct nl_msg *msg,
62 int argc, char **argv)
63 {
64 return 0;
65 }
66 TOPLEVEL(disconnect, NULL,
67 NL80211_CMD_DISCONNECT, 0, CIB_NETDEV, disconnect,
68 "Disconnect from the current network.");
69
70 static int iw_connect(struct nl80211_state *state, struct nl_cb *cb,
71 struct nl_msg *msg, int argc, char **argv)
72 {
73 char **conn_argv, *dev = argv[0];
74 static const __u32 cmds[] = {
75 NL80211_CMD_CONNECT,
76 };
77 struct print_event_args printargs = { };
78 int conn_argc, err;
79 bool wait = false;
80 int i;
81
82 /* strip "wlan0 connect" */
83 argc -= 2;
84 argv += 2;
85
86 /* check -w */
87 if (argc && strcmp(argv[0], "-w") == 0) {
88 wait = true;
89 argc--;
90 argv++;
91 }
92
93 conn_argc = 3 + argc;
94 conn_argv = calloc(conn_argc, sizeof(*conn_argv));
95 if (!conn_argv)
96 return -ENOMEM;
97 conn_argv[0] = dev;
98 conn_argv[1] = "connect";
99 conn_argv[2] = "establish";
100 for (i = 0; i < argc; i++)
101 conn_argv[i + 3] = argv[i];
102 err = handle_cmd(state, II_NETDEV, conn_argc, conn_argv);
103 free(conn_argv);
104 if (err)
105 return err;
106
107 if (!wait)
108 return 0;
109
110 /*
111 * WARNING: DO NOT COPY THIS CODE INTO YOUR APPLICATION
112 *
113 * This code has a bug, which requires creating a separate
114 * nl80211 socket to fix:
115 * It is possible for a NL80211_CMD_NEW_SCAN_RESULTS or
116 * NL80211_CMD_SCAN_ABORTED message to be sent by the kernel
117 * before (!) we listen to it, because we only start listening
118 * after we send our scan request.
119 *
120 * Doing it the other way around has a race condition as well,
121 * if you first open the events socket you may get a notification
122 * for a previous scan.
123 *
124 * The only proper way to fix this would be to listen to events
125 * before sending the command, and for the kernel to send the
126 * connect request along with the event, so that you can match
127 * up whether the connect _you_ requested was finished or aborted.
128 *
129 * Alas, the kernel doesn't do that (yet).
130 */
131
132 __listen_events(state, ARRAY_SIZE(cmds), cmds, &printargs);
133 return 0;
134 }
135 TOPLEVEL(connect, "[-w] <SSID> [<freq in MHz>] [<bssid>] [key 0:abcde d:1:6162636465]",
136 0, 0, CIB_NETDEV, iw_connect,
137 "Join the network with the given SSID (and frequency, BSSID).\n"
138 "With -w, wait for the connect to finish or fail.");
139 HIDDEN(connect, establish, "", NL80211_CMD_CONNECT, 0, CIB_NETDEV, iw_conn);
0 iw (0.9.19-1) unstable; urgency=low
1
2 * New upstream release.
3 - iw moves from /usr/bin to /usr/sbin
4 * Switch to source format 3.0 (quilt).
5 * Bump Standards-Version to 3.8.4, no other changes required.
6 * Remove Reinhard Tartler from uploaders as per request. Thanks for
7 past contributions.
8 * Remove uupdate command from debian/watch, bz2 orig tarballs can now
9 be used.
10 * Ensure DEB_BUILD_OPTIONS=noopt is respected by exporting default
11 CFLAGS in debian/rules.
12 * Export V=1 in debian/rules so that the upstream build system is
13 verbose.
14 * Update debian/copyright.
15
16 -- Kel Modderman <kel@otaku42.de> Sun, 11 Apr 2010 14:25:22 +1000
17
018 iw (0.9.14-1) unstable; urgency=low
119
220 * New upstream release.
22 Priority: extra
33 Maintainer: Debian/Ubuntu wpasupplicant Maintainers <pkg-wpa-devel@lists.alioth.debian.org>
44 Uploaders: Faidon Liambotis <paravoid@debian.org>,
5 Reinhard Tartler <siretart@tauware.de>,
65 Kel Modderman <kel@otaku42.de>
76 Build-Depends: debhelper (>= 7),
87 libnl-dev (>= 1.1),
98 pkg-config (>= 0.22)
10 Standards-Version: 3.8.1
9 Standards-Version: 3.8.4
1110 Vcs-Svn: svn://svn.debian.org/pkg-wpa/iw/trunk
1211 Vcs-Browser: http://svn.debian.org/wsvn/pkg-wpa/iw/trunk/
1312 Homepage: http://wireless.kernel.org/en/users/Documentation/iw
22 Upstream-Source: http://git.sipsolutions.net/iw.git
33
44 Files: *
5 Copyright: Copyright (c) 2007, 2008 Johannes Berg
5 Copyright: Copyright (c) 2007-2010 Johannes Berg
66 Copyright: Copyright (c) 2007 Andy Lutomirski
77 Copyright: Copyright (c) 2007 Mike Kershaw
8 Copyright: Copyright (c) 2008 Luis R. Rodriguez
8 Copyright: Copyright (c) 2008-2009 Luis R. Rodriguez
99 License: ISC
1010
1111 Files: debian/*
12 Copyright: Copyright (c) 2007, 2008 Johannes Berg
13 Copyright: Copyright (c) 2008 Kel Modderman
12 Copyright: Copyright (c) 2007-2008 Johannes Berg
13 Copyright: Copyright (c) 2008-2010 Kel Modderman
1414 License: ISC
1515
1616 License: ISC
00 #!/usr/bin/make -f
1 export CFLAGS = -g -O$(if $(findstring noopt,$(DEB_BUILD_OPTIONS)),0,2)
2 export V=1
3
14 %:
25 dh $@
0 3.0 (quilt)
00 version=3
1 http://wireless.kernel.org/download/iw/iw-(.*)\.tar\.bz2 debian uupdate
1 http://wireless.kernel.org/download/iw/iw-(.*)\.tar\.bz2
88 return NL_OK;
99 }
1010
11 struct print_event_args {
12 bool frame, time;
11 struct ieee80211_beacon_channel {
12 __u16 center_freq;
13 bool passive_scan;
14 bool no_ibss;
1315 };
16
17 static int parse_beacon_hint_chan(struct nlattr *tb,
18 struct ieee80211_beacon_channel *chan)
19 {
20 struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1];
21 static struct nla_policy beacon_freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
22 [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 },
23 [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG },
24 [NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG },
25 };
26
27 if (nla_parse_nested(tb_freq,
28 NL80211_FREQUENCY_ATTR_MAX,
29 tb,
30 beacon_freq_policy))
31 return -EINVAL;
32
33 chan->center_freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
34
35 if (tb_freq[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN])
36 chan->passive_scan = true;
37 if (tb_freq[NL80211_FREQUENCY_ATTR_NO_IBSS])
38 chan->no_ibss = true;
39
40 return 0;
41 }
1442
1543 static void print_frame(struct print_event_args *args, struct nlattr *attr)
1644 {
73101
74102 static int print_event(struct nl_msg *msg, void *arg)
75103 {
104 #define PARSE_BEACON_CHAN(_attr, _chan) do { \
105 r = parse_beacon_hint_chan(tb[_attr], \
106 &_chan); \
107 if (r) \
108 return NL_SKIP; \
109 } while (0)
76110 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
77 struct nlattr *tb[NL80211_ATTR_MAX + 1];
111 struct nlattr *tb[NL80211_ATTR_MAX + 1], *nst;
78112 struct print_event_args *args = arg;
79113 char ifname[100];
80114 char macbuf[6*3];
81115 __u8 reg_type;
116 struct ieee80211_beacon_channel chan_before_beacon, chan_after_beacon;
117 __u32 wiphy_idx = 0;
118 int r;
119 int rem_nst;
120 __u16 status;
82121
83122 if (args->time) {
84123 struct timeval tv;
103142 case NL80211_CMD_NEW_WIPHY:
104143 printf("renamed to %s\n", nla_get_string(tb[NL80211_ATTR_WIPHY_NAME]));
105144 break;
145 case NL80211_CMD_TRIGGER_SCAN:
146 printf("scan started\n");
147 break;
106148 case NL80211_CMD_NEW_SCAN_RESULTS:
107 printf("scan finished\n");
108 break;
149 printf("scan finished:");
109150 case NL80211_CMD_SCAN_ABORTED:
110 printf("scan aborted\n");
151 if (gnlh->cmd == NL80211_CMD_SCAN_ABORTED)
152 printf("scan aborted:");
153 if (tb[NL80211_ATTR_SCAN_FREQUENCIES]) {
154 nla_for_each_nested(nst, tb[NL80211_ATTR_SCAN_FREQUENCIES], rem_nst)
155 printf(" %d", nla_get_u32(nst));
156 printf(",");
157 }
158 if (tb[NL80211_ATTR_SCAN_SSIDS]) {
159 nla_for_each_nested(nst, tb[NL80211_ATTR_SCAN_SSIDS], rem_nst) {
160 printf(" \"");
161 print_ssid_escaped(nla_len(nst), nla_data(nst));
162 printf("\"");
163 }
164 }
165 printf("\n");
111166 break;
112167 case NL80211_CMD_REG_CHANGE:
113168 printf("regulatory domain change: ");
144199
145200 printf("\n");
146201 break;
202 case NL80211_CMD_REG_BEACON_HINT:
203
204 wiphy_idx = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
205
206 memset(&chan_before_beacon, 0, sizeof(chan_before_beacon));
207 memset(&chan_after_beacon, 0, sizeof(chan_after_beacon));
208
209 PARSE_BEACON_CHAN(NL80211_ATTR_FREQ_BEFORE, chan_before_beacon);
210 PARSE_BEACON_CHAN(NL80211_ATTR_FREQ_AFTER, chan_after_beacon);
211
212 if (chan_before_beacon.center_freq != chan_after_beacon.center_freq)
213 break;
214
215 /* A beacon hint is sent _only_ if something _did_ change */
216 printf("beacon hint:\n");
217
218 printf("phy%d %d MHz [%d]:\n",
219 wiphy_idx,
220 chan_before_beacon.center_freq,
221 ieee80211_frequency_to_channel(chan_before_beacon.center_freq));
222
223 if (chan_before_beacon.passive_scan && !chan_after_beacon.passive_scan)
224 printf("\to active scanning enabled\n");
225 if (chan_before_beacon.no_ibss && !chan_after_beacon.no_ibss)
226 printf("\to beaconing enabled\n");
227
228 break;
229 case NL80211_CMD_NEW_STATION:
230 mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
231 printf("new station %s\n", macbuf);
232 break;
147233 case NL80211_CMD_JOIN_IBSS:
148234 mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
149235 printf("IBSS %s joined\n", macbuf);
150236 break;
151237 case NL80211_CMD_AUTHENTICATE:
152238 printf("auth");
153 print_frame(args, tb[NL80211_ATTR_FRAME]);
239 if (tb[NL80211_ATTR_FRAME])
240 print_frame(args, tb[NL80211_ATTR_FRAME]);
241 else if (tb[NL80211_ATTR_TIMED_OUT])
242 printf(": timed out");
243 else
244 printf(": unknown event");
154245 printf("\n");
155246 break;
156247 case NL80211_CMD_ASSOCIATE:
157248 printf("assoc");
158 print_frame(args, tb[NL80211_ATTR_FRAME]);
249 if (tb[NL80211_ATTR_FRAME])
250 print_frame(args, tb[NL80211_ATTR_FRAME]);
251 else if (tb[NL80211_ATTR_TIMED_OUT])
252 printf(": timed out");
253 else
254 printf(": unknown event");
159255 printf("\n");
160256 break;
161257 case NL80211_CMD_DEAUTHENTICATE:
168264 print_frame(args, tb[NL80211_ATTR_FRAME]);
169265 printf("\n");
170266 break;
267 case NL80211_CMD_CONNECT:
268 status = 0;
269 if (!tb[NL80211_ATTR_STATUS_CODE])
270 printf("unknown connect status");
271 else if (nla_get_u16(tb[NL80211_ATTR_STATUS_CODE]) == 0)
272 printf("connected");
273 else {
274 status = nla_get_u16(tb[NL80211_ATTR_STATUS_CODE]);
275 printf("failed to connect");
276 }
277 if (tb[NL80211_ATTR_MAC]) {
278 mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
279 printf(" to %s", macbuf);
280 }
281 if (status)
282 printf(", status: %d: %s", status, get_status_str(status));
283 printf("\n");
284 break;
285 case NL80211_CMD_ROAM:
286 printf("roamed");
287 if (tb[NL80211_ATTR_MAC]) {
288 mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
289 printf(" to %s", macbuf);
290 }
291 printf("\n");
292 break;
293 case NL80211_CMD_DISCONNECT:
294 printf("disconnected");
295 if (tb[NL80211_ATTR_DISCONNECTED_BY_AP])
296 printf(" (by AP)");
297 else
298 printf(" (local request)");
299 if (tb[NL80211_ATTR_REASON_CODE])
300 printf(" reason: %d: %s", nla_get_u16(tb[NL80211_ATTR_REASON_CODE]),
301 get_reason_str(nla_get_u16(tb[NL80211_ATTR_REASON_CODE])));
302 printf("\n");
303 break;
171304 default:
172305 printf("unknown event %d\n", gnlh->cmd);
173306 break;
174307 }
175308
176309 return NL_SKIP;
310 #undef PARSE_BEACON_CHAN
177311 }
178312
179313 struct wait_event {
180314 int n_cmds;
181315 const __u32 *cmds;
182316 __u32 cmd;
317 struct print_event_args *pargs;
183318 };
184319
185320 static int wait_event(struct nl_msg *msg, void *arg)
191326 for (i = 0; i < wait->n_cmds; i++) {
192327 if (gnlh->cmd == wait->cmds[i]) {
193328 wait->cmd = gnlh->cmd;
329 if (wait->pargs)
330 print_event(msg, wait->pargs);
194331 }
195332 }
196333
197334 return NL_SKIP;
198335 }
199336
200 static __u32 __listen_events(struct nl80211_state *state,
201 const int n_waits, const __u32 *waits,
202 struct print_event_args *args)
337 __u32 __listen_events(struct nl80211_state *state,
338 const int n_waits, const __u32 *waits,
339 struct print_event_args *args)
203340 {
204341 int mcid, ret;
205342 struct nl_cb *cb = nl_cb_alloc(iw_debug ? NL_CB_DEBUG : NL_CB_DEFAULT);
249386 if (n_waits && waits) {
250387 wait_ev.cmds = waits;
251388 wait_ev.n_cmds = n_waits;
389 wait_ev.pargs = args;
252390 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, wait_event, &wait_ev);
253 } else {
391 } else
254392 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_event, args);
255 }
256393
257394 wait_ev.cmd = 0;
258395
77
88 #include "nl80211.h"
99 #include "iw.h"
10
11 SECTION(ibss);
1012
1113 static int join_ibss(struct nl80211_state *state,
1214 struct nl_cb *cb,
3941 }
4042
4143 if (argc) {
42 if (mac_addr_a2n(abssid, argv[0]))
43 return 1;
44 NLA_PUT(msg, NL80211_ATTR_MAC, 6, abssid);
45 argv++;
46 argc--;
44 if (mac_addr_a2n(abssid, argv[0]) == 0) {
45 NLA_PUT(msg, NL80211_ATTR_MAC, 6, abssid);
46 argv++;
47 argc--;
48 }
4749 }
4850
49 if (argc)
51 if (!argc)
52 return 0;
53
54 if (strcmp(*argv, "key") != 0 && strcmp(*argv, "keys") != 0)
5055 return 1;
5156
52 return 0;
57 argv++;
58 argc--;
59
60 return parse_keys(msg, argv, argc);
5361 nla_put_failure:
5462 return -ENOSPC;
5563 }
6472 COMMAND(ibss, leave, NULL,
6573 NL80211_CMD_LEAVE_IBSS, 0, CIB_NETDEV, leave_ibss,
6674 "Leave the current IBSS cell.");
67 COMMAND(ibss, join, "<SSID> <freq in MHz> [fixed-freq] [<fixed bssid>]",
75 COMMAND(ibss, join, "<SSID> <freq in MHz> [fixed-freq] [<fixed bssid>] [key d:0:abcde]",
6876 NL80211_CMD_JOIN_IBSS, 0, CIB_NETDEV, join_ibss,
6977 "Join the IBSS cell with the given SSID, if it doesn't exist create\n"
7078 "it on the given frequency. When fixed frequency is requested, don't\n"
+37
-120
info.c less more
1818 printf(", ");
1919 printf("%s", name);
2020 *open = 1;
21 }
22
23 static void print_mcs_index(unsigned char *mcs)
24 {
25 unsigned int mcs_bit;
26
27 for (mcs_bit = 0; mcs_bit <= 76; mcs_bit++) {
28 unsigned int mcs_octet = mcs_bit/8;
29 unsigned int MCS_RATE_BIT = 1 << mcs_bit % 8;
30 bool mcs_rate_idx_set;
31
32 mcs_rate_idx_set = !!(mcs[mcs_octet] & MCS_RATE_BIT);
33
34 if (!mcs_rate_idx_set)
35 continue;
36
37 printf("\t\t\tMCS index %d\n", mcs_bit);
38 }
3921 }
4022
4123 static int print_phy_handler(struct nl_msg *msg, void *arg)
6547 struct nlattr *nl_freq;
6648 struct nlattr *nl_rate;
6749 struct nlattr *nl_mode;
50 struct nlattr *nl_cmd;
6851 int bandidx = 1;
69 int rem_band, rem_freq, rem_rate, rem_mode;
52 int rem_band, rem_freq, rem_rate, rem_mode, rem_cmd;
7053 int open;
7154
7255 nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
8770
8871 #ifdef NL80211_BAND_ATTR_HT_CAPA
8972 if (tb_band[NL80211_BAND_ATTR_HT_CAPA]) {
90 unsigned short cap = nla_get_u16(tb_band[NL80211_BAND_ATTR_HT_CAPA]);
91 #define PCOM(fmt, args...) do { printf("\t\t\t* " fmt "\n", ##args); } while (0)
92 #define PBCOM(bit, args...) if (cap & (bit)) PCOM(args)
93 printf("\t\tHT capabilities: 0x%.4x\n", cap);
94 PBCOM(0x0001, "LPDC coding");
95 if (cap & 0x0002)
96 PCOM("20/40 MHz operation");
97 else
98 PCOM("20 MHz operation");
99 switch ((cap & 0x000c) >> 2) {
100 case 0:
101 PCOM("static SM PS");
102 break;
103 case 1:
104 PCOM("dynamic SM PS");
105 break;
106 case 2:
107 PCOM("reserved SM PS");
108 break;
109 case 3:
110 PCOM("SM PS disabled");
111 break;
112 }
113 PBCOM(0x0010, "HT-greenfield");
114 PBCOM(0x0020, "20 MHz short GI");
115 PBCOM(0x0040, "40 MHz short GI");
116 PBCOM(0x0080, "TX STBC");
117 if (cap & 0x300)
118 PCOM("RX STBC %d streams", (cap & 0x0300) >> 8);
119 PBCOM(0x0400, "HT-delayed block-ack");
120 PCOM("max A-MSDU len %d", 0xeff + ((cap & 0x0800) << 1));
121 PBCOM(0x1000, "DSSS/CCK 40 MHz");
122 PBCOM(0x2000, "PSMP support");
123 PBCOM(0x4000, "40 MHz intolerant");
124 PBCOM(0x8000, "L-SIG TXOP protection support");
73 __u16 cap = nla_get_u16(tb_band[NL80211_BAND_ATTR_HT_CAPA]);
74 print_ht_capability(cap);
12575 }
12676 if (tb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR]) {
127 unsigned char factor = nla_get_u8(tb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR]);
128 printf("\t\tHT A-MPDU factor: 0x%.4x (%d bytes)\n", factor, (1<<(13+factor))-1);
77 __u8 exponent = nla_get_u8(tb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR]);
78 print_ampdu_length(exponent);
12979 }
13080 if (tb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY]) {
131 unsigned char dens = nla_get_u8(tb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY]);
132 printf("\t\tHT A-MPDU density: 0x%.4x (", dens);
133 switch (dens) {
134 case 0:
135 printf("no restriction)\n");
136 break;
137 case 1:
138 printf("1/4 usec)\n");
139 break;
140 case 2:
141 printf("1/2 usec)\n");
142 break;
143 default:
144 printf("%d usec)\n", 1<<(dens - 3));
145 }
81 __u8 spacing = nla_get_u8(tb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY]);
82 print_ampdu_spacing(spacing);
14683 }
14784 if (tb_band[NL80211_BAND_ATTR_HT_MCS_SET] &&
148 nla_len(tb_band[NL80211_BAND_ATTR_HT_MCS_SET]) == 16) {
149 /* As defined in 7.3.2.57.4 Supported MCS Set field */
150 unsigned int tx_max_num_spatial_streams, max_rx_supp_data_rate;
151 unsigned char *mcs = nla_data(tb_band[NL80211_BAND_ATTR_HT_MCS_SET]);
152 bool tx_mcs_set_defined, tx_mcs_set_equal, tx_unequal_modulation;
153
154 printf("\t\tHT MCS set: %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x\n",
155 mcs[0], mcs[1], mcs[2], mcs[3], mcs[4], mcs[5], mcs[6], mcs[7],
156 mcs[8], mcs[9], mcs[10], mcs[11], mcs[12], mcs[13], mcs[14], mcs[15]);
157
158 max_rx_supp_data_rate = ((mcs[10] >> 8) & ((mcs[11] & 0x3) << 8));
159 tx_mcs_set_defined = !!(mcs[12] & (1 << 0));
160 tx_mcs_set_equal = !(mcs[12] & (1 << 1));
161 tx_max_num_spatial_streams = (mcs[12] | ((1 << 3) | (1 << 4))) + 1;
162 tx_unequal_modulation = !!(mcs[12] & (1 << 5));
163
164 if (max_rx_supp_data_rate)
165 printf("\t\tHT Max RX data rate: %d Mbps\n", max_rx_supp_data_rate);
166 /* XXX: else see 9.6.0e.5.3 how to get this I think */
167
168 if (tx_mcs_set_defined) {
169 if (tx_mcs_set_equal) {
170 printf("\t\tHT TX/RX MCS rate indexes supported:\n");
171 print_mcs_index(&mcs[0]);
172 } else {
173 printf("\t\tHT RX MCS rate indexes supported:\n");
174 print_mcs_index(&mcs[0]);
175
176 if (tx_unequal_modulation)
177 printf("TX unequal modulation supported\n");
178 else
179 printf("TX unequal modulation not supported\n");
180
181 printf("\t\tHT TX Max spatiel streams: %d\n",
182 tx_max_num_spatial_streams);
183
184 printf("\t\tHT TX MCS rate indexes supported may differ\n");
185 }
186 }
187 else {
188 printf("\t\tHT RX MCS rate indexes supported:\n");
189 print_mcs_index(&mcs[0]);
190 printf("\t\tHT TX MCS rates indexes are undefined\n");
191 }
192
193 }
85 nla_len(tb_band[NL80211_BAND_ATTR_HT_MCS_SET]) == 16)
86 print_ht_mcs(nla_data(tb_band[NL80211_BAND_ATTR_HT_MCS_SET]));
19487 #endif
19588
19689 printf("\t\tFrequencies:\n");
225118 printf("\n");
226119 }
227120
228 printf("\t\tBitrates:\n");
121 printf("\t\tBitrates (non-HT):\n");
229122
230123 nla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], rem_rate) {
231124 nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX, nla_data(nl_rate),
246139 printf("\tmax # scan SSIDs: %d\n",
247140 nla_get_u8(tb_msg[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]));
248141
142 if (tb_msg[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) {
143 unsigned int frag;
144
145 frag = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]);
146 if (frag != (unsigned int)-1)
147 printf("\tFragmentation threshold: %d\n", frag);
148 }
149
150 if (tb_msg[NL80211_ATTR_WIPHY_RTS_THRESHOLD]) {
151 unsigned int rts;
152
153 rts = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_RTS_THRESHOLD]);
154 if (rts != (unsigned int)-1)
155 printf("\tRTS threshold: %d\n", rts);
156 }
157
249158 if (!tb_msg[NL80211_ATTR_SUPPORTED_IFTYPES])
250 return NL_SKIP;
159 goto commands;
251160
252161 printf("\tSupported interface modes:\n");
253162 nla_for_each_nested(nl_mode, tb_msg[NL80211_ATTR_SUPPORTED_IFTYPES], rem_mode)
254163 printf("\t\t * %s\n", iftype_name(nl_mode->nla_type));
164
165 commands:
166 if (!tb_msg[NL80211_ATTR_SUPPORTED_COMMANDS])
167 return NL_SKIP;
168
169 printf("\tSupported commands:\n");
170 nla_for_each_nested(nl_cmd, tb_msg[NL80211_ATTR_SUPPORTED_COMMANDS], rem_cmd)
171 printf("\t\t * %s\n", command_name(nla_get_u32(nl_cmd)));
255172
256173 return NL_SKIP;
257174 }
265182
266183 return 0;
267184 }
268 TOPLEVEL(info, NULL, NL80211_CMD_GET_WIPHY, 0, CIB_PHY, handle_info,
185 __COMMAND(NULL, info, "info", NULL, NL80211_CMD_GET_WIPHY, 0, 0, CIB_PHY, handle_info,
269186 "Show capabilities for the specified wireless device.");
270187 TOPLEVEL(list, NULL, NL80211_CMD_GET_WIPHY, NLM_F_DUMP, CIB_NONE, handle_info,
271188 "List all wireless devices and their capabilities.");
1616 "control: show control frames\n"\
1717 "otherbss: show frames from other BSSes\n"\
1818 "cook: use cooked mode"
19
20 SECTION(interface);
1921
2022 static char *mntr_flags[NL80211_MNTR_FLAG_MAX + 1] = {
2123 "none",
134136 return 2;
135137 }
136138
139 static int parse_4addr_flag(const char *value, struct nl_msg *msg)
140 {
141 if (strcmp(value, "on") == 0)
142 NLA_PUT_U8(msg, NL80211_ATTR_4ADDR, 1);
143 else if (strcmp(value, "off") == 0)
144 NLA_PUT_U8(msg, NL80211_ATTR_4ADDR, 0);
145 else
146 return 1;
147 return 0;
148
149 nla_put_failure:
150 return 1;
151 }
152
137153 static int handle_interface_add(struct nl80211_state *state,
138154 struct nl_cb *cb,
139155 struct nl_msg *msg,
163179 if (!argc)
164180 return 1;
165181 mesh_id = argv[0];
182 argc--;
183 argv++;
184 } else if (strcmp(argv[0], "4addr") == 0) {
185 argc--;
186 argv++;
187 if (parse_4addr_flag(argv[0], msg)) {
188 fprintf(stderr, "4addr error\n");
189 return 2;
190 }
166191 argc--;
167192 argv++;
168193 } else if (strcmp(argv[0], "flags") == 0) {
189214 nla_put_failure:
190215 return -ENOBUFS;
191216 }
192 COMMAND(interface, add, "<name> type <type> [mesh_id <meshid>] [flags <flag>*]",
217 COMMAND(interface, add, "<name> type <type> [mesh_id <meshid>] [4addr on|off] [flags <flag>*]",
193218 NL80211_CMD_NEW_INTERFACE, 0, CIB_PHY, handle_interface_add,
194219 "Add a new virtual interface with the given configuration.\n"
195220 IFACE_TYPES "\n\n"
196221 "The flags are only used for monitor interfaces, valid flags are:\n"
197222 VALID_FLAGS "\n\n"
198223 "The mesh_id is used only for mesh mode.");
199 COMMAND(interface, add, "<name> type <type> [mesh_id <meshid>] [flags <flag>*]",
224 COMMAND(interface, add, "<name> type <type> [mesh_id <meshid>] [4addr on|off] [flags <flag>*]",
200225 NL80211_CMD_NEW_INTERFACE, 0, CIB_NETDEV, handle_interface_add, NULL);
201226
202227 static int handle_interface_del(struct nl80211_state *state,
+124
-77
iw.c less more
9393 nl_socket_free(state->nl_sock);
9494 }
9595
96 __COMMAND(NULL, NULL, "", NULL, 0, 0, 0, CIB_NONE, NULL, NULL);
97 __COMMAND(NULL, NULL, "", NULL, 1, 0, 0, CIB_NONE, NULL, NULL);
98
9996 static int cmd_size;
10097
101 static void __usage_cmd(struct cmd *cmd, char *indent, bool full)
98 extern struct cmd __start___cmd;
99 extern struct cmd __stop___cmd;
100
101 #define for_each_cmd(_cmd) \
102 for (_cmd = &__start___cmd; _cmd < &__stop___cmd; \
103 _cmd = (const struct cmd *)((char *)_cmd + cmd_size))
104
105
106 static void __usage_cmd(const struct cmd *cmd, char *indent, bool full)
102107 {
103108 const char *start, *lend, *end;
104109
105 fprintf(stderr, "%s", indent);
110 printf("%s", indent);
106111
107112 switch (cmd->idby) {
108113 case CIB_NONE:
109114 break;
110115 case CIB_PHY:
111 fprintf(stderr, "phy <phyname> ");
116 printf("phy <phyname> ");
112117 break;
113118 case CIB_NETDEV:
114 fprintf(stderr, "dev <devname> ");
115 break;
116 }
117 if (cmd->section)
118 fprintf(stderr, "%s ", cmd->section);
119 fprintf(stderr, "%s", cmd->name);
119 printf("dev <devname> ");
120 break;
121 }
122 if (cmd->parent && cmd->parent->name)
123 printf("%s ", cmd->parent->name);
124 printf("%s", cmd->name);
120125 if (cmd->args)
121 fprintf(stderr, " %s", cmd->args);
122 fprintf(stderr, "\n");
126 printf(" %s", cmd->args);
127 printf("\n");
123128
124129 if (!full || !cmd->help)
125130 return;
128133 if (strlen(indent))
129134 indent = "\t\t";
130135 else
131 fprintf(stderr, "\n");
136 printf("\n");
132137
133138 /* print line by line */
134139 start = cmd->help;
137142 lend = strchr(start, '\n');
138143 if (!lend)
139144 lend = end;
140 fprintf(stderr, "%s", indent);
141 fprintf(stderr, "%.*s\n", (int)(lend - start), start);
145 printf("%s", indent);
146 printf("%.*s\n", (int)(lend - start), start);
142147 start = lend + 1;
143148 } while (end != lend);
144149
145 fprintf(stderr, "\n");
150 printf("\n");
146151 }
147152
148153 static void usage_options(void)
149154 {
150 fprintf(stderr, "Options:\n");
151 fprintf(stderr, "\t--debug\t\tenable netlink debugging\n");
155 printf("Options:\n");
156 printf("\t--debug\t\tenable netlink debugging\n");
152157 }
153158
154159 static const char *argv0;
155160
156161 static void usage(bool full)
157162 {
158 struct cmd *cmd;
159
160 fprintf(stderr, "Usage:\t%s [options] command\n", argv0);
163 const struct cmd *section, *cmd;
164
165 printf("Usage:\t%s [options] command\n", argv0);
161166 usage_options();
162 fprintf(stderr, "\t--version\tshow version (%s)\n", iw_version);
163 fprintf(stderr, "Commands:\n");
164 for (cmd = &__start___cmd; cmd < &__stop___cmd;
165 cmd = (struct cmd *)((char *)cmd + cmd_size)) {
166 if (!cmd->handler || cmd->hidden)
167 printf("\t--version\tshow version (%s)\n", iw_version);
168 printf("Commands:\n");
169 for_each_cmd(section) {
170 if (section->parent)
167171 continue;
168 __usage_cmd(cmd, "\t", full);
169 }
172
173 if (section->handler && !section->hidden)
174 __usage_cmd(section, "\t", full);
175
176 for_each_cmd(cmd) {
177 if (section != cmd->parent)
178 continue;
179 if (!cmd->handler || cmd->hidden)
180 continue;
181 __usage_cmd(cmd, "\t", full);
182 }
183 }
184 printf("\nYou can omit the 'phy' or 'dev' if "
185 "the identification is unique,\n"
186 "e.g. \"iw wlan0 info\" or \"iw phy0 info\". "
187 "(Don't when scripting.)\n\n"
188 "Do NOT screenscrape this tool, we don't "
189 "consider its output stable.\n\n");
170190 }
171191
172192 static int print_help(struct nl80211_state *state,
179199 TOPLEVEL(help, NULL, 0, 0, CIB_NONE, print_help,
180200 "Print usage for each command.");
181201
182 static void usage_cmd(struct cmd *cmd)
183 {
184 fprintf(stderr, "Usage:\t%s [options] ", argv0);
202 static void usage_cmd(const struct cmd *cmd)
203 {
204 printf("Usage:\t%s [options] ", argv0);
185205 __usage_cmd(cmd, "", true);
186206 usage_options();
187207 }
202222 if (fd < 0)
203223 return -1;
204224 pos = read(fd, buf, sizeof(buf) - 1);
205 if (pos < 0)
225 if (pos < 0) {
226 close(fd);
206227 return -1;
228 }
207229 buf[pos] = '\0';
230 close(fd);
208231 return atoi(buf);
209232 }
210233
231254 }
232255
233256 static int __handle_cmd(struct nl80211_state *state, enum id_input idby,
234 int argc, char **argv, struct cmd **cmdout)
235 {
236 struct cmd *cmd, *match = NULL;
257 int argc, char **argv, const struct cmd **cmdout)
258 {
259 const struct cmd *cmd, *match = NULL, *sectcmd;
237260 struct nl_cb *cb;
238261 struct nl_msg *msg;
239262 int devidx = 0;
278301 if (devidx < 0)
279302 return -errno;
280303
281 section = command = *argv;
304 section = *argv;
282305 argc--;
283306 argv++;
284307
285 for (cmd = &__start___cmd; cmd < &__stop___cmd;
286 cmd = (struct cmd *)((char *)cmd + cmd_size)) {
308 for_each_cmd(sectcmd) {
309 if (sectcmd->parent)
310 continue;
311 /* ok ... bit of a hack for the dupe 'info' section */
312 if (match && sectcmd->idby != command_idby)
313 continue;
314 if (strcmp(sectcmd->name, section) == 0)
315 match = sectcmd;
316 }
317
318 sectcmd = match;
319 match = NULL;
320 if (!sectcmd)
321 return 1;
322
323 if (argc > 0) {
324 command = *argv;
325
326 for_each_cmd(cmd) {
327 if (!cmd->handler)
328 continue;
329 if (cmd->parent != sectcmd)
330 continue;
331 if (cmd->idby != command_idby)
332 continue;
333 if (strcmp(cmd->name, command))
334 continue;
335 if (argc > 1 && !cmd->args)
336 continue;
337 match = cmd;
338 break;
339 }
340
341 if (match) {
342 argc--;
343 argv++;
344 }
345 }
346
347 if (match)
348 cmd = match;
349 else {
350 /* Use the section itself, if possible. */
351 cmd = sectcmd;
352 if (argc && !cmd->args)
353 return 1;
354 if (cmd->idby != command_idby)
355 return 1;
287356 if (!cmd->handler)
288 continue;
289 if (cmd->idby != command_idby)
290 continue;
291 if (cmd->section) {
292 if (strcmp(cmd->section, section))
293 continue;
294 /* this is a bit icky ... */
295 if (command == section) {
296 if (argc <= 0) {
297 if (match)
298 break;
299 return 1;
300 }
301 command = *argv;
302 argc--;
303 argv++;
304 }
305 } else if (section != command)
306 continue;
307 if (strcmp(cmd->name, command))
308 continue;
309 if (argc && !cmd->args)
310 continue;
311
312 match = cmd;
313 }
314
315 cmd = match;
316
317 if (!cmd)
318 return 1;
357 return 1;
358 }
319359
320360 if (cmdout)
321361 *cmdout = cmd;
389429 {
390430 struct nl80211_state nlstate;
391431 int err;
392 struct cmd *cmd = NULL;
432 const struct cmd *cmd = NULL;
393433
394434 /* calculate command size including padding */
395 cmd_size = abs((long)&__cmd_NULL_NULL_1_CIB_NONE_0
396 - (long)&__cmd_NULL_NULL_0_CIB_NONE_0);
435 cmd_size = abs((long)&__section_set - (long)&__section_get);
397436 /* strip off self */
398437 argc--;
399438 argv0 = *argv++;
431470 } else if (*(*argv + 3) == '#')
432471 err = __handle_cmd(&nlstate, II_PHY_IDX, argc, argv, &cmd);
433472 else
434 err = 1;
435 } else
436 err = __handle_cmd(&nlstate, II_NONE, argc, argv, &cmd);
473 goto detect;
474 } else {
475 int idx;
476 enum id_input idby = II_NONE;
477 detect:
478 if ((idx = if_nametoindex(argv[0])) != 0)
479 idby = II_NETDEV;
480 else if ((idx = phy_lookup(argv[0])) >= 0)
481 idby = II_PHY_NAME;
482 err = __handle_cmd(&nlstate, idby, argc, argv, &cmd);
483 }
437484
438485 if (err == 1) {
439486 if (cmd)
+61
-10
iw.h less more
00 #ifndef __IW_H
11 #define __IW_H
22
3 #include <stdbool.h>
34 #include <netlink/netlink.h>
45 #include <netlink/genl/genl.h>
56 #include <netlink/genl/family.h>
3334 };
3435
3536 struct cmd {
36 const char *section;
3737 const char *name;
3838 const char *args;
3939 const char *help;
5050 struct nl_cb *cb,
5151 struct nl_msg *msg,
5252 int argc, char **argv);
53 const struct cmd *parent;
5354 };
5455
5556 #define ARRAY_SIZE(ar) (sizeof(ar)/sizeof(ar[0]))
5657
5758 #define __COMMAND(_section, _symname, _name, _args, _nlcmd, _flags, _hidden, _idby, _handler, _help)\
58 static const struct cmd \
59 static struct cmd \
5960 __cmd ## _ ## _symname ## _ ## _handler ## _ ## _nlcmd ## _ ## _idby ## _ ## _hidden\
6061 __attribute__((used)) __attribute__((section("__cmd"))) = { \
61 .section = (_section), \
6262 .name = (_name), \
6363 .args = (_args), \
6464 .cmd = (_nlcmd), \
6767 .idby = (_idby), \
6868 .handler = (_handler), \
6969 .help = (_help), \
70 .parent = _section, \
7071 }
7172 #define COMMAND(section, name, args, cmd, flags, idby, handler, help) \
72 __COMMAND(#section, name, #name, args, cmd, flags, 0, idby, handler, help)
73 __COMMAND(&(__section ## _ ## section), name, #name, args, cmd, flags, 0, idby, handler, help)
7374 #define HIDDEN(section, name, args, cmd, flags, idby, handler) \
74 __COMMAND(#section, name, #name, args, cmd, flags, 1, idby, handler, NULL)
75 #define TOPLEVEL(name, args, cmd, flags, idby, handler, help) \
76 __COMMAND(NULL, name, #name, args, cmd, flags, 0, idby, handler, help)
77 extern struct cmd __start___cmd;
78 extern struct cmd __stop___cmd;
75 __COMMAND(&(__section ## _ ## section), name, #name, args, cmd, flags, 1, idby, handler, NULL)
76
77 #define TOPLEVEL(_name, _args, _nlcmd, _flags, _idby, _handler, _help) \
78 struct cmd \
79 __section ## _ ## _name \
80 __attribute__((used)) __attribute__((section("__cmd"))) = { \
81 .name = (#_name), \
82 .args = (_args), \
83 .cmd = (_nlcmd), \
84 .nl_msg_flags = (_flags), \
85 .idby = (_idby), \
86 .handler = (_handler), \
87 .help = (_help), \
88 }
89 #define SECTION(_name) \
90 struct cmd __section ## _ ## _name \
91 __attribute__((used)) __attribute__((section("__cmd"))) = { \
92 .name = (#_name), \
93 .hidden = 1, \
94 }
95
96 #define DECLARE_SECTION(_name) \
97 extern struct cmd __section ## _ ## _name;
7998
8099 extern const char iw_version[];
81100
83102
84103 int handle_cmd(struct nl80211_state *state, enum id_input idby,
85104 int argc, char **argv);
105
106 struct print_event_args {
107 bool frame, time;
108 };
109
86110 __u32 listen_events(struct nl80211_state *state,
87111 const int n_waits, const __u32 *waits);
112 __u32 __listen_events(struct nl80211_state *state,
113 const int n_waits, const __u32 *waits,
114 struct print_event_args *args);
88115
89116
90117 int mac_addr_a2n(unsigned char *mac_addr, char *arg);
91 int mac_addr_n2a(char *mac_addr, unsigned char *arg);
118 void mac_addr_n2a(char *mac_addr, unsigned char *arg);
119
120 int parse_keys(struct nl_msg *msg, char **argv, int argc);
121
122 void print_ht_mcs(const __u8 *mcs);
123 void print_ampdu_length(__u8 exponent);
124 void print_ampdu_spacing(__u8 spacing);
125 void print_ht_capability(__u16 cap);
92126
93127 const char *iftype_name(enum nl80211_iftype iftype);
128 const char *command_name(enum nl80211_commands cmd);
94129 int ieee80211_channel_to_frequency(int chan);
95130 int ieee80211_frequency_to_channel(int freq);
131
132 void print_ssid_escaped(const uint8_t len, const uint8_t *data);
96133
97134 int nl_get_multicast_id(struct nl_sock *sock, const char *family, const char *group);
98135
101138 const char *get_reason_str(uint16_t reason);
102139 const char *get_status_str(uint16_t status);
103140
141 enum print_ie_type {
142 PRINT_SCAN,
143 PRINT_LINK,
144 };
145
146 #define BIT(x) (1ULL<<(x))
147
148 void print_ies(unsigned char *ie, int ielen, bool unknown,
149 enum print_ie_type ptype);
150
151
152 DECLARE_SECTION(set);
153 DECLARE_SECTION(get);
154
104155 #endif /* __IW_H */
0 #include <net/if.h>
1 #include <errno.h>
2 #include <string.h>
3 #include <ctype.h>
4 #include <stdbool.h>
5
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>
11
12 #include "nl80211.h"
13 #include "iw.h"
14
15 struct link_result {
16 uint8_t bssid[8];
17 bool link_found;
18 bool anything_found;
19 };
20
21 static struct link_result lr = { .link_found = false };
22
23 static int link_bss_handler(struct nl_msg *msg, void *arg)
24 {
25 struct nlattr *tb[NL80211_ATTR_MAX + 1];
26 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
27 struct nlattr *bss[NL80211_BSS_MAX + 1];
28 static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
29 [NL80211_BSS_TSF] = { .type = NLA_U64 },
30 [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
31 [NL80211_BSS_BSSID] = { },
32 [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },
33 [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },
34 [NL80211_BSS_INFORMATION_ELEMENTS] = { },
35 [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },
36 [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },
37 [NL80211_BSS_STATUS] = { .type = NLA_U32 },
38 };
39 struct link_result *result = arg;
40 char mac_addr[20], dev[20];
41
42 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
43 genlmsg_attrlen(gnlh, 0), NULL);
44
45 if (!tb[NL80211_ATTR_BSS]) {
46 fprintf(stderr, "bss info missing!\n");
47 return NL_SKIP;
48 }
49 if (nla_parse_nested(bss, NL80211_BSS_MAX,
50 tb[NL80211_ATTR_BSS],
51 bss_policy)) {
52 fprintf(stderr, "failed to parse nested attributes!\n");
53 return NL_SKIP;
54 }
55
56 if (!bss[NL80211_BSS_BSSID])
57 return NL_SKIP;
58
59 if (!bss[NL80211_BSS_STATUS])
60 return NL_SKIP;
61
62 mac_addr_n2a(mac_addr, nla_data(bss[NL80211_BSS_BSSID]));
63 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
64
65 switch (nla_get_u32(bss[NL80211_BSS_STATUS])) {
66 case NL80211_BSS_STATUS_ASSOCIATED:
67 printf("Connected to %s (on %s)\n", mac_addr, dev);
68 break;
69 case NL80211_BSS_STATUS_AUTHENTICATED:
70 printf("Authenticated with %s (on %s)\n", mac_addr, dev);
71 return NL_SKIP;
72 default:
73 return NL_SKIP;
74 }
75
76 result->anything_found = true;
77
78 if (bss[NL80211_BSS_INFORMATION_ELEMENTS])
79 print_ies(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]),
80 nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]),
81 false, PRINT_LINK);
82
83 if (bss[NL80211_BSS_FREQUENCY])
84 printf("\tfreq: %d\n",
85 nla_get_u32(bss[NL80211_BSS_FREQUENCY]));
86
87 if (nla_get_u32(bss[NL80211_BSS_STATUS]) != NL80211_BSS_STATUS_ASSOCIATED)
88 return NL_SKIP;
89
90 /* only in the assoc case do we want more info from station get */
91 result->link_found = true;
92 memcpy(result->bssid, nla_data(bss[NL80211_BSS_BSSID]), 6);
93 return NL_SKIP;
94 }
95
96 static int handle_scan_for_link(struct nl80211_state *state,
97 struct nl_cb *cb,
98 struct nl_msg *msg,
99 int argc, char **argv)
100 {
101 if (argc > 0)
102 return 1;
103
104 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, link_bss_handler, &lr);
105 return 0;
106 }
107
108 static int print_link_sta(struct nl_msg *msg, void *arg)
109 {
110 struct nlattr *tb[NL80211_ATTR_MAX + 1];
111 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
112 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
113 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
114 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
115 [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
116 [NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },
117 [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },
118 [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },
119 [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },
120 [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
121 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
122 [NL80211_STA_INFO_LLID] = { .type = NLA_U16 },
123 [NL80211_STA_INFO_PLID] = { .type = NLA_U16 },
124 [NL80211_STA_INFO_PLINK_STATE] = { .type = NLA_U8 },
125 };
126
127 static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
128 [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
129 [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
130 [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
131 [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
132 };
133
134 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
135 genlmsg_attrlen(gnlh, 0), NULL);
136
137 if (!tb[NL80211_ATTR_STA_INFO]) {
138 fprintf(stderr, "sta stats missing!\n");
139 return NL_SKIP;
140 }
141 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
142 tb[NL80211_ATTR_STA_INFO],
143 stats_policy)) {
144 fprintf(stderr, "failed to parse nested attributes!\n");
145 return NL_SKIP;
146 }
147
148 if (sinfo[NL80211_STA_INFO_RX_BYTES] && sinfo[NL80211_STA_INFO_RX_PACKETS])
149 printf("\tRX: %u bytes (%u packets)\n",
150 nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]),
151 nla_get_u32(sinfo[NL80211_STA_INFO_RX_PACKETS]));
152 if (sinfo[NL80211_STA_INFO_TX_BYTES] && sinfo[NL80211_STA_INFO_TX_PACKETS])
153 printf("\tTX: %u bytes (%u packets)\n",
154 nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]),
155 nla_get_u32(sinfo[NL80211_STA_INFO_TX_PACKETS]));
156 if (sinfo[NL80211_STA_INFO_SIGNAL])
157 printf("\tsignal: %d dBm\n",
158 (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]));
159
160 if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
161 if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
162 sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
163 fprintf(stderr, "failed to parse nested rate attributes!\n");
164 } else {
165 printf("\ttx bitrate: ");
166 if (rinfo[NL80211_RATE_INFO_BITRATE]) {
167 int rate = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
168 printf("%d.%d MBit/s", rate / 10, rate % 10);
169 }
170
171 if (rinfo[NL80211_RATE_INFO_MCS])
172 printf(" MCS %d", nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]));
173 if (rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
174 printf(" 40Mhz");
175 if (rinfo[NL80211_RATE_INFO_SHORT_GI])
176 printf(" short GI");
177 printf("\n");
178 }
179 }
180
181 return NL_SKIP;
182 }
183
184 static int handle_link_sta(struct nl80211_state *state,
185 struct nl_cb *cb,
186 struct nl_msg *msg,
187 int argc, char **argv)
188 {
189 unsigned char mac_addr[ETH_ALEN];
190
191 if (argc < 1)
192 return 1;
193
194 if (mac_addr_a2n(mac_addr, argv[0])) {
195 fprintf(stderr, "invalid mac address\n");
196 return 2;
197 }
198
199 argc--;
200 argv++;
201
202 if (argc)
203 return 1;
204
205 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
206
207 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_link_sta, NULL);
208
209 return 0;
210 nla_put_failure:
211 return -ENOBUFS;
212 }
213
214 static int handle_link(struct nl80211_state *state, struct nl_cb *cb,
215 struct nl_msg *msg, int argc, char **argv)
216 {
217 char *link_argv[] = {
218 NULL,
219 "link",
220 "get_bss",
221 NULL,
222 };
223 char *station_argv[] = {
224 NULL,
225 "link",
226 "get_sta",
227 NULL,
228 NULL,
229 };
230 char bssid_buf[3*6];
231 int err;
232
233 link_argv[0] = argv[0];
234 err = handle_cmd(state, II_NETDEV, 3, link_argv);
235 if (err)
236 return err;
237
238 if (!lr.link_found) {
239 if (!lr.anything_found)
240 printf("Not connected.\n");
241 return 0;
242 }
243
244 mac_addr_n2a(bssid_buf, lr.bssid);
245 bssid_buf[17] = '\0';
246
247 station_argv[0] = argv[0];
248 station_argv[3] = bssid_buf;
249 return handle_cmd(state, II_NETDEV, 4, station_argv);
250 }
251 TOPLEVEL(link, NULL, 0, 0, CIB_NETDEV, handle_link,
252 "Print information about the current link, if any.");
253 HIDDEN(link, get_sta, "", NL80211_CMD_GET_STATION, 0,
254 CIB_NETDEV, handle_link_sta);
255 HIDDEN(link, get_bss, NULL, NL80211_CMD_GET_SCAN, NLM_F_DUMP,
256 CIB_NETDEV, handle_scan_for_link);
164164 {"mesh_hwmp_net_diameter_traversal_time",
165165 NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
166166 _my_nla_put_u16, _parse_u16, _print_u16_in_TUs},
167 {"mesh_hwmp_rootmode", NL80211_MESHCONF_HWMP_ROOTMODE,
168 _my_nla_put_u8, _parse_u8, _print_u8},
167169 };
168170
169171 static void print_all_mesh_param_descr(void)
99
1010 #include "nl80211.h"
1111 #include "iw.h"
12
13 SECTION(mpath);
1214
1315 enum plink_state {
1416 LISTEN,
3537 char dst[20], next_hop[20], dev[20];
3638 static struct nla_policy mpath_policy[NL80211_MPATH_INFO_MAX + 1] = {
3739 [NL80211_MPATH_INFO_FRAME_QLEN] = { .type = NLA_U32 },
38 [NL80211_MPATH_INFO_DSN] = { .type = NLA_U32 },
40 [NL80211_MPATH_INFO_SN] = { .type = NLA_U32 },
3941 [NL80211_MPATH_INFO_METRIC] = { .type = NLA_U32 },
4042 [NL80211_MPATH_INFO_EXPTIME] = { .type = NLA_U32 },
4143 [NL80211_MPATH_INFO_DISCOVERY_TIMEOUT] = { .type = NLA_U32 },
5355 */
5456
5557 if (!tb[NL80211_ATTR_MPATH_INFO]) {
56 fprintf(stderr, "mpath info missing!");
58 fprintf(stderr, "mpath info missing!\n");
5759 return NL_SKIP;
5860 }
5961 if (nla_parse_nested(pinfo, NL80211_MPATH_INFO_MAX,
6062 tb[NL80211_ATTR_MPATH_INFO],
6163 mpath_policy)) {
62 fprintf(stderr, "failed to parse nested attributes!");
64 fprintf(stderr, "failed to parse nested attributes!\n");
6365 return NL_SKIP;
6466 }
6567
6769 mac_addr_n2a(next_hop, nla_data(tb[NL80211_ATTR_MPATH_NEXT_HOP]));
6870 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
6971 printf("%s %s %s", dst, next_hop, dev);
70 if (pinfo[NL80211_MPATH_INFO_DSN])
72 if (pinfo[NL80211_MPATH_INFO_SN])
7173 printf("\t%u",
72 nla_get_u32(pinfo[NL80211_MPATH_INFO_DSN]));
74 nla_get_u32(pinfo[NL80211_MPATH_INFO_SN]));
7375 if (pinfo[NL80211_MPATH_INFO_METRIC])
7476 printf("\t%u",
7577 nla_get_u32(pinfo[NL80211_MPATH_INFO_METRIC]));
181183 struct nl_msg *msg,
182184 int argc, char **argv)
183185 {
186 printf("DEST ADDR NEXT HOP IFACE\tSN\tMETRIC\tQLEN\t"
187 "EXPTIME\t\tDTIM\tDRET\tFLAGS\n");
184188 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_mpath_handler, NULL);
185189 return 0;
186190 }
2323 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2424 *
2525 */
26
27 #include <linux/types.h>
2628
2729 /**
2830 * DOC: Station handling
7678 * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT,
7779 * %NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD.
7880 * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA,
79 * %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC and %NL80211_ATTR_KEY_CIPHER
80 * attributes.
81 * %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC, %NL80211_ATTR_KEY_CIPHER,
82 * and %NL80211_ATTR_KEY_SEQ attributes.
8183 * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX
8284 * or %NL80211_ATTR_MAC.
8385 *
156158 * NL80211_CMD_GET_SCAN and on the "scan" multicast group)
157159 * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons,
158160 * partial scan results may be available
161 *
162 * @NL80211_CMD_GET_SURVEY: get survey resuls, e.g. channel occupation
163 * or noise level
164 * @NL80211_CMD_NEW_SURVEY_RESULTS: survey data notification (as a reply to
165 * NL80211_CMD_GET_SURVEY and on the "scan" multicast group)
159166 *
160167 * @NL80211_CMD_REG_CHANGE: indicates to userspace the regulatory domain
161168 * has been changed and provides details of the request information
202209 * frame, i.e., it was for the local STA and was received in correct
203210 * state. This is similar to MLME-AUTHENTICATE.confirm primitive in the
204211 * MLME SAP interface (kernel providing MLME, userspace SME). The
205 * included NL80211_ATTR_FRAME attribute contains the management frame
206 * (including both the header and frame body, but not FCS).
212 * included %NL80211_ATTR_FRAME attribute contains the management frame
213 * (including both the header and frame body, but not FCS). This event is
214 * also used to indicate if the authentication attempt timed out. In that
215 * case the %NL80211_ATTR_FRAME attribute is replaced with a
216 * %NL80211_ATTR_TIMED_OUT flag (and %NL80211_ATTR_MAC to indicate which
217 * pending authentication timed out).
207218 * @NL80211_CMD_ASSOCIATE: association request and notification; like
208219 * NL80211_CMD_AUTHENTICATE but for Association and Reassociation
209220 * (similar to MLME-ASSOCIATE.request, MLME-REASSOCIATE.request,
229240 * and optionally a MAC (as BSSID) and FREQ_FIXED attribute if those
230241 * should be fixed rather than automatically determined. Can only be
231242 * executed on a network interface that is UP, and fixed BSSID/FREQ
232 * may be rejected.
243 * may be rejected. Another optional parameter is the beacon interval,
244 * given in the %NL80211_ATTR_BEACON_INTERVAL attribute, which if not
245 * given defaults to 100 TU (102.4ms).
233246 * @NL80211_CMD_LEAVE_IBSS: Leave the IBSS -- no special arguments, the IBSS is
234247 * determined by the network interface.
248 *
249 * @NL80211_CMD_TESTMODE: testmode command, takes a wiphy (or ifindex) attribute
250 * to identify the device, and the TESTDATA blob attribute to pass through
251 * to the driver.
252 *
253 * @NL80211_CMD_CONNECT: connection request and notification; this command
254 * requests to connect to a specified network but without separating
255 * auth and assoc steps. For this, you need to specify the SSID in a
256 * %NL80211_ATTR_SSID attribute, and can optionally specify the association
257 * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_MAC,
258 * %NL80211_ATTR_WIPHY_FREQ and %NL80211_ATTR_CONTROL_PORT.
259 * It is also sent as an event, with the BSSID and response IEs when the
260 * connection is established or failed to be established. This can be
261 * determined by the STATUS_CODE attribute.
262 * @NL80211_CMD_ROAM: request that the card roam (currently not implemented),
263 * sent as an event when the card/driver roamed by itself.
264 * @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify
265 * userspace that a connection was dropped by the AP or due to other
266 * reasons, for this the %NL80211_ATTR_DISCONNECTED_BY_AP and
267 * %NL80211_ATTR_REASON_CODE attributes are used.
268 *
269 * @NL80211_CMD_SET_WIPHY_NETNS: Set a wiphy's netns. Note that all devices
270 * associated with this wiphy must be down and will follow.
235271 *
236272 * @NL80211_CMD_MAX: highest used command number
237273 * @__NL80211_CMD_AFTER_LAST: internal use
300336
301337 NL80211_CMD_JOIN_IBSS,
302338 NL80211_CMD_LEAVE_IBSS,
339
340 NL80211_CMD_TESTMODE,
341
342 NL80211_CMD_CONNECT,
343 NL80211_CMD_ROAM,
344 NL80211_CMD_DISCONNECT,
345
346 NL80211_CMD_SET_WIPHY_NETNS,
347
348 NL80211_CMD_GET_SURVEY,
349 NL80211_CMD_NEW_SURVEY_RESULTS,
303350
304351 /* add new commands above here */
305352
373420 *
374421 * @NL80211_ATTR_STA_AID: Association ID for the station (u16)
375422 * @NL80211_ATTR_STA_FLAGS: flags, nested element with NLA_FLAG attributes of
376 * &enum nl80211_sta_flags.
423 * &enum nl80211_sta_flags (deprecated, use %NL80211_ATTR_STA_FLAGS2)
377424 * @NL80211_ATTR_STA_LISTEN_INTERVAL: listen interval as defined by
378425 * IEEE 802.11 7.3.1.6 (u16).
379426 * @NL80211_ATTR_STA_SUPPORTED_RATES: supported rates, array of supported
440487 * @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz)
441488 * @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive
442489 * scanning and include a zero-length SSID (wildcard) for wildcard scan
443 * @NL80211_ATTR_SCAN_GENERATION: the scan generation increases whenever the
444 * scan result list changes (BSS expired or added) so that applications
445 * can verify that they got a single, consistent snapshot (when all dump
446 * messages carried the same generation number)
447490 * @NL80211_ATTR_BSS: scan result BSS
448491 *
449492 * @NL80211_ATTR_REG_INITIATOR: indicates who requested the regulatory domain
484527 * @NL80211_ATTR_FREQ_FIXED: a flag indicating the IBSS should not try to look
485528 * for other networks on different channels
486529 *
530 * @NL80211_ATTR_TIMED_OUT: a flag indicating than an operation timed out; this
531 * is used, e.g., with %NL80211_CMD_AUTHENTICATE event
532 *
533 * @NL80211_ATTR_USE_MFP: Whether management frame protection (IEEE 802.11w) is
534 * used for the association (&enum nl80211_mfp, represented as a u32);
535 * this attribute can be used
536 * with %NL80211_CMD_ASSOCIATE request
537 *
538 * @NL80211_ATTR_STA_FLAGS2: Attribute containing a
539 * &struct nl80211_sta_flag_update.
540 *
541 * @NL80211_ATTR_CONTROL_PORT: A flag indicating whether user space controls
542 * IEEE 802.1X port, i.e., sets/clears %NL80211_STA_FLAG_AUTHORIZED, in
543 * station mode. If the flag is included in %NL80211_CMD_ASSOCIATE
544 * request, the driver will assume that the port is unauthorized until
545 * authorized by user space. Otherwise, port is marked authorized by
546 * default in station mode.
547 *
548 * @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver.
549 * We recommend using nested, driver-specific attributes within this.
550 *
551 * @NL80211_ATTR_DISCONNECTED_BY_AP: A flag indicating that the DISCONNECT
552 * event was due to the AP disconnecting the station, and not due to
553 * a local disconnect request.
554 * @NL80211_ATTR_STATUS_CODE: StatusCode for the %NL80211_CMD_CONNECT
555 * event (u16)
556 * @NL80211_ATTR_PRIVACY: Flag attribute, used with connect(), indicating
557 * that protected APs should be used.
558 *
559 * @NL80211_ATTR_CIPHERS_PAIRWISE: Used with CONNECT and ASSOCIATE to
560 * indicate which unicast key ciphers will be used with the connection
561 * (an array of u32).
562 * @NL80211_ATTR_CIPHER_GROUP: Used with CONNECT and ASSOCIATE to indicate
563 * which group key cipher will be used with the connection (a u32).
564 * @NL80211_ATTR_WPA_VERSIONS: Used with CONNECT and ASSOCIATE to indicate
565 * which WPA version(s) the AP we want to associate with is using
566 * (a u32 with flags from &enum nl80211_wpa_versions).
567 * @NL80211_ATTR_AKM_SUITES: Used with CONNECT and ASSOCIATE to indicate
568 * which key management algorithm(s) to use (an array of u32).
569 *
570 * @NL80211_ATTR_REQ_IE: (Re)association request information elements as
571 * sent out by the card, for ROAM and successful CONNECT events.
572 * @NL80211_ATTR_RESP_IE: (Re)association response information elements as
573 * sent by peer, for ROAM and successful CONNECT events.
574 *
575 * @NL80211_ATTR_PREV_BSSID: previous BSSID, to be used by in ASSOCIATE
576 * commands to specify using a reassociate frame
577 *
578 * @NL80211_ATTR_KEY: key information in a nested attribute with
579 * %NL80211_KEY_* sub-attributes
580 * @NL80211_ATTR_KEYS: array of keys for static WEP keys for connect()
581 * and join_ibss(), key information is in a nested attribute each
582 * with %NL80211_KEY_* sub-attributes
583 *
584 * @NL80211_ATTR_PID: Process ID of a network namespace.
585 *
586 * @NL80211_ATTR_GENERATION: Used to indicate consistent snapshots for
587 * dumps. This number increases whenever the object list being
588 * dumped changes, and as such userspace can verify that it has
589 * obtained a complete and consistent snapshot by verifying that
590 * all dump messages contain the same generation number. If it
591 * changed then the list changed and the dump should be repeated
592 * completely from scratch.
593 *
594 * @NL80211_ATTR_4ADDR: Use 4-address frames on a virtual interface
595 *
596 * @NL80211_ATTR_SURVEY_INFO: survey information about a channel, part of
597 * the survey response for %NL80211_CMD_GET_SURVEY, nested attribute
598 * containing info as possible, see &enum survey_info.
599 *
487600 * @NL80211_ATTR_MAX: highest attribute number currently defined
488601 * @__NL80211_ATTR_AFTER_LAST: internal use
489602 */
555668
556669 NL80211_ATTR_SCAN_FREQUENCIES,
557670 NL80211_ATTR_SCAN_SSIDS,
558 NL80211_ATTR_SCAN_GENERATION,
671 NL80211_ATTR_GENERATION, /* replaces old SCAN_GENERATION */
559672 NL80211_ATTR_BSS,
560673
561674 NL80211_ATTR_REG_INITIATOR,
584697 NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
585698 NL80211_ATTR_WIPHY_RTS_THRESHOLD,
586699
700 NL80211_ATTR_TIMED_OUT,
701
702 NL80211_ATTR_USE_MFP,
703
704 NL80211_ATTR_STA_FLAGS2,
705
706 NL80211_ATTR_CONTROL_PORT,
707
708 NL80211_ATTR_TESTDATA,
709
710 NL80211_ATTR_PRIVACY,
711
712 NL80211_ATTR_DISCONNECTED_BY_AP,
713 NL80211_ATTR_STATUS_CODE,
714
715 NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
716 NL80211_ATTR_CIPHER_SUITE_GROUP,
717 NL80211_ATTR_WPA_VERSIONS,
718 NL80211_ATTR_AKM_SUITES,
719
720 NL80211_ATTR_REQ_IE,
721 NL80211_ATTR_RESP_IE,
722
723 NL80211_ATTR_PREV_BSSID,
724
725 NL80211_ATTR_KEY,
726 NL80211_ATTR_KEYS,
727
728 NL80211_ATTR_PID,
729
730 NL80211_ATTR_4ADDR,
731
732 NL80211_ATTR_SURVEY_INFO,
733
587734 /* add attributes here, update the policy in nl80211.c */
588735
589736 __NL80211_ATTR_AFTER_LAST,
590737 NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
591738 };
739
740 /* source-level API compatibility */
741 #define NL80211_ATTR_SCAN_GENERATION NL80211_ATTR_GENERATION
592742
593743 /*
594744 * Allow user space programs to use #ifdef on new attributes by defining them
595745 * here
596746 */
747 #define NL80211_CMD_CONNECT NL80211_CMD_CONNECT
597748 #define NL80211_ATTR_HT_CAPABILITY NL80211_ATTR_HT_CAPABILITY
598749 #define NL80211_ATTR_BSS_BASIC_RATES NL80211_ATTR_BSS_BASIC_RATES
599750 #define NL80211_ATTR_WIPHY_TXQ_PARAMS NL80211_ATTR_WIPHY_TXQ_PARAMS
607758 #define NL80211_ATTR_SSID NL80211_ATTR_SSID
608759 #define NL80211_ATTR_AUTH_TYPE NL80211_ATTR_AUTH_TYPE
609760 #define NL80211_ATTR_REASON_CODE NL80211_ATTR_REASON_CODE
761 #define NL80211_ATTR_CIPHER_SUITES_PAIRWISE NL80211_ATTR_CIPHER_SUITES_PAIRWISE
762 #define NL80211_ATTR_CIPHER_SUITE_GROUP NL80211_ATTR_CIPHER_SUITE_GROUP
763 #define NL80211_ATTR_WPA_VERSIONS NL80211_ATTR_WPA_VERSIONS
764 #define NL80211_ATTR_AKM_SUITES NL80211_ATTR_AKM_SUITES
765 #define NL80211_ATTR_KEY NL80211_ATTR_KEY
766 #define NL80211_ATTR_KEYS NL80211_ATTR_KEYS
610767
611768 #define NL80211_MAX_SUPP_RATES 32
612769 #define NL80211_MAX_SUPP_REG_RULES 32
614771 #define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16
615772 #define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24
616773 #define NL80211_HT_CAPABILITY_LEN 26
774
775 #define NL80211_MAX_NR_CIPHER_SUITES 5
776 #define NL80211_MAX_NR_AKM_SUITES 2
617777
618778 /**
619779 * enum nl80211_iftype - (virtual) interface types
671831 __NL80211_STA_FLAG_AFTER_LAST,
672832 NL80211_STA_FLAG_MAX = __NL80211_STA_FLAG_AFTER_LAST - 1
673833 };
834
835 /**
836 * struct nl80211_sta_flag_update - station flags mask/set
837 * @mask: mask of station flags to set
838 * @set: which values to set them to
839 *
840 * Both mask and set contain bits as per &enum nl80211_sta_flags.
841 */
842 struct nl80211_sta_flag_update {
843 __u32 mask;
844 __u32 set;
845 } __attribute__((packed));
674846
675847 /**
676848 * enum nl80211_rate_info - bitrate information
740912 *
741913 * @NL80211_MPATH_FLAG_ACTIVE: the mesh path is active
742914 * @NL80211_MPATH_FLAG_RESOLVING: the mesh path discovery process is running
743 * @NL80211_MPATH_FLAG_DSN_VALID: the mesh path contains a valid DSN
915 * @NL80211_MPATH_FLAG_SN_VALID: the mesh path contains a valid SN
744916 * @NL80211_MPATH_FLAG_FIXED: the mesh path has been manually set
745917 * @NL80211_MPATH_FLAG_RESOLVED: the mesh path discovery process succeeded
746918 */
747919 enum nl80211_mpath_flags {
748920 NL80211_MPATH_FLAG_ACTIVE = 1<<0,
749921 NL80211_MPATH_FLAG_RESOLVING = 1<<1,
750 NL80211_MPATH_FLAG_DSN_VALID = 1<<2,
922 NL80211_MPATH_FLAG_SN_VALID = 1<<2,
751923 NL80211_MPATH_FLAG_FIXED = 1<<3,
752924 NL80211_MPATH_FLAG_RESOLVED = 1<<4,
753925 };
760932 *
761933 * @__NL80211_MPATH_INFO_INVALID: attribute number 0 is reserved
762934 * @NL80211_ATTR_MPATH_FRAME_QLEN: number of queued frames for this destination
763 * @NL80211_ATTR_MPATH_DSN: destination sequence number
935 * @NL80211_ATTR_MPATH_SN: destination sequence number
764936 * @NL80211_ATTR_MPATH_METRIC: metric (cost) of this mesh path
765937 * @NL80211_ATTR_MPATH_EXPTIME: expiration time for the path, in msec from now
766938 * @NL80211_ATTR_MPATH_FLAGS: mesh path flags, enumerated in
771943 enum nl80211_mpath_info {
772944 __NL80211_MPATH_INFO_INVALID,
773945 NL80211_MPATH_INFO_FRAME_QLEN,
774 NL80211_MPATH_INFO_DSN,
946 NL80211_MPATH_INFO_SN,
775947 NL80211_MPATH_INFO_METRIC,
776948 NL80211_MPATH_INFO_EXPTIME,
777949 NL80211_MPATH_INFO_FLAGS,
9621134 };
9631135
9641136 /**
1137 * enum nl80211_survey_info - survey information
1138 *
1139 * These attribute types are used with %NL80211_ATTR_SURVEY_INFO
1140 * when getting information about a survey.
1141 *
1142 * @__NL80211_SURVEY_INFO_INVALID: attribute number 0 is reserved
1143 * @NL80211_SURVEY_INFO_FREQUENCY: center frequency of channel
1144 * @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm)
1145 */
1146 enum nl80211_survey_info {
1147 __NL80211_SURVEY_INFO_INVALID,
1148 NL80211_SURVEY_INFO_FREQUENCY,
1149 NL80211_SURVEY_INFO_NOISE,
1150
1151 /* keep last */
1152 __NL80211_SURVEY_INFO_AFTER_LAST,
1153 NL80211_SURVEY_INFO_MAX = __NL80211_SURVEY_INFO_AFTER_LAST - 1
1154 };
1155
1156 /**
9651157 * enum nl80211_mntr_flags - monitor configuration flags
9661158 *
9671159 * Monitor configuration flags.
10401232 *
10411233 * @NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME: The interval of time (in TUs)
10421234 * that it takes for an HWMP information element to propagate across the mesh
1235 *
1236 * @NL80211_MESHCONF_ROOTMODE: whether root mode is enabled or not
10431237 *
10441238 * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute
10451239 *
10601254 NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
10611255 NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
10621256 NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
1257 NL80211_MESHCONF_HWMP_ROOTMODE,
10631258
10641259 /* keep last */
10651260 __NL80211_MESHCONF_ATTR_AFTER_LAST,
11211316 * in mBm (100 * dBm) (s32)
11221317 * @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon
11231318 * in unspecified units, scaled to 0..100 (u8)
1319 * @NL80211_BSS_STATUS: status, if this BSS is "used"
1320 * @NL80211_BSS_SEEN_MS_AGO: age of this BSS entry in ms
11241321 * @__NL80211_BSS_AFTER_LAST: internal
11251322 * @NL80211_BSS_MAX: highest BSS attribute
11261323 */
11341331 NL80211_BSS_INFORMATION_ELEMENTS,
11351332 NL80211_BSS_SIGNAL_MBM,
11361333 NL80211_BSS_SIGNAL_UNSPEC,
1334 NL80211_BSS_STATUS,
1335 NL80211_BSS_SEEN_MS_AGO,
11371336
11381337 /* keep last */
11391338 __NL80211_BSS_AFTER_LAST,
11401339 NL80211_BSS_MAX = __NL80211_BSS_AFTER_LAST - 1
1340 };
1341
1342 /**
1343 * enum nl80211_bss_status - BSS "status"
1344 */
1345 enum nl80211_bss_status {
1346 NL80211_BSS_STATUS_AUTHENTICATED,
1347 NL80211_BSS_STATUS_ASSOCIATED,
1348 NL80211_BSS_STATUS_IBSS_JOINED,
11411349 };
11421350
11431351 /**
11471355 * @NL80211_AUTHTYPE_SHARED_KEY: Shared Key authentication (WEP only)
11481356 * @NL80211_AUTHTYPE_FT: Fast BSS Transition (IEEE 802.11r)
11491357 * @NL80211_AUTHTYPE_NETWORK_EAP: Network EAP (some Cisco APs and mainly LEAP)
1358 * @__NL80211_AUTHTYPE_NUM: internal
1359 * @NL80211_AUTHTYPE_MAX: maximum valid auth algorithm
1360 * @NL80211_AUTHTYPE_AUTOMATIC: determine automatically (if necessary by
1361 * trying multiple times); this is invalid in netlink -- leave out
1362 * the attribute for this on CONNECT commands.
11501363 */
11511364 enum nl80211_auth_type {
11521365 NL80211_AUTHTYPE_OPEN_SYSTEM,
11531366 NL80211_AUTHTYPE_SHARED_KEY,
11541367 NL80211_AUTHTYPE_FT,
11551368 NL80211_AUTHTYPE_NETWORK_EAP,
1369
1370 /* keep last */
1371 __NL80211_AUTHTYPE_NUM,
1372 NL80211_AUTHTYPE_MAX = __NL80211_AUTHTYPE_NUM - 1,
1373 NL80211_AUTHTYPE_AUTOMATIC
11561374 };
11571375
11581376 /**
11671385 NL80211_KEYTYPE_PEERKEY,
11681386 };
11691387
1388 /**
1389 * enum nl80211_mfp - Management frame protection state
1390 * @NL80211_MFP_NO: Management frame protection not used
1391 * @NL80211_MFP_REQUIRED: Management frame protection required
1392 */
1393 enum nl80211_mfp {
1394 NL80211_MFP_NO,
1395 NL80211_MFP_REQUIRED,
1396 };
1397
1398 enum nl80211_wpa_versions {
1399 NL80211_WPA_VERSION_1 = 1 << 0,
1400 NL80211_WPA_VERSION_2 = 1 << 1,
1401 };
1402
1403 /**
1404 * enum nl80211_key_attributes - key attributes
1405 * @__NL80211_KEY_INVALID: invalid
1406 * @NL80211_KEY_DATA: (temporal) key data; for TKIP this consists of
1407 * 16 bytes encryption key followed by 8 bytes each for TX and RX MIC
1408 * keys
1409 * @NL80211_KEY_IDX: key ID (u8, 0-3)
1410 * @NL80211_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11
1411 * section 7.3.2.25.1, e.g. 0x000FAC04)
1412 * @NL80211_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and
1413 * CCMP keys, each six bytes in little endian
1414 * @NL80211_KEY_DEFAULT: flag indicating default key
1415 * @NL80211_KEY_DEFAULT_MGMT: flag indicating default management key
1416 * @__NL80211_KEY_AFTER_LAST: internal
1417 * @NL80211_KEY_MAX: highest key attribute
1418 */
1419 enum nl80211_key_attributes {
1420 __NL80211_KEY_INVALID,
1421 NL80211_KEY_DATA,
1422 NL80211_KEY_IDX,
1423 NL80211_KEY_CIPHER,
1424 NL80211_KEY_SEQ,
1425 NL80211_KEY_DEFAULT,
1426 NL80211_KEY_DEFAULT_MGMT,
1427
1428 /* keep last */
1429 __NL80211_KEY_AFTER_LAST,
1430 NL80211_KEY_MAX = __NL80211_KEY_AFTER_LAST - 1
1431 };
1432
11701433 #endif /* __LINUX_NL80211_H */
9191 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_chan, NULL);
9292 COMMAND(set, channel, "<channel> [HT20|HT40+|HT40-]",
9393 NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_chan, NULL);
94
95 static int handle_fragmentation(struct nl80211_state *state,
96 struct nl_cb *cb, struct nl_msg *msg,
97 int argc, char **argv)
98 {
99 unsigned int frag;
100
101 if (argc != 1)
102 return 1;
103
104 if (strcmp("off", argv[0]) == 0)
105 frag = -1;
106 else
107 frag = strtoul(argv[0], NULL, 10);
108
109 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, frag);
110
111 return 0;
112 nla_put_failure:
113 return -ENOBUFS;
114 }
115 COMMAND(set, frag, "<fragmentation threshold|off>",
116 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_fragmentation,
117 "Set fragmentation threshold.");
118
119 static int handle_rts(struct nl80211_state *state,
120 struct nl_cb *cb, struct nl_msg *msg,
121 int argc, char **argv)
122 {
123 unsigned int rts;
124
125 if (argc != 1)
126 return 1;
127
128 if (strcmp("off", argv[0]) == 0)
129 rts = -1;
130 else
131 rts = strtoul(argv[0], NULL, 10);
132
133 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, rts);
134
135 return 0;
136 nla_put_failure:
137 return -ENOBUFS;
138 }
139 COMMAND(set, rts, "<rts threshold|off>",
140 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_rts,
141 "Set rts threshold.");
142
143 static int handle_netns(struct nl80211_state *state,
144 struct nl_cb *cb,
145 struct nl_msg *msg,
146 int argc, char **argv)
147 {
148 char *end;
149
150 if (argc != 1)
151 return 1;
152
153 NLA_PUT_U32(msg, NL80211_ATTR_PID,
154 strtoul(argv[0], &end, 10));
155
156 if (*end != '\0')
157 return 1;
158
159 return 0;
160 nla_put_failure:
161 return -ENOBUFS;
162 }
163 COMMAND(set, netns, "<pid>",
164 NL80211_CMD_SET_WIPHY_NETNS, 0, CIB_PHY, handle_netns,
165 "Put this wireless device into a different network namespace");
2525 [23] = "IEEE 802.1X authentication failed",
2626 [24] = "Cipher Suite rejected per security policy",
2727 [31] = "TS deleted because QoS AP lacks sufficient bandwidth for this QoS STA due to a change in BSS service characteristics or operational mode",
28 [32] = "Disassociated for unspecified] = QoS-related reason",
28 [32] = "Disassociated for unspecified QoS-related reason",
2929 [33] = "Disassociated because QAP lacks sufficient bandwidth for this STA",
3030 [34] = "Disassociated because of excessive frame losses and/or poor channel conditions",
3131 [35] = "Disassociated because QSTA is transmitting outside the limits of its polled TXOPs",
1010
1111 #include "nl80211.h"
1212 #include "iw.h"
13
14 SECTION(reg);
1315
1416 #define MHZ_TO_KHZ(freq) ((freq) * 1000)
1517 #define KHZ_TO_MHZ(freq) ((freq) / 1000)
+130
-46
scan.c less more
3131
3232 struct scan_params {
3333 bool unknown;
34 enum print_ie_type type;
3435 };
3536
3637 static int handle_scan(struct nl80211_state *state,
106107 nlmsg_free(freqs);
107108 return err;
108109 }
109 COMMAND(scan, trigger, "[freq <freq>*] [ssid <ssid>*|passive]",
110 NL80211_CMD_TRIGGER_SCAN, 0, CIB_NETDEV, handle_scan,
111 "Trigger a scan on the given frequencies with probing for the given\n"
112 "SSIDs (or wildcard if not given) unless passive scanning is requested.");
113110
114111 static void tab_on_first(bool *first)
115112 {
121118
122119 static void print_ssid(const uint8_t type, uint8_t len, const uint8_t *data)
123120 {
124 int i;
125
126121 printf(" ");
127
128 for (i = 0; i < len; i++) {
129 if (isprint(data[i]))
130 printf("%c", data[i]);
131 else
132 printf("\\x%.2x", data[i]);
133 }
122 print_ssid_escaped(len, data);
134123 printf("\n");
135124 }
136125
429418 static void print_rsn(const uint8_t type, uint8_t len, const uint8_t *data)
430419 {
431420 print_rsn_ie("CCMP", "IEEE 802.1X", len, data);
421 }
422
423 static void print_ht_capa(const uint8_t type, uint8_t len, const uint8_t *data)
424 {
425 if (len != 26) {
426 printf("\n\t\tHT Capability IE len != expected 26 bytes, skipping parse\n");
427 return;
428 }
429 printf("\n");
430 print_ht_capability(data[0] | (data[1] << 8));
431 print_ampdu_length(data[2] & 3);
432 print_ampdu_spacing((data[2] >> 2) & 3);
433 print_ht_mcs(data + 3);
432434 }
433435
434436 static void print_capabilities(const uint8_t type, uint8_t len, const uint8_t *data)
485487 const char *name;
486488 void (*print)(const uint8_t type, uint8_t len, const uint8_t *data);
487489 uint8_t minlen, maxlen;
490 uint8_t flags;
488491 };
489492
490493 static void print_ie(const struct ie_print *p, const uint8_t type,
520523 }
521524
522525 static const struct ie_print ieprinters[] = {
523 [0] = { "SSID", print_ssid, 0, 32, },
524 [1] = { "Supported rates", print_supprates, 0, 255, },
525 [3] = { "DS Paramater set", print_ds, 1, 1, },
526 [0] = { "SSID", print_ssid, 0, 32, BIT(PRINT_SCAN) | BIT(PRINT_LINK), },
527 [1] = { "Supported rates", print_supprates, 0, 255, BIT(PRINT_SCAN), },
528 [3] = { "DS Parameter set", print_ds, 1, 1, BIT(PRINT_SCAN), },
526529 [5] = PRINT_IGN,
527 [7] = { "Country", print_country, 3, 255, },
528 [32] = { "Power constraint", print_powerconstraint, 1, 1, },
529 [42] = { "ERP", print_erp, 1, 255, },
530 [48] = { "RSN", print_rsn, 2, 255, },
531 [50] = { "Extended supported rates", print_supprates, 0, 255, },
532 [127] = { "Extended capabilities", print_capabilities, 0, 255, },
530 [7] = { "Country", print_country, 3, 255, BIT(PRINT_SCAN), },
531 [32] = { "Power constraint", print_powerconstraint, 1, 1, BIT(PRINT_SCAN), },
532 [42] = { "ERP", print_erp, 1, 255, BIT(PRINT_SCAN), },
533 [45] = { "HT capabilities", print_ht_capa, 1, 255, BIT(PRINT_SCAN), },
534 [48] = { "RSN", print_rsn, 2, 255, BIT(PRINT_SCAN), },
535 [50] = { "Extended supported rates", print_supprates, 0, 255, BIT(PRINT_SCAN), },
536 [127] = { "Extended capabilities", print_capabilities, 0, 255, BIT(PRINT_SCAN), },
533537 };
534538
535539 static void print_wifi_wpa(const uint8_t type, uint8_t len, const uint8_t *data)
536540 {
537541 print_rsn_ie("TKIP", "IEEE 802.1X", len, data);
542 }
543
544 static bool print_wifi_wmm_param(const uint8_t *data, uint8_t len)
545 {
546 int i;
547 static const char *aci_tbl[] = { "BE", "BK", "VI", "VO" };
548
549 if (len < 19)
550 goto invalid;
551
552 if (data[0] != 1) {
553 printf("Parameter: not version 1: ");
554 return false;
555 }
556
557 printf("\t * Parameter version 1");
558
559 data++;
560
561 if (data[0] & 0x80)
562 printf("\n\t\t * u-APSD");
563
564 data += 2;
565
566 for (i = 0; i < 4; i++) {
567 printf("\n\t\t * %s:", aci_tbl[(data[0] >> 5) & 3]);
568 if (data[4] & 0x10)
569 printf(" acm");
570 printf(" CW %d-%d", (1 << (data[1] & 0xf)) - 1,
571 (1 << (data[1] >> 4)) - 1);
572 printf(", AIFSN %d", data[0] & 0xf);
573 if (data[2] | data[3])
574 printf(", TXOP %d usec", (data[2] + (data[3] << 8)) * 32);
575 data += 4;
576 }
577
578 printf("\n");
579 return true;
580
581 invalid:
582 printf("invalid: ");
583 return false;
538584 }
539585
540586 static void print_wifi_wmm(const uint8_t type, uint8_t len, const uint8_t *data)
546592 printf(" information:");
547593 break;
548594 case 0x01:
549 printf(" parameter:");
595 if (print_wifi_wmm_param(data + 1, len - 1))
596 return;
550597 break;
551598 default:
552599 printf(" type %d:", data[0]);
553600 break;
554601 }
555602
556 for(i = 0; i < len - 1; i++)
557 printf(" %.02x", data[i + 1]);
603 for(i = 1; i < len; i++)
604 printf(" %.02x", data[i]);
558605 printf("\n");
559606 }
560607
587634 printf("\t * Model: %.*s\n", sublen, data + 4);
588635 break;
589636 case 0x1057: {
590 __u16 val = (data[4] << 8) | data[5];
637 __u8 val = data[4];
591638 tab_on_first(&first);
592 printf("\t * AP setup locked: 0x%.4x\n", val);
639 printf("\t * AP setup locked: 0x%.2x\n", val);
593640 break;
594641 }
595642 case 0x1008: {
637684 }
638685
639686 static const struct ie_print wifiprinters[] = {
640 [1] = { "WPA", print_wifi_wpa, 2, 255, },
641 [2] = { "WMM", print_wifi_wmm, 1, 255, },
642 [4] = { "WPS", print_wifi_wps, 0, 255, },
687 [1] = { "WPA", print_wifi_wpa, 2, 255, BIT(PRINT_SCAN), },
688 [2] = { "WMM", print_wifi_wmm, 1, 255, BIT(PRINT_SCAN), },
689 [4] = { "WPS", print_wifi_wps, 0, 255, BIT(PRINT_SCAN), },
643690 };
644691
645692 static void print_vendor(unsigned char len, unsigned char *data,
646 struct scan_params *params)
693 bool unknown, enum print_ie_type ptype)
647694 {
648695 int i;
649696
656703 }
657704
658705 if (len >= 4 && memcmp(data, wifi_oui, 3) == 0) {
659 if (data[3] < ARRAY_SIZE(wifiprinters) && wifiprinters[data[3]].name) {
706 if (data[3] < ARRAY_SIZE(wifiprinters) &&
707 wifiprinters[data[3]].name &&
708 wifiprinters[data[3]].flags & BIT(ptype)) {
660709 print_ie(&wifiprinters[data[3]], data[3], len - 4, data + 4);
661710 return;
662711 }
663 if (!params->unknown)
712 if (!unknown)
664713 return;
665714 printf("\tWiFi OUI %#.2x, data:", data[3]);
666715 for(i = 0; i < len - 4; i++)
669718 return;
670719 }
671720
672 if (!params->unknown)
721 if (!unknown)
673722 return;
674723
675724 printf("\tVendor specific: OUI %.2x:%.2x:%.2x, data:",
679728 printf("\n");
680729 }
681730
682 static void print_ies(unsigned char *ie, int ielen, struct scan_params *params)
731 void print_ies(unsigned char *ie, int ielen, bool unknown,
732 enum print_ie_type ptype)
683733 {
684734 while (ielen >= 2 && ielen >= ie[1]) {
685 if (ie[0] < ARRAY_SIZE(ieprinters) && ieprinters[ie[0]].name) {
735 if (ie[0] < ARRAY_SIZE(ieprinters) &&
736 ieprinters[ie[0]].name &&
737 ieprinters[ie[0]].flags & BIT(ptype)) {
686738 print_ie(&ieprinters[ie[0]], ie[0], ie[1], ie + 2);
687739 } else if (ie[0] == 221 /* vendor */) {
688 print_vendor(ie[1], ie + 2, params);
689 } else if (params->unknown) {
740 print_vendor(ie[1], ie + 2, unknown, ptype);
741 } else if (unknown) {
690742 int i;
691743
692744 printf("\tUnknown IE (%d):", ie[0]);
714766 [NL80211_BSS_INFORMATION_ELEMENTS] = { },
715767 [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },
716768 [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },
769 [NL80211_BSS_STATUS] = { .type = NLA_U32 },
770 [NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 },
717771 };
772 struct scan_params *params = arg;
718773
719774 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
720775 genlmsg_attrlen(gnlh, 0), NULL);
721776
722777 if (!tb[NL80211_ATTR_BSS]) {
723 fprintf(stderr, "bss info missing!");
778 fprintf(stderr, "bss info missing!\n");
724779 return NL_SKIP;
725780 }
726781 if (nla_parse_nested(bss, NL80211_BSS_MAX,
727782 tb[NL80211_ATTR_BSS],
728783 bss_policy)) {
729 fprintf(stderr, "failed to parse nested attributes!");
784 fprintf(stderr, "failed to parse nested attributes!\n");
730785 return NL_SKIP;
731786 }
732787
735790
736791 mac_addr_n2a(mac_addr, nla_data(bss[NL80211_BSS_BSSID]));
737792 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
738 printf("BSS %s (on %s)\n", mac_addr, dev);
793 printf("BSS %s (on %s)", mac_addr, dev);
794
795 if (bss[NL80211_BSS_STATUS]) {
796 switch (nla_get_u32(bss[NL80211_BSS_STATUS])) {
797 case NL80211_BSS_STATUS_AUTHENTICATED:
798 printf(" -- authenticated");
799 break;
800 case NL80211_BSS_STATUS_ASSOCIATED:
801 printf(" -- associated");
802 break;
803 case NL80211_BSS_STATUS_IBSS_JOINED:
804 printf(" -- joined");
805 break;
806 default:
807 printf(" -- unknown status: %d",
808 nla_get_u32(bss[NL80211_BSS_STATUS]));
809 break;
810 }
811 }
812 printf("\n");
739813
740814 if (bss[NL80211_BSS_TSF]) {
741815 unsigned long long tsf;
785859 unsigned char s = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]);
786860 printf("\tsignal: %d/100\n", s);
787861 }
862 if (bss[NL80211_BSS_SEEN_MS_AGO]) {
863 int age = nla_get_u32(bss[NL80211_BSS_SEEN_MS_AGO]);
864 printf("\tlast seen: %d ms ago\n", age);
865 }
788866 if (bss[NL80211_BSS_INFORMATION_ELEMENTS])
789867 print_ies(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]),
790868 nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]),
791 arg);
869 params->unknown, params->type);
792870
793871 return NL_SKIP;
794872 }
807885 if (argc == 1 && !strcmp(argv[0], "-u"))
808886 scan_params.unknown = true;
809887
888 scan_params.type = PRINT_SCAN;
889
810890 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_bss_handler,
811891 &scan_params);
812892 return 0;
813893 }
814 COMMAND(scan, dump, "[-u]",
815 NL80211_CMD_GET_SCAN, NLM_F_DUMP, CIB_NETDEV, handle_scan_dump,
816 "Dump the current scan results. If -u is specified, print unknown\n"
817 "data in scan results.");
818894
819895 static int handle_scan_combined(struct nl80211_state *state,
820896 struct nl_cb *cb,
893969 "Scan on the given frequencies and probe for the given SSIDs\n"
894970 "(or wildcard if not given) unless passive scanning is requested.\n"
895971 "If -u is specified print unknown data in the scan results.");
972 COMMAND(scan, dump, "[-u]",
973 NL80211_CMD_GET_SCAN, NLM_F_DUMP, CIB_NETDEV, handle_scan_dump,
974 "Dump the current scan results. If -u is specified, print unknown\n"
975 "data in scan results.");
976 COMMAND(scan, trigger, "[freq <freq>*] [ssid <ssid>*|passive]",
977 NL80211_CMD_TRIGGER_SCAN, 0, CIB_NETDEV, handle_scan,
978 "Trigger a scan on the given frequencies with probing for the given\n"
979 "SSIDs (or wildcard if not given) unless passive scanning is requested.");
0 #include "iw.h"
1
2 SECTION(get);
3 SECTION(set);
99
1010 #include "nl80211.h"
1111 #include "iw.h"
12
13 SECTION(station);
1214
1315 enum plink_state {
1416 LISTEN,
6466 */
6567
6668 if (!tb[NL80211_ATTR_STA_INFO]) {
67 fprintf(stderr, "sta stats missing!");
69 fprintf(stderr, "sta stats missing!\n");
6870 return NL_SKIP;
6971 }
7072 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
7173 tb[NL80211_ATTR_STA_INFO],
7274 stats_policy)) {
73 fprintf(stderr, "failed to parse nested attributes!");
75 fprintf(stderr, "failed to parse nested attributes!\n");
7476 return NL_SKIP;
7577 }
7678
7981 printf("Station %s (on %s)", mac_addr, dev);
8082
8183 if (sinfo[NL80211_STA_INFO_INACTIVE_TIME])
82 printf("\n\tinactive time:\t%d ms",
84 printf("\n\tinactive time:\t%u ms",
8385 nla_get_u32(sinfo[NL80211_STA_INFO_INACTIVE_TIME]));
8486 if (sinfo[NL80211_STA_INFO_RX_BYTES])
85 printf("\n\trx bytes:\t%d",
87 printf("\n\trx bytes:\t%u",
8688 nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]));
8789 if (sinfo[NL80211_STA_INFO_RX_PACKETS])
88 printf("\n\trx packets:\t%d",
90 printf("\n\trx packets:\t%u",
8991 nla_get_u32(sinfo[NL80211_STA_INFO_RX_PACKETS]));
9092 if (sinfo[NL80211_STA_INFO_TX_BYTES])
91 printf("\n\ttx bytes:\t%d",
93 printf("\n\ttx bytes:\t%u",
9294 nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]));
9395 if (sinfo[NL80211_STA_INFO_TX_PACKETS])
94 printf("\n\ttx packets:\t%d",
96 printf("\n\ttx packets:\t%u",
9597 nla_get_u32(sinfo[NL80211_STA_INFO_TX_PACKETS]));
9698 if (sinfo[NL80211_STA_INFO_SIGNAL])
9799 printf("\n\tsignal: \t%d dBm",
100102 if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
101103 if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
102104 sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
103 fprintf(stderr, "failed to parse nested rate attributes!");
105 fprintf(stderr, "failed to parse nested rate attributes!\n");
104106 } else {
105107 printf("\n\ttx bitrate:\t");
106108 if (rinfo[NL80211_RATE_INFO_BITRATE]) {
124126 printf("\n\tmesh plid:\t%d",
125127 nla_get_u16(sinfo[NL80211_STA_INFO_PLID]));
126128 if (sinfo[NL80211_STA_INFO_PLINK_STATE]) {
127 switch (nla_get_u16(sinfo[NL80211_STA_INFO_PLINK_STATE])) {
129 switch (nla_get_u8(sinfo[NL80211_STA_INFO_PLINK_STATE])) {
128130 case LISTEN:
129131 strcpy(state_name, "LISTEN");
130132 break;
193195 NL80211_CMD_DEL_STATION, 0, CIB_NETDEV, handle_station_get,
194196 "Remove the given station entry (use with caution!)");
195197
196 static int handle_station_set(struct nl80211_state *state,
198 static int handle_station_set_plink(struct nl80211_state *state,
197199 struct nl_cb *cb,
198200 struct nl_msg *msg,
199201 int argc, char **argv)
238240 return -ENOBUFS;
239241 }
240242 COMMAND(station, set, "<MAC address> plink_action <open|block>",
241 NL80211_CMD_SET_STATION, 0, CIB_NETDEV, handle_station_set,
243 NL80211_CMD_SET_STATION, 0, CIB_NETDEV, handle_station_set_plink,
242244 "Set mesh peer link action for this station (peer).");
245
246 static int handle_station_set_vlan(struct nl80211_state *state,
247 struct nl_cb *cb,
248 struct nl_msg *msg,
249 int argc, char **argv)
250 {
251 unsigned char mac_addr[ETH_ALEN];
252 unsigned long sta_vlan = 0;
253 char *err = NULL;
254
255 if (argc < 3)
256 return 1;
257
258 if (mac_addr_a2n(mac_addr, argv[0])) {
259 fprintf(stderr, "invalid mac address\n");
260 return 2;
261 }
262 argc--;
263 argv++;
264
265 if (strcmp("vlan", argv[0]) != 0)
266 return 1;
267 argc--;
268 argv++;
269
270 sta_vlan = strtoul(argv[0], &err, 0);
271 if (err && *err) {
272 fprintf(stderr, "invalid vlan id\n");
273 return 2;
274 }
275 argc--;
276 argv++;
277
278 if (argc)
279 return 1;
280
281 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
282 NLA_PUT_U32(msg, NL80211_ATTR_STA_VLAN, sta_vlan);
283
284 return 0;
285 nla_put_failure:
286 return -ENOBUFS;
287 }
288 COMMAND(station, set, "<MAC address> vlan <ifindex>",
289 NL80211_CMD_SET_STATION, 0, CIB_NETDEV, handle_station_set_vlan,
290 "Set an AP VLAN for this station.");
291
243292
244293 static int handle_station_dump(struct nl80211_state *state,
245294 struct nl_cb *cb,
0 #include <net/if.h>
1 #include <errno.h>
2 #include <string.h>
3
4 #include <netlink/genl/genl.h>
5 #include <netlink/genl/family.h>
6 #include <netlink/genl/ctrl.h>
7 #include <netlink/msg.h>
8 #include <netlink/attr.h>
9
10 #include "nl80211.h"
11 #include "iw.h"
12
13 SECTION(survey);
14
15 static int print_survey_handler(struct nl_msg *msg, void *arg)
16 {
17 struct nlattr *tb[NL80211_ATTR_MAX + 1];
18 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
19 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
20 char dev[20];
21
22 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
23 [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
24 [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },
25 };
26
27 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
28 genlmsg_attrlen(gnlh, 0), NULL);
29
30 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
31 printf("Survey data from %s\n", dev);
32
33 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
34 fprintf(stderr, "survey data missing!\n");
35 return NL_SKIP;
36 }
37
38 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,
39 tb[NL80211_ATTR_SURVEY_INFO],
40 survey_policy)) {
41 fprintf(stderr, "failed to parse nested attributes!\n");
42 return NL_SKIP;
43 }
44
45 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
46 printf("\tfrequency:\t%u MHz\n",
47 nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]));
48 if (sinfo[NL80211_SURVEY_INFO_NOISE])
49 printf("\tnoise:\t\t%d dBm\n",
50 (int8_t)nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]));
51 return NL_SKIP;
52 }
53
54 static int handle_survey_dump(struct nl80211_state *state,
55 struct nl_cb *cb,
56 struct nl_msg *msg,
57 int argc, char **argv)
58 {
59 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_survey_handler, NULL);
60 return 0;
61 }
62 COMMAND(survey, dump, NULL,
63 NL80211_CMD_GET_SURVEY, NLM_F_DUMP, CIB_NETDEV, handle_survey_dump,
64 "List all gathered channel survey data");
65
0 #include <ctype.h>
1 #include <netlink/attr.h>
2 #include <errno.h>
3 #include <stdbool.h>
04 #include "iw.h"
15 #include "nl80211.h"
26
3 int mac_addr_n2a(char *mac_addr, unsigned char *arg)
7 void mac_addr_n2a(char *mac_addr, unsigned char *arg)
48 {
59 int i, l;
610
1418 l += 3;
1519 }
1620 }
17 return 0;
1821 }
1922
2023 int mac_addr_a2n(unsigned char *mac_addr, char *arg)
6568 return modebuf;
6669 }
6770
71 static const char *commands[NL80211_CMD_MAX + 1] = {
72 "unspecified",
73 "get_wiphy",
74 "set_wiphy",
75 "new_wiphy",
76 "del_wiphy",
77 "get_interface",
78 "set_interface",
79 "new_interface",
80 "del_interface",
81 "get_key",
82 "set_key",
83 "new_key",
84 "del_key",
85 "get_beacon",
86 "set_beacon",
87 "new_beacon",
88 "del_beacon",
89 "get_station",
90 "set_station",
91 "new_station",
92 "del_station",
93 "get_mpath",
94 "set_mpath",
95 "new_mpath",
96 "del_mpath",
97 "set_bss",
98 "set_reg",
99 "reg_set_reg",
100 "get_mesh_params",
101 "set_mesh_params",
102 "set_mgmt_extra_ie",
103 "get_reg",
104 "get_scan",
105 "trigger_scan",
106 "new_scan_results",
107 "scan_aborted",
108 "reg_change",
109 "authenticate",
110 "associate",
111 "deauthenticate",
112 "disassociate",
113 "michael_mic_failure",
114 "reg_beacon_hint",
115 "join_ibss",
116 "leave_ibss",
117 "testmode",
118 "connect",
119 "roam",
120 "disconnect",
121 "set_wiphy_netns"
122 };
123
124 static char cmdbuf[100];
125
126 const char *command_name(enum nl80211_commands cmd)
127 {
128 if (cmd <= NL80211_CMD_MAX)
129 return commands[cmd];
130 sprintf(cmdbuf, "Unknown command (%d)", cmd);
131 return cmdbuf;
132 }
133
68134 int ieee80211_channel_to_frequency(int chan)
69135 {
70136 if (chan < 14)
88154 /* FIXME: dot11ChannelStartingFactor (802.11-2007 17.3.8.3.2) */
89155 return freq/5 - 1000;
90156 }
157
158 void print_ssid_escaped(const uint8_t len, const uint8_t *data)
159 {
160 int i;
161
162 for (i = 0; i < len; i++) {
163 if (isprint(data[i]))
164 printf("%c", data[i]);
165 else
166 printf("\\x%.2x", data[i]);
167 }
168 }
169
170 static int hex2num(char digit)
171 {
172 if (!isxdigit(digit))
173 return -1;
174 if (isdigit(digit))
175 return digit - '0';
176 return tolower(digit) - 'a' + 10;
177 }
178
179 static int hex2byte(char *hex)
180 {
181 int d1, d2;
182
183 d1 = hex2num(hex[0]);
184 if (d1 < 0)
185 return -1;
186 d2 = hex2num(hex[1]);
187 if (d2 < 0)
188 return -1;
189 return (d1 << 4) | d2;
190 }
191
192 static char *hex2bin(char *hex, char *buf)
193 {
194 char *result = buf;
195 int d;
196
197 while (hex[0]) {
198 d = hex2byte(hex);
199 if (d < 0)
200 return NULL;
201 buf[0] = d;
202 buf++;
203 hex += 2;
204 }
205
206 return result;
207 }
208
209 int parse_keys(struct nl_msg *msg, char **argv, int argc)
210 {
211 struct nlattr *keys;
212 int i = 0;
213 bool have_default = false;
214 char keybuf[13];
215
216 if (!argc)
217 return 1;
218
219 NLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY);
220
221 keys = nla_nest_start(msg, NL80211_ATTR_KEYS);
222 if (!keys)
223 return -ENOBUFS;
224
225 do {
226 char *arg = *argv;
227 int pos = 0, keylen;
228 struct nlattr *key = nla_nest_start(msg, ++i);
229 char *keydata;
230
231 if (!key)
232 return -ENOBUFS;
233
234 if (arg[pos] == 'd') {
235 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);
236 pos++;
237 if (arg[pos] == ':')
238 pos++;
239 have_default = true;
240 }
241
242 if (!isdigit(arg[pos]))
243 goto explain;
244 NLA_PUT_U8(msg, NL80211_KEY_IDX, arg[pos++] - '0');
245 if (arg[pos++] != ':')
246 goto explain;
247 keydata = arg + pos;
248 switch (strlen(keydata)) {
249 case 10:
250 keydata = hex2bin(keydata, keybuf);
251 case 5:
252 NLA_PUT_U32(msg, NL80211_KEY_CIPHER, 0x000FAC01);
253 keylen = 5;
254 break;
255 case 26:
256 keydata = hex2bin(keydata, keybuf);
257 case 13:
258 NLA_PUT_U32(msg, NL80211_KEY_CIPHER, 0x000FAC05);
259 keylen = 13;
260 break;
261 default:
262 goto explain;
263 }
264
265 if (!keydata)
266 goto explain;
267
268 NLA_PUT(msg, NL80211_KEY_DATA, keylen, keydata);
269
270 argv++;
271 argc--;
272
273 /* one key should be TX key */
274 if (!have_default && !argc)
275 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);
276
277 nla_nest_end(msg, key);
278 } while (argc);
279
280 nla_nest_end(msg, keys);
281
282 return 0;
283 nla_put_failure:
284 return -ENOBUFS;
285 explain:
286 fprintf(stderr, "key must be [d:]index:data where\n"
287 " 'd:' means default (transmit) key\n"
288 " 'index:' is a single digit (0-3)\n"
289 " 'data' must be 5 or 13 ascii chars\n"
290 " or 10 or 26 hex digits\n"
291 "for example: d:2:6162636465 is the same as d:2:abcde\n");
292 return 2;
293 }
294
295 static void print_mcs_index(const __u8 *mcs)
296 {
297 unsigned int mcs_bit, prev_bit = -2, prev_cont = 0;
298
299 for (mcs_bit = 0; mcs_bit <= 76; mcs_bit++) {
300 unsigned int mcs_octet = mcs_bit/8;
301 unsigned int MCS_RATE_BIT = 1 << mcs_bit % 8;
302 bool mcs_rate_idx_set;
303
304 mcs_rate_idx_set = !!(mcs[mcs_octet] & MCS_RATE_BIT);
305
306 if (!mcs_rate_idx_set)
307 continue;
308
309 if (prev_bit != mcs_bit - 1) {
310 if (prev_bit != -2)
311 printf("%d, ", prev_bit);
312 else
313 printf(" ");
314 printf("%d", mcs_bit);
315 prev_cont = 0;
316 } else if (!prev_cont) {
317 printf("-");
318 prev_cont = 1;
319 }
320
321 prev_bit = mcs_bit;
322 }
323
324 if (prev_cont)
325 printf("%d", prev_bit);
326 printf("\n");
327 }
328
329 /*
330 * There are only 4 possible values, we just use a case instead of computing it,
331 * but technically this can also be computed through the formula:
332 *
333 * Max AMPDU length = (2 ^ (13 + exponent)) - 1 bytes
334 */
335 static __u32 compute_ampdu_length(__u8 exponent)
336 {
337 switch (exponent) {
338 case 0: return 8191; /* (2 ^(13 + 0)) -1 */
339 case 1: return 16383; /* (2 ^(13 + 1)) -1 */
340 case 2: return 32767; /* (2 ^(13 + 2)) -1 */
341 case 3: return 65535; /* (2 ^(13 + 3)) -1 */
342 default: return 0;
343 }
344 }
345
346 static const char *print_ampdu_space(__u8 space)
347 {
348 switch (space) {
349 case 0: return "No restriction";
350 case 1: return "1/4 usec";
351 case 2: return "1/2 usec";
352 case 3: return "1 usec";
353 case 4: return "2 usec";
354 case 5: return "4 usec";
355 case 6: return "8 usec";
356 case 7: return "16 usec";
357 default:
358 return "BUG (spacing more than 3 bits!)";
359 }
360 }
361
362 void print_ampdu_length(__u8 exponent)
363 {
364 __u32 max_ampdu_length;
365
366 max_ampdu_length = compute_ampdu_length(exponent);
367
368 if (max_ampdu_length) {
369 printf("\t\tMaximum RX AMPDU length %d bytes (exponent: 0x0%02x)\n",
370 max_ampdu_length, exponent);
371 } else {
372 printf("\t\tMaximum RX AMPDU length: unrecognized bytes "
373 "(exponent: %d)\n", exponent);
374 }
375 }
376
377 void print_ampdu_spacing(__u8 spacing)
378 {
379 printf("\t\tMinimum RX AMPDU time spacing: %s (0x%02x)\n",
380 print_ampdu_space(spacing), spacing);
381 }
382
383 void print_ht_capability(__u16 cap)
384 {
385 #define PRINT_HT_CAP(_cond, _str) \
386 do { \
387 if (_cond) \
388 printf("\t\t\t" _str "\n"); \
389 } while (0)
390
391 printf("\t\tCapabilities: 0x%02x\n", cap);
392
393 PRINT_HT_CAP((cap & BIT(0)), "RX LDCP");
394 PRINT_HT_CAP((cap & BIT(1)), "HT20/HT40");
395 PRINT_HT_CAP(!(cap & BIT(1)), "HT20");
396
397 PRINT_HT_CAP(((cap >> 2) & 0x3) == 0, "Static SM Power Save");
398 PRINT_HT_CAP(((cap >> 2) & 0x3) == 1, "Dynamic SM Power Save");
399 PRINT_HT_CAP(((cap >> 2) & 0x3) == 3, "SM Power Save disabled");
400
401 PRINT_HT_CAP((cap & BIT(4)), "RX Greenfield");
402 PRINT_HT_CAP((cap & BIT(5)), "RX HT20 SGI");
403 PRINT_HT_CAP((cap & BIT(6)), "RX HT40 SGI");
404 PRINT_HT_CAP((cap & BIT(7)), "TX STBC");
405
406 PRINT_HT_CAP(((cap >> 8) & 0x3) == 0, "No RX STBC");
407 PRINT_HT_CAP(((cap >> 8) & 0x3) == 1, "RX STBC 1-stream");
408 PRINT_HT_CAP(((cap >> 8) & 0x3) == 2, "RX STBC 2-streams");
409 PRINT_HT_CAP(((cap >> 8) & 0x3) == 3, "RX STBC 3-streams");
410
411 PRINT_HT_CAP((cap & BIT(10)), "HT Delayed Block Ack");
412
413 PRINT_HT_CAP((cap & BIT(11)), "Max AMSDU length: 3839 bytes");
414 PRINT_HT_CAP(!(cap & BIT(11)), "Max AMSDU length: 7935 bytes");
415
416 /*
417 * For beacons and probe response this would mean the BSS
418 * does or does not allow the usage of DSSS/CCK HT40.
419 * Otherwise it means the STA does or does not use
420 * DSSS/CCK HT40.
421 */
422 PRINT_HT_CAP((cap & BIT(12)), "DSSS/CCK HT40");
423 PRINT_HT_CAP(!(cap & BIT(12)), "No DSSS/CCK HT40");
424
425 /* BIT(13) is reserved */
426
427 PRINT_HT_CAP((cap & BIT(14)), "40 MHz Intolerant");
428
429 PRINT_HT_CAP((cap & BIT(15)), "L-SIG TXOP protection");
430 #undef PRINT_HT_CAP
431 }
432
433 void print_ht_mcs(const __u8 *mcs)
434 {
435 /* As defined in 7.3.2.57.4 Supported MCS Set field */
436 unsigned int tx_max_num_spatial_streams, max_rx_supp_data_rate;
437 bool tx_mcs_set_defined, tx_mcs_set_equal, tx_unequal_modulation;
438
439 max_rx_supp_data_rate = ((mcs[10] >> 8) & ((mcs[11] & 0x3) << 8));
440 tx_mcs_set_defined = !!(mcs[12] & (1 << 0));
441 tx_mcs_set_equal = !(mcs[12] & (1 << 1));
442 tx_max_num_spatial_streams = ((mcs[12] >> 2) & 3) + 1;
443 tx_unequal_modulation = !!(mcs[12] & (1 << 4));
444
445 if (max_rx_supp_data_rate)
446 printf("\t\tHT Max RX data rate: %d Mbps\n", max_rx_supp_data_rate);
447 /* XXX: else see 9.6.0e.5.3 how to get this I think */
448
449 if (tx_mcs_set_defined) {
450 if (tx_mcs_set_equal) {
451 printf("\t\tHT TX/RX MCS rate indexes supported:");
452 print_mcs_index(mcs);
453 } else {
454 printf("\t\tHT RX MCS rate indexes supported:");
455 print_mcs_index(mcs);
456
457 if (tx_unequal_modulation)
458 printf("\t\tTX unequal modulation supported\n");
459 else
460 printf("\t\tTX unequal modulation not supported\n");
461
462 printf("\t\tHT TX Max spatial streams: %d\n",
463 tx_max_num_spatial_streams);
464
465 printf("\t\tHT TX MCS rate indexes supported may differ\n");
466 }
467 } else {
468 printf("\t\tHT RX MCS rate indexes supported:");
469 print_mcs_index(mcs);
470 printf("\t\tHT TX MCS rate indexes are undefined\n");
471 }
472 }
00 #!/bin/sh
11
2 VERSION="0.9.14"
2 VERSION="0.9.19"
33 OUT="$1"
4
5 echo '#include "iw.h"' > "$OUT"
46
57 if head=`git rev-parse --verify HEAD 2>/dev/null`; then
68 git update-index --refresh --unmerged > /dev/null
1012 # is correct...
1113 [ "${descr%%-*}" = "v$VERSION" ] || exit 2
1214
13 echo -n 'const char iw_version[] = "' > "$OUT"
1415 v="${descr#v}"
1516 if git diff-index --name-only HEAD | read dummy ; then
1617 v="$v"-dirty
1920 v="$VERSION"
2021 fi
2122
22 echo "const char iw_version[] = \"$v\";" > "$OUT"
23 echo "const char iw_version[] = \"$v\";" >> "$OUT"