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
,
21 int argc
, char **argv
,
27 NLA_PUT_STRING(msg
, NL80211_ATTR_WIPHY_NAME
, *argv
);
33 COMMAND(set
, name
, "<new name>", NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_name
,
34 "Rename this wireless device.");
36 static int handle_freqs(struct nl_msg
*msg
, int argc
, char **argv
)
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
, },
49 int i
, bwval
= NL80211_CHAN_WIDTH_20_NOHT
;
55 for (i
= 0; i
< ARRAY_SIZE(bwmap
); i
++) {
56 if (strcasecmp(bwmap
[i
].name
, argv
[0]) == 0) {
62 if (bwval
== NL80211_CHAN_WIDTH_20_NOHT
)
65 NLA_PUT_U32(msg
, NL80211_ATTR_CHANNEL_WIDTH
, bwval
);
73 freq
= strtoul(argv
[1], &end
, 10);
76 NLA_PUT_U32(msg
, NL80211_ATTR_CENTER_FREQ1
, freq
);
84 freq
= strtoul(argv
[2], &end
, 10);
87 NLA_PUT_U32(msg
, NL80211_ATTR_CENTER_FREQ2
, freq
);
94 static int handle_freqchan(struct nl_msg
*msg
, bool chan
,
95 int argc
, char **argv
)
102 { .name
= "HT20", .val
= NL80211_CHAN_HT20
, },
103 { .name
= "HT40+", .val
= NL80211_CHAN_HT40PLUS
, },
104 { .name
= "HT40-", .val
= NL80211_CHAN_HT40MINUS
, },
106 unsigned int htval
= NL80211_CHAN_NO_HT
;
110 if (!argc
|| argc
> 4)
115 freq
= strtoul(argv
[0], &end
, 10);
120 enum nl80211_band band
;
121 band
= freq
<= 14 ? NL80211_BAND_2GHZ
: NL80211_BAND_5GHZ
;
122 freq
= ieee80211_channel_to_frequency(freq
, band
);
125 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_FREQ
, freq
);
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
;
136 if (htval
== NL80211_CHAN_NO_HT
)
137 return handle_freqs(msg
, argc
- 1, argv
+ 1);
140 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_CHANNEL_TYPE
, htval
);
147 static int handle_freq(struct nl80211_state
*state
,
148 struct nl_cb
*cb
, struct nl_msg
*msg
,
149 int argc
, char **argv
,
152 return handle_freqchan(msg
, false, argc
, argv
);
154 COMMAND(set
, freq
, "<freq> [HT20|HT40+|HT40-]",
155 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_freq
,
156 "Set frequency/channel the hardware is using, including HT\n"
158 COMMAND(set
, freq
, "<freq> [HT20|HT40+|HT40-]\n"
159 "<control freq> [20|40|80|80+80|160] [<center freq 1>] [<center freq 2>]",
160 NL80211_CMD_SET_WIPHY
, 0, CIB_NETDEV
, handle_freq
, NULL
);
162 static int handle_chan(struct nl80211_state
*state
,
163 struct nl_cb
*cb
, struct nl_msg
*msg
,
164 int argc
, char **argv
,
167 return handle_freqchan(msg
, true, argc
, argv
);
169 COMMAND(set
, channel
, "<channel> [HT20|HT40+|HT40-]",
170 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_chan
, NULL
);
171 COMMAND(set
, channel
, "<channel> [HT20|HT40+|HT40-]",
172 NL80211_CMD_SET_WIPHY
, 0, CIB_NETDEV
, handle_chan
, NULL
);
174 static int handle_fragmentation(struct nl80211_state
*state
,
175 struct nl_cb
*cb
, struct nl_msg
*msg
,
176 int argc
, char **argv
,
184 if (strcmp("off", argv
[0]) == 0)
191 frag
= strtoul(argv
[0], &end
, 10);
196 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_FRAG_THRESHOLD
, frag
);
202 COMMAND(set
, frag
, "<fragmentation threshold|off>",
203 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_fragmentation
,
204 "Set fragmentation threshold.");
206 static int handle_rts(struct nl80211_state
*state
,
207 struct nl_cb
*cb
, struct nl_msg
*msg
,
208 int argc
, char **argv
,
216 if (strcmp("off", argv
[0]) == 0)
223 rts
= strtoul(argv
[0], &end
, 10);
228 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_RTS_THRESHOLD
, rts
);
234 COMMAND(set
, rts
, "<rts threshold|off>",
235 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_rts
,
236 "Set rts threshold.");
238 static 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
)
242 unsigned int retry_short
= 0, retry_long
= 0;
243 bool have_retry_s
= false, have_retry_l
= false;
249 } parser_state
= S_NONE
;
251 if (!argc
|| (argc
!= 2 && argc
!= 4))
254 for (i
= 0; i
< argc
; i
++) {
258 if (strcmp(argv
[i
], "short") == 0) {
261 parser_state
= S_SHORT
;
263 } else if (strcmp(argv
[i
], "long") == 0) {
266 parser_state
= S_LONG
;
269 tmpul
= strtoul(argv
[i
], &end
, 10);
272 if (!tmpul
|| tmpul
> 255)
274 switch (parser_state
) {
287 if (!have_retry_s
&& !have_retry_l
)
290 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_RETRY_SHORT
, retry_short
);
292 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_RETRY_LONG
, retry_long
);
298 COMMAND(set
, retry
, "[short <limit>] [long <limit>]",
299 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_retry
,
302 #ifndef NETNS_RUN_DIR
303 #define NETNS_RUN_DIR "/var/run/netns"
305 int netns_get_fd(const char *name
)
307 char pathbuf
[MAXPATHLEN
];
308 const char *path
, *ptr
;
311 ptr
= strchr(name
, '/');
313 snprintf(pathbuf
, sizeof(pathbuf
), "%s/%s",
314 NETNS_RUN_DIR
, name
);
317 return open(path
, O_RDONLY
);
320 static int handle_netns(struct nl80211_state
*state
,
323 int argc
, char **argv
,
329 if (argc
< 1 || !*argv
[0])
333 NLA_PUT_U32(msg
, NL80211_ATTR_PID
,
334 strtoul(argv
[0], &end
, 10));
336 printf("Invalid parameter: pid(%s)\n", argv
[0]);
342 if (argc
!= 2 || strcmp(argv
[0], "name"))
345 if ((fd
= netns_get_fd(argv
[1])) >= 0) {
346 NLA_PUT_U32(msg
, NL80211_ATTR_NETNS_FD
, fd
);
349 printf("Invalid parameter: nsname(%s)\n", argv
[0]);
357 COMMAND(set
, netns
, "{ <pid> | name <nsname> }",
358 NL80211_CMD_SET_WIPHY_NETNS
, 0, CIB_PHY
, handle_netns
,
359 "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");
364 static int handle_coverage(struct nl80211_state
*state
,
367 int argc
, char **argv
,
371 unsigned int coverage
;
378 coverage
= strtoul(argv
[0], &end
, 10);
385 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_COVERAGE_CLASS
, coverage
);
391 COMMAND(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.");
396 static int handle_distance(struct nl80211_state
*state
,
399 int argc
, char **argv
,
408 if (strcmp("auto", argv
[0]) == 0) {
409 NLA_PUT_FLAG(msg
, NL80211_ATTR_WIPHY_DYN_ACK
);
412 unsigned int distance
, coverage
;
414 distance
= strtoul(argv
[0], &end
, 10);
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.
426 coverage
= (distance
+ 449) / 450;
430 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_COVERAGE_CLASS
, coverage
);
437 COMMAND(set
, distance
, "<auto|distance>",
438 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_distance
,
439 "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"
442 "Valid values: 0 - 114750");
444 static int handle_txpower(struct nl80211_state
*state
,
447 int argc
, char **argv
,
450 enum nl80211_tx_power_setting type
;
453 /* get the required args */
454 if (argc
!= 1 && argc
!= 2)
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
;
464 printf("Invalid parameter: %s\n", argv
[0]);
468 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_TX_POWER_SETTING
, type
);
470 if (type
!= NL80211_TX_POWER_AUTOMATIC
) {
473 printf("Missing TX power level argument.\n");
477 mbm
= strtol(argv
[1], &endptr
, 10);
480 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_TX_POWER_LEVEL
, mbm
);
481 } else if (argc
!= 1)
489 COMMAND(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.");
492 COMMAND(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.");
496 static int handle_antenna(struct nl80211_state
*state
,
499 int argc
, char **argv
,
503 uint32_t tx_ant
= 0, rx_ant
= 0;
505 if (argc
== 1 && strcmp(argv
[0], "all") == 0) {
508 } else if (argc
== 1) {
509 tx_ant
= rx_ant
= strtoul(argv
[0], &end
, 0);
513 else if (argc
== 2) {
514 tx_ant
= strtoul(argv
[0], &end
, 0);
517 rx_ant
= strtoul(argv
[1], &end
, 0);
523 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_ANTENNA_TX
, tx_ant
);
524 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_ANTENNA_RX
, rx_ant
);
531 COMMAND(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.");