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>
18 static int handle_name(struct nl80211_state
*state
,
20 int argc
, char **argv
,
26 NLA_PUT_STRING(msg
, NL80211_ATTR_WIPHY_NAME
, *argv
);
32 COMMAND(set
, name
, "<new name>", NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_name
,
33 "Rename this wireless device.");
35 static int handle_freqs(struct nl_msg
*msg
, int argc
, char **argv
)
41 { .name
= "20", .val
= NL80211_CHAN_WIDTH_20
, },
42 { .name
= "40", .val
= NL80211_CHAN_WIDTH_40
, },
43 { .name
= "80", .val
= NL80211_CHAN_WIDTH_80
, },
44 { .name
= "80+80", .val
= NL80211_CHAN_WIDTH_80P80
, },
45 { .name
= "160", .val
= NL80211_CHAN_WIDTH_160
, },
48 int i
, bwval
= NL80211_CHAN_WIDTH_20_NOHT
;
54 for (i
= 0; i
< ARRAY_SIZE(bwmap
); i
++) {
55 if (strcasecmp(bwmap
[i
].name
, argv
[0]) == 0) {
61 if (bwval
== NL80211_CHAN_WIDTH_20_NOHT
)
64 NLA_PUT_U32(msg
, NL80211_ATTR_CHANNEL_WIDTH
, bwval
);
72 freq
= strtoul(argv
[1], &end
, 10);
75 NLA_PUT_U32(msg
, NL80211_ATTR_CENTER_FREQ1
, freq
);
83 freq
= strtoul(argv
[2], &end
, 10);
86 NLA_PUT_U32(msg
, NL80211_ATTR_CENTER_FREQ2
, freq
);
93 static int handle_freqchan(struct nl_msg
*msg
, bool chan
,
94 int argc
, char **argv
)
101 { .name
= "HT20", .val
= NL80211_CHAN_HT20
, },
102 { .name
= "HT40+", .val
= NL80211_CHAN_HT40PLUS
, },
103 { .name
= "HT40-", .val
= NL80211_CHAN_HT40MINUS
, },
105 unsigned int htval
= NL80211_CHAN_NO_HT
;
109 if (!argc
|| argc
> 4)
114 freq
= strtoul(argv
[0], &end
, 10);
119 enum nl80211_band band
;
120 band
= freq
<= 14 ? NL80211_BAND_2GHZ
: NL80211_BAND_5GHZ
;
121 freq
= ieee80211_channel_to_frequency(freq
, band
);
124 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_FREQ
, freq
);
127 return handle_freqs(msg
, argc
- 1, argv
+ 1);
128 } else if (argc
== 2) {
129 for (i
= 0; i
< ARRAY_SIZE(htmap
); i
++) {
130 if (strcasecmp(htmap
[i
].name
, argv
[1]) == 0) {
131 htval
= htmap
[i
].val
;
135 if (htval
== NL80211_CHAN_NO_HT
)
136 return handle_freqs(msg
, argc
- 1, argv
+ 1);
139 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_CHANNEL_TYPE
, htval
);
146 static int handle_freq(struct nl80211_state
*state
, struct nl_msg
*msg
,
147 int argc
, char **argv
,
150 return handle_freqchan(msg
, false, argc
, argv
);
152 COMMAND(set
, freq
, "<freq> [HT20|HT40+|HT40-]",
153 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_freq
,
154 "Set frequency/channel the hardware is using, including HT\n"
156 COMMAND(set
, freq
, "<freq> [HT20|HT40+|HT40-]\n"
157 "<control freq> [20|40|80|80+80|160] [<center freq 1>] [<center freq 2>]",
158 NL80211_CMD_SET_WIPHY
, 0, CIB_NETDEV
, handle_freq
, NULL
);
160 static int handle_chan(struct nl80211_state
*state
, struct nl_msg
*msg
,
161 int argc
, char **argv
,
164 return handle_freqchan(msg
, true, argc
, argv
);
166 COMMAND(set
, channel
, "<channel> [HT20|HT40+|HT40-]",
167 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_chan
, NULL
);
168 COMMAND(set
, channel
, "<channel> [HT20|HT40+|HT40-]",
169 NL80211_CMD_SET_WIPHY
, 0, CIB_NETDEV
, handle_chan
, NULL
);
171 static int handle_fragmentation(struct nl80211_state
*state
,
173 int argc
, char **argv
,
181 if (strcmp("off", argv
[0]) == 0)
188 frag
= strtoul(argv
[0], &end
, 10);
193 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_FRAG_THRESHOLD
, frag
);
199 COMMAND(set
, frag
, "<fragmentation threshold|off>",
200 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_fragmentation
,
201 "Set fragmentation threshold.");
203 static int handle_rts(struct nl80211_state
*state
,
205 int argc
, char **argv
,
213 if (strcmp("off", argv
[0]) == 0)
220 rts
= strtoul(argv
[0], &end
, 10);
225 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_RTS_THRESHOLD
, rts
);
231 COMMAND(set
, rts
, "<rts threshold|off>",
232 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_rts
,
233 "Set rts threshold.");
235 static int handle_retry(struct nl80211_state
*state
,
237 int argc
, char **argv
, enum id_input id
)
239 unsigned int retry_short
= 0, retry_long
= 0;
240 bool have_retry_s
= false, have_retry_l
= false;
246 } parser_state
= S_NONE
;
248 if (!argc
|| (argc
!= 2 && argc
!= 4))
251 for (i
= 0; i
< argc
; i
++) {
255 if (strcmp(argv
[i
], "short") == 0) {
258 parser_state
= S_SHORT
;
260 } else if (strcmp(argv
[i
], "long") == 0) {
263 parser_state
= S_LONG
;
266 tmpul
= strtoul(argv
[i
], &end
, 10);
269 if (!tmpul
|| tmpul
> 255)
271 switch (parser_state
) {
284 if (!have_retry_s
&& !have_retry_l
)
287 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_RETRY_SHORT
, retry_short
);
289 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_RETRY_LONG
, retry_long
);
295 COMMAND(set
, retry
, "[short <limit>] [long <limit>]",
296 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_retry
,
299 #ifndef NETNS_RUN_DIR
300 #define NETNS_RUN_DIR "/var/run/netns"
302 int netns_get_fd(const char *name
)
304 char pathbuf
[MAXPATHLEN
];
305 const char *path
, *ptr
;
308 ptr
= strchr(name
, '/');
310 snprintf(pathbuf
, sizeof(pathbuf
), "%s/%s",
311 NETNS_RUN_DIR
, name
);
314 return open(path
, O_RDONLY
);
317 static int handle_netns(struct nl80211_state
*state
,
319 int argc
, char **argv
,
325 if (argc
< 1 || !*argv
[0])
329 NLA_PUT_U32(msg
, NL80211_ATTR_PID
,
330 strtoul(argv
[0], &end
, 10));
332 printf("Invalid parameter: pid(%s)\n", argv
[0]);
338 if (argc
!= 2 || strcmp(argv
[0], "name"))
341 if ((fd
= netns_get_fd(argv
[1])) >= 0) {
342 NLA_PUT_U32(msg
, NL80211_ATTR_NETNS_FD
, fd
);
345 printf("Invalid parameter: nsname(%s)\n", argv
[0]);
353 COMMAND(set
, netns
, "{ <pid> | name <nsname> }",
354 NL80211_CMD_SET_WIPHY_NETNS
, 0, CIB_PHY
, handle_netns
,
355 "Put this wireless device into a different network namespace:\n"
356 " <pid> - change network namespace by process id\n"
357 " <nsname> - change network namespace by name from "NETNS_RUN_DIR
"\n"
358 " or by absolute path (man ip-netns)\n");
360 static int handle_coverage(struct nl80211_state
*state
,
362 int argc
, char **argv
,
366 unsigned int coverage
;
373 coverage
= strtoul(argv
[0], &end
, 10);
380 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_COVERAGE_CLASS
, coverage
);
386 COMMAND(set
, coverage
, "<coverage class>",
387 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_coverage
,
388 "Set coverage class (1 for every 3 usec of air propagation time).\n"
389 "Valid values: 0 - 255.");
391 static int handle_distance(struct nl80211_state
*state
,
393 int argc
, char **argv
,
402 if (strcmp("auto", argv
[0]) == 0) {
403 NLA_PUT_FLAG(msg
, NL80211_ATTR_WIPHY_DYN_ACK
);
406 unsigned int distance
, coverage
;
408 distance
= strtoul(argv
[0], &end
, 10);
414 * Divide double the distance by the speed of light
415 * in m/usec (300) to get round-trip time in microseconds
416 * and then divide the result by three to get coverage class
417 * as specified in IEEE 802.11-2007 table 7-27.
418 * Values are rounded upwards.
420 coverage
= (distance
+ 449) / 450;
424 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_COVERAGE_CLASS
, coverage
);
431 COMMAND(set
, distance
, "<auto|distance>",
432 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_distance
,
433 "Enable ACK timeout estimation algorithm (dynack) or set appropriate\n"
434 "coverage class for given link distance in meters.\n"
435 "To disable dynack set valid value for coverage class.\n"
436 "Valid values: 0 - 114750");
438 static int handle_txpower(struct nl80211_state
*state
,
440 int argc
, char **argv
,
443 enum nl80211_tx_power_setting type
;
446 /* get the required args */
447 if (argc
!= 1 && argc
!= 2)
450 if (!strcmp(argv
[0], "auto"))
451 type
= NL80211_TX_POWER_AUTOMATIC
;
452 else if (!strcmp(argv
[0], "fixed"))
453 type
= NL80211_TX_POWER_FIXED
;
454 else if (!strcmp(argv
[0], "limit"))
455 type
= NL80211_TX_POWER_LIMITED
;
457 printf("Invalid parameter: %s\n", argv
[0]);
461 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_TX_POWER_SETTING
, type
);
463 if (type
!= NL80211_TX_POWER_AUTOMATIC
) {
466 printf("Missing TX power level argument.\n");
470 mbm
= strtol(argv
[1], &endptr
, 10);
473 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_TX_POWER_LEVEL
, mbm
);
474 } else if (argc
!= 1)
482 COMMAND(set
, txpower
, "<auto|fixed|limit> [<tx power in mBm>]",
483 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_txpower
,
484 "Specify transmit power level and setting type.");
485 COMMAND(set
, txpower
, "<auto|fixed|limit> [<tx power in mBm>]",
486 NL80211_CMD_SET_WIPHY
, 0, CIB_NETDEV
, handle_txpower
,
487 "Specify transmit power level and setting type.");
489 static int handle_antenna(struct nl80211_state
*state
,
491 int argc
, char **argv
,
495 uint32_t tx_ant
= 0, rx_ant
= 0;
497 if (argc
== 1 && strcmp(argv
[0], "all") == 0) {
500 } else if (argc
== 1) {
501 tx_ant
= rx_ant
= strtoul(argv
[0], &end
, 0);
505 else if (argc
== 2) {
506 tx_ant
= strtoul(argv
[0], &end
, 0);
509 rx_ant
= strtoul(argv
[1], &end
, 0);
515 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_ANTENNA_TX
, tx_ant
);
516 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_ANTENNA_RX
, rx_ant
);
523 COMMAND(set
, antenna
, "<bitmap> | all | <tx bitmap> <rx bitmap>",
524 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_antenna
,
525 "Set a bitmap of allowed antennas to use for TX and RX.\n"
526 "The driver may reject antenna configurations it cannot support.");