blob: 271c9d9429eb96411e0b63b27d4f072a4c6ec4f8 [file] [log] [blame]
Johannes Berg379f8392008-12-08 12:53:58 +01001#include <stdbool.h>
Johannes Berg0f55e0b2008-09-16 17:40:48 +02002#include <errno.h>
Johannes Berg0f55e0b2008-09-16 17:40:48 +02003#include <net/if.h>
Johannes Bergd0260392010-09-22 11:33:28 +02004#include <strings.h>
Vadim Kochan91454b62015-02-14 09:33:12 +02005#include <sys/param.h>
6#include <sys/stat.h>
7#include <fcntl.h>
Johannes Berg0f55e0b2008-09-16 17:40:48 +02008
9#include <netlink/genl/genl.h>
10#include <netlink/genl/family.h>
11#include <netlink/genl/ctrl.h>
12#include <netlink/msg.h>
13#include <netlink/attr.h>
14
Johannes Bergf408e012008-09-18 19:32:11 +020015#include "nl80211.h"
Johannes Berg0f55e0b2008-09-16 17:40:48 +020016#include "iw.h"
17
Johannes Berg7c37a242009-04-08 13:13:28 +020018static int handle_name(struct nl80211_state *state,
19 struct nl_cb *cb,
Johannes Berg0f55e0b2008-09-16 17:40:48 +020020 struct nl_msg *msg,
Johannes Berg05514f92012-07-19 11:50:50 +020021 int argc, char **argv,
22 enum id_input id)
Johannes Berg0f55e0b2008-09-16 17:40:48 +020023{
Johannes Berg0f55e0b2008-09-16 17:40:48 +020024 if (argc != 1)
Johannes Berg5e75fd02008-09-16 18:13:12 +020025 return 1;
Johannes Berg0f55e0b2008-09-16 17:40:48 +020026
27 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, *argv);
28
Johannes Berg70391cc2008-09-16 18:35:06 +020029 return 0;
Johannes Berg0f55e0b2008-09-16 17:40:48 +020030 nla_put_failure:
Johannes Berg70391cc2008-09-16 18:35:06 +020031 return -ENOBUFS;
Johannes Berg0f55e0b2008-09-16 17:40:48 +020032}
Johannes Bergcea8fa12009-05-05 15:05:10 +020033COMMAND(set, name, "<new name>", NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_name,
34 "Rename this wireless device.");
Johannes Bergb822cda2008-12-08 12:43:42 +010035
Johannes Berg7c60bb72012-11-20 16:52:12 +010036static int handle_freqs(struct nl_msg *msg, int argc, char **argv)
37{
38 static const struct {
39 const char *name;
40 unsigned int val;
41 } bwmap[] = {
42 { .name = "20", .val = NL80211_CHAN_WIDTH_20, },
43 { .name = "40", .val = NL80211_CHAN_WIDTH_40, },
44 { .name = "80", .val = NL80211_CHAN_WIDTH_80, },
45 { .name = "80+80", .val = NL80211_CHAN_WIDTH_80P80, },
46 { .name = "160", .val = NL80211_CHAN_WIDTH_160, },
47 };
48 uint32_t freq;
49 int i, bwval = NL80211_CHAN_WIDTH_20_NOHT;
50 char *end;
51
52 if (argc < 1)
53 return 1;
54
55 for (i = 0; i < ARRAY_SIZE(bwmap); i++) {
56 if (strcasecmp(bwmap[i].name, argv[0]) == 0) {
57 bwval = bwmap[i].val;
58 break;
59 }
60 }
61
62 if (bwval == NL80211_CHAN_WIDTH_20_NOHT)
63 return 1;
64
65 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH, bwval);
66
67 if (argc == 1)
68 return 0;
69
70 /* center freq 1 */
71 if (!*argv[1])
72 return 1;
73 freq = strtoul(argv[1], &end, 10);
74 if (*end)
75 return 1;
76 NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ1, freq);
77
78 if (argc == 2)
79 return 0;
80
81 /* center freq 2 */
82 if (!*argv[2])
83 return 1;
84 freq = strtoul(argv[2], &end, 10);
85 if (*end)
86 return 1;
87 NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ2, freq);
88
89 return 0;
90 nla_put_failure:
91 return -ENOBUFS;
92}
93
Johannes Berg379f8392008-12-08 12:53:58 +010094static int handle_freqchan(struct nl_msg *msg, bool chan,
95 int argc, char **argv)
Johannes Bergb822cda2008-12-08 12:43:42 +010096{
Johannes Berge86b7e02010-04-01 18:49:21 +020097 char *end;
Johannes Bergb822cda2008-12-08 12:43:42 +010098 static const struct {
99 const char *name;
100 unsigned int val;
101 } htmap[] = {
Johannes Berg68632dc2008-12-12 22:40:45 +0100102 { .name = "HT20", .val = NL80211_CHAN_HT20, },
103 { .name = "HT40+", .val = NL80211_CHAN_HT40PLUS, },
104 { .name = "HT40-", .val = NL80211_CHAN_HT40MINUS, },
Johannes Bergb822cda2008-12-08 12:43:42 +0100105 };
Johannes Berg68632dc2008-12-12 22:40:45 +0100106 unsigned int htval = NL80211_CHAN_NO_HT;
Johannes Bergb822cda2008-12-08 12:43:42 +0100107 unsigned int freq;
108 int i;
109
Johannes Berg7c60bb72012-11-20 16:52:12 +0100110 if (!argc || argc > 4)
Johannes Bergb822cda2008-12-08 12:43:42 +0100111 return 1;
112
Johannes Berge86b7e02010-04-01 18:49:21 +0200113 if (!*argv[0])
114 return 1;
115 freq = strtoul(argv[0], &end, 10);
116 if (*end)
117 return 1;
118
Bruno Randolf58b46da2013-09-26 17:45:45 +0100119 if (chan) {
120 enum nl80211_band band;
121 band = freq <= 14 ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
122 freq = ieee80211_channel_to_frequency(freq, band);
123 }
Johannes Bergb822cda2008-12-08 12:43:42 +0100124
125 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
Johannes Berg7c60bb72012-11-20 16:52:12 +0100126
127 if (argc > 2) {
128 return handle_freqs(msg, argc - 1, argv + 1);
129 } else if (argc == 2) {
130 for (i = 0; i < ARRAY_SIZE(htmap); i++) {
131 if (strcasecmp(htmap[i].name, argv[1]) == 0) {
132 htval = htmap[i].val;
133 break;
134 }
135 }
136 if (htval == NL80211_CHAN_NO_HT)
137 return handle_freqs(msg, argc - 1, argv + 1);
138 }
139
Johannes Berg68632dc2008-12-12 22:40:45 +0100140 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, htval);
Johannes Bergb822cda2008-12-08 12:43:42 +0100141
142 return 0;
143 nla_put_failure:
144 return -ENOBUFS;
145}
Johannes Berg379f8392008-12-08 12:53:58 +0100146
Johannes Berg7c37a242009-04-08 13:13:28 +0200147static int handle_freq(struct nl80211_state *state,
148 struct nl_cb *cb, struct nl_msg *msg,
Johannes Berg05514f92012-07-19 11:50:50 +0200149 int argc, char **argv,
150 enum id_input id)
Johannes Berg379f8392008-12-08 12:53:58 +0100151{
152 return handle_freqchan(msg, false, argc, argv);
153}
Johannes Bergb822cda2008-12-08 12:43:42 +0100154COMMAND(set, freq, "<freq> [HT20|HT40+|HT40-]",
Johannes Berg00c448b2009-05-05 15:04:19 +0200155 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_freq,
156 "Set frequency/channel the hardware is using, including HT\n"
157 "configuration.");
Johannes Berg7c60bb72012-11-20 16:52:12 +0100158COMMAND(set, freq, "<freq> [HT20|HT40+|HT40-]\n"
159 "<control freq> [20|40|80|80+80|160] [<center freq 1>] [<center freq 2>]",
Johannes Berg01ae06f2009-05-05 14:48:16 +0200160 NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_freq, NULL);
Johannes Berg379f8392008-12-08 12:53:58 +0100161
Johannes Berg7c37a242009-04-08 13:13:28 +0200162static int handle_chan(struct nl80211_state *state,
163 struct nl_cb *cb, struct nl_msg *msg,
Johannes Berg05514f92012-07-19 11:50:50 +0200164 int argc, char **argv,
165 enum id_input id)
Johannes Berg379f8392008-12-08 12:53:58 +0100166{
167 return handle_freqchan(msg, true, argc, argv);
168}
169COMMAND(set, channel, "<channel> [HT20|HT40+|HT40-]",
Johannes Berg01ae06f2009-05-05 14:48:16 +0200170 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_chan, NULL);
Johannes Berg379f8392008-12-08 12:53:58 +0100171COMMAND(set, channel, "<channel> [HT20|HT40+|HT40-]",
Johannes Berg01ae06f2009-05-05 14:48:16 +0200172 NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_chan, NULL);
Johannes Berg625aa4a2009-08-11 11:26:42 +0200173
174static int handle_fragmentation(struct nl80211_state *state,
175 struct nl_cb *cb, struct nl_msg *msg,
Johannes Berg05514f92012-07-19 11:50:50 +0200176 int argc, char **argv,
177 enum id_input id)
Johannes Berg625aa4a2009-08-11 11:26:42 +0200178{
179 unsigned int frag;
180
181 if (argc != 1)
182 return 1;
183
184 if (strcmp("off", argv[0]) == 0)
185 frag = -1;
Johannes Berge86b7e02010-04-01 18:49:21 +0200186 else {
187 char *end;
188
189 if (!*argv[0])
190 return 1;
191 frag = strtoul(argv[0], &end, 10);
192 if (*end != '\0')
193 return 1;
194 }
Johannes Berg625aa4a2009-08-11 11:26:42 +0200195
196 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, frag);
197
198 return 0;
199 nla_put_failure:
200 return -ENOBUFS;
201}
202COMMAND(set, frag, "<fragmentation threshold|off>",
203 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_fragmentation,
204 "Set fragmentation threshold.");
205
206static int handle_rts(struct nl80211_state *state,
207 struct nl_cb *cb, struct nl_msg *msg,
Johannes Berg05514f92012-07-19 11:50:50 +0200208 int argc, char **argv,
209 enum id_input id)
Johannes Berg625aa4a2009-08-11 11:26:42 +0200210{
211 unsigned int rts;
212
213 if (argc != 1)
214 return 1;
215
216 if (strcmp("off", argv[0]) == 0)
217 rts = -1;
Johannes Berge86b7e02010-04-01 18:49:21 +0200218 else {
219 char *end;
220
221 if (!*argv[0])
222 return 1;
223 rts = strtoul(argv[0], &end, 10);
224 if (*end != '\0')
225 return 1;
226 }
Johannes Berg625aa4a2009-08-11 11:26:42 +0200227
228 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, rts);
229
230 return 0;
231 nla_put_failure:
232 return -ENOBUFS;
233}
234COMMAND(set, rts, "<rts threshold|off>",
235 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_rts,
236 "Set rts threshold.");
Johannes Berge960e062009-09-24 20:18:47 +0200237
Ujjal Royc993e6e2014-03-07 12:23:38 +0530238static int handle_retry(struct nl80211_state *state,
239 struct nl_cb *cb, struct nl_msg *msg,
240 int argc, char **argv, enum id_input id)
241{
242 unsigned int retry_short = 0, retry_long = 0;
243 bool have_retry_s = false, have_retry_l = false;
244 int i;
245 enum {
246 S_NONE,
247 S_SHORT,
248 S_LONG,
249 } parser_state = S_NONE;
250
251 if (!argc || (argc != 2 && argc != 4))
252 return 1;
253
254 for (i = 0; i < argc; i++) {
255 char *end;
256 unsigned int tmpul;
257
258 if (strcmp(argv[i], "short") == 0) {
259 if (have_retry_s)
260 return 1;
261 parser_state = S_SHORT;
262 have_retry_s = true;
263 } else if (strcmp(argv[i], "long") == 0) {
264 if (have_retry_l)
265 return 1;
266 parser_state = S_LONG;
267 have_retry_l = true;
268 } else {
269 tmpul = strtoul(argv[i], &end, 10);
270 if (*end != '\0')
271 return 1;
272 if (!tmpul || tmpul > 255)
273 return -EINVAL;
274 switch (parser_state) {
275 case S_SHORT:
276 retry_short = tmpul;
277 break;
278 case S_LONG:
279 retry_long = tmpul;
280 break;
281 default:
282 return 1;
283 }
284 }
285 }
286
287 if (!have_retry_s && !have_retry_l)
288 return 1;
289 if (have_retry_s)
290 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT, retry_short);
291 if (have_retry_l)
292 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_LONG, retry_long);
293
294 return 0;
295 nla_put_failure:
296 return -ENOBUFS;
297}
298COMMAND(set, retry, "[short <limit>] [long <limit>]",
299 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_retry,
300 "Set retry limit.");
301
Vadim Kochan91454b62015-02-14 09:33:12 +0200302#ifndef NETNS_RUN_DIR
303#define NETNS_RUN_DIR "/var/run/netns"
304#endif
305int netns_get_fd(const char *name)
306{
307 char pathbuf[MAXPATHLEN];
308 const char *path, *ptr;
309
310 path = name;
311 ptr = strchr(name, '/');
312 if (!ptr) {
313 snprintf(pathbuf, sizeof(pathbuf), "%s/%s",
314 NETNS_RUN_DIR, name );
315 path = pathbuf;
316 }
317 return open(path, O_RDONLY);
318}
319
Johannes Berge960e062009-09-24 20:18:47 +0200320static int handle_netns(struct nl80211_state *state,
321 struct nl_cb *cb,
322 struct nl_msg *msg,
Johannes Berg05514f92012-07-19 11:50:50 +0200323 int argc, char **argv,
324 enum id_input id)
Johannes Berge960e062009-09-24 20:18:47 +0200325{
326 char *end;
Vadim Kochan91454b62015-02-14 09:33:12 +0200327 int fd;
Johannes Berge960e062009-09-24 20:18:47 +0200328
Vadim Kochan91454b62015-02-14 09:33:12 +0200329 if (argc < 1 || !*argv[0])
Johannes Berge960e062009-09-24 20:18:47 +0200330 return 1;
331
Vadim Kochan91454b62015-02-14 09:33:12 +0200332 if (argc == 1) {
333 NLA_PUT_U32(msg, NL80211_ATTR_PID,
334 strtoul(argv[0], &end, 10));
335 if (*end != '\0') {
336 printf("Invalid parameter: pid(%s)\n", argv[0]);
337 return 1;
338 }
339 return 0;
340 }
341
342 if (argc != 2 || strcmp(argv[0], "name"))
Johannes Berge86b7e02010-04-01 18:49:21 +0200343 return 1;
344
Vadim Kochan91454b62015-02-14 09:33:12 +0200345 if ((fd = netns_get_fd(argv[1])) >= 0) {
346 NLA_PUT_U32(msg, NL80211_ATTR_NETNS_FD, fd);
347 return 0;
348 } else {
349 printf("Invalid parameter: nsname(%s)\n", argv[0]);
350 }
Johannes Berge960e062009-09-24 20:18:47 +0200351
Vadim Kochan91454b62015-02-14 09:33:12 +0200352 return 1;
Johannes Berge960e062009-09-24 20:18:47 +0200353
Johannes Berge960e062009-09-24 20:18:47 +0200354 nla_put_failure:
355 return -ENOBUFS;
356}
Vadim Kochan91454b62015-02-14 09:33:12 +0200357COMMAND(set, netns, "{ <pid> | name <nsname> }",
Johannes Berge960e062009-09-24 20:18:47 +0200358 NL80211_CMD_SET_WIPHY_NETNS, 0, CIB_PHY, handle_netns,
Vadim Kochan91454b62015-02-14 09:33:12 +0200359 "Put this wireless device into a different network namespace:\n"
360 " <pid> - change network namespace by process id\n"
361 " <nsname> - change network namespace by name from "NETNS_RUN_DIR"\n"
362 " or by absolute path (man ip-netns)\n");
Lukáš Turekb2f92dd2010-02-17 21:13:23 -0500363
364static int handle_coverage(struct nl80211_state *state,
365 struct nl_cb *cb,
366 struct nl_msg *msg,
Johannes Berg05514f92012-07-19 11:50:50 +0200367 int argc, char **argv,
368 enum id_input id)
Lukáš Turekb2f92dd2010-02-17 21:13:23 -0500369{
Johannes Berge86b7e02010-04-01 18:49:21 +0200370 char *end;
Lukáš Turekb2f92dd2010-02-17 21:13:23 -0500371 unsigned int coverage;
372
373 if (argc != 1)
374 return 1;
375
Johannes Berge86b7e02010-04-01 18:49:21 +0200376 if (!*argv[0])
377 return 1;
378 coverage = strtoul(argv[0], &end, 10);
Lukáš Turekb2f92dd2010-02-17 21:13:23 -0500379 if (coverage > 255)
380 return 1;
381
Johannes Berge86b7e02010-04-01 18:49:21 +0200382 if (*end)
383 return 1;
384
Lukáš Turekb2f92dd2010-02-17 21:13:23 -0500385 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, coverage);
386
387 return 0;
388 nla_put_failure:
389 return -ENOBUFS;
390}
391COMMAND(set, coverage, "<coverage class>",
392 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_coverage,
393 "Set coverage class (1 for every 3 usec of air propagation time).\n"
394 "Valid values: 0 - 255.");
395
396static int handle_distance(struct nl80211_state *state,
397 struct nl_cb *cb,
398 struct nl_msg *msg,
Johannes Berg05514f92012-07-19 11:50:50 +0200399 int argc, char **argv,
400 enum id_input id)
Lukáš Turekb2f92dd2010-02-17 21:13:23 -0500401{
Lukáš Turekb2f92dd2010-02-17 21:13:23 -0500402 if (argc != 1)
403 return 1;
404
Johannes Berge86b7e02010-04-01 18:49:21 +0200405 if (!*argv[0])
406 return 1;
407
Lorenzo Bianconie6421422014-09-07 19:32:20 +0200408 if (strcmp("auto", argv[0]) == 0) {
409 NLA_PUT_FLAG(msg, NL80211_ATTR_WIPHY_DYN_ACK);
410 } else {
411 char *end;
412 unsigned int distance, coverage;
Johannes Berge86b7e02010-04-01 18:49:21 +0200413
Lorenzo Bianconie6421422014-09-07 19:32:20 +0200414 distance = strtoul(argv[0], &end, 10);
Lukáš Turekb2f92dd2010-02-17 21:13:23 -0500415
Lorenzo Bianconie6421422014-09-07 19:32:20 +0200416 if (*end)
417 return 1;
Lukáš Turekb2f92dd2010-02-17 21:13:23 -0500418
Lorenzo Bianconie6421422014-09-07 19:32:20 +0200419 /*
420 * Divide double the distance by the speed of light
421 * in m/usec (300) to get round-trip time in microseconds
422 * and then divide the result by three to get coverage class
423 * as specified in IEEE 802.11-2007 table 7-27.
424 * Values are rounded upwards.
425 */
426 coverage = (distance + 449) / 450;
427 if (coverage > 255)
428 return 1;
429
430 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, coverage);
431 }
Lukáš Turekb2f92dd2010-02-17 21:13:23 -0500432
433 return 0;
434 nla_put_failure:
435 return -ENOBUFS;
436}
Lorenzo Bianconie6421422014-09-07 19:32:20 +0200437COMMAND(set, distance, "<auto|distance>",
Lukáš Turekb2f92dd2010-02-17 21:13:23 -0500438 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_distance,
Lorenzo Bianconie6421422014-09-07 19:32:20 +0200439 "Enable ACK timeout estimation algorithm (dynack) or set appropriate\n"
440 "coverage class for given link distance in meters.\n"
441 "To disable dynack set valid value for coverage class.\n"
Lukáš Turekb2f92dd2010-02-17 21:13:23 -0500442 "Valid values: 0 - 114750");
Juuso Oikarinena0b1f572010-06-23 12:12:57 +0300443
444static int handle_txpower(struct nl80211_state *state,
445 struct nl_cb *cb,
446 struct nl_msg *msg,
Johannes Berg05514f92012-07-19 11:50:50 +0200447 int argc, char **argv,
448 enum id_input id)
Juuso Oikarinena0b1f572010-06-23 12:12:57 +0300449{
450 enum nl80211_tx_power_setting type;
451 int mbm;
452
453 /* get the required args */
454 if (argc != 1 && argc != 2)
455 return 1;
456
457 if (!strcmp(argv[0], "auto"))
458 type = NL80211_TX_POWER_AUTOMATIC;
459 else if (!strcmp(argv[0], "fixed"))
460 type = NL80211_TX_POWER_FIXED;
461 else if (!strcmp(argv[0], "limit"))
462 type = NL80211_TX_POWER_LIMITED;
463 else {
464 printf("Invalid parameter: %s\n", argv[0]);
465 return 2;
466 }
467
468 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_TX_POWER_SETTING, type);
469
470 if (type != NL80211_TX_POWER_AUTOMATIC) {
Johannes Berg18e05612011-04-28 19:41:04 +0200471 char *endptr;
Juuso Oikarinena0b1f572010-06-23 12:12:57 +0300472 if (argc != 2) {
473 printf("Missing TX power level argument.\n");
474 return 2;
475 }
476
Johannes Berg18e05612011-04-28 19:41:04 +0200477 mbm = strtol(argv[1], &endptr, 10);
Felix Fietkau08ec4c62011-11-07 18:49:51 +0100478 if (*endptr)
Johannes Berg18e05612011-04-28 19:41:04 +0200479 return 2;
Juuso Oikarinena0b1f572010-06-23 12:12:57 +0300480 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL, mbm);
481 } else if (argc != 1)
482 return 1;
483
484 return 0;
485
486 nla_put_failure:
487 return -ENOBUFS;
488}
489COMMAND(set, txpower, "<auto|fixed|limit> [<tx power in mBm>]",
490 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_txpower,
491 "Specify transmit power level and setting type.");
492COMMAND(set, txpower, "<auto|fixed|limit> [<tx power in mBm>]",
493 NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_txpower,
494 "Specify transmit power level and setting type.");
Bruno Randolfafce7982010-12-22 10:54:39 +0900495
496static int handle_antenna(struct nl80211_state *state,
497 struct nl_cb *cb,
498 struct nl_msg *msg,
Johannes Berg05514f92012-07-19 11:50:50 +0200499 int argc, char **argv,
500 enum id_input id)
Bruno Randolfafce7982010-12-22 10:54:39 +0900501{
502 char *end;
503 uint32_t tx_ant = 0, rx_ant = 0;
504
505 if (argc == 1 && strcmp(argv[0], "all") == 0) {
506 tx_ant = 0xffffffff;
507 rx_ant = 0xffffffff;
508 } else if (argc == 1) {
509 tx_ant = rx_ant = strtoul(argv[0], &end, 0);
510 if (*end)
511 return 1;
512 }
513 else if (argc == 2) {
514 tx_ant = strtoul(argv[0], &end, 0);
515 if (*end)
516 return 1;
517 rx_ant = strtoul(argv[1], &end, 0);
518 if (*end)
519 return 1;
520 } else
521 return 1;
522
523 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_TX, tx_ant);
524 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_RX, rx_ant);
525
526 return 0;
527
528 nla_put_failure:
529 return -ENOBUFS;
530}
531COMMAND(set, antenna, "<bitmap> | all | <tx bitmap> <rx bitmap>",
532 NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_antenna,
533 "Set a bitmap of allowed antennas to use for TX and RX.\n"
534 "The driver may reject antenna configurations it cannot support.");