8 #include <netlink/genl/genl.h>
9 #include <netlink/genl/family.h>
10 #include <netlink/genl/ctrl.h>
11 #include <netlink/msg.h>
12 #include <netlink/attr.h>
24 static char *dfs_state_name(enum nl80211_dfs_state state
)
27 case NL80211_DFS_USABLE
:
29 case NL80211_DFS_AVAILABLE
:
31 case NL80211_DFS_UNAVAILABLE
:
38 static int print_channels_handler(struct nl_msg
*msg
, void *arg
)
40 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
41 struct channels_ctx
*ctx
= arg
;
42 struct nlattr
*tb_msg
[NL80211_ATTR_MAX
+ 1];
43 struct nlattr
*tb_band
[NL80211_BAND_ATTR_MAX
+ 1];
44 struct nlattr
*tb_freq
[NL80211_FREQUENCY_ATTR_MAX
+ 1];
45 struct nlattr
*nl_band
;
46 struct nlattr
*nl_freq
;
47 int rem_band
, rem_freq
;
49 nla_parse(tb_msg
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0), genlmsg_attrlen(gnlh
, 0), NULL
);
51 if (tb_msg
[NL80211_ATTR_WIPHY_BANDS
]) {
52 nla_for_each_nested(nl_band
, tb_msg
[NL80211_ATTR_WIPHY_BANDS
], rem_band
) {
53 if (ctx
->last_band
!= nl_band
->nla_type
) {
54 printf("Band %d:\n", nl_band
->nla_type
+ 1);
55 ctx
->width_40
= false;
56 ctx
->width_80
= false;
57 ctx
->width_160
= false;
58 ctx
->last_band
= nl_band
->nla_type
;
61 nla_parse(tb_band
, NL80211_BAND_ATTR_MAX
, nla_data(nl_band
), nla_len(nl_band
), NULL
);
63 if (tb_band
[NL80211_BAND_ATTR_HT_CAPA
]) {
64 __u16 cap
= nla_get_u16(tb_band
[NL80211_BAND_ATTR_HT_CAPA
]);
70 if (tb_band
[NL80211_BAND_ATTR_VHT_CAPA
]) {
75 capa
= nla_get_u32(tb_band
[NL80211_BAND_ATTR_VHT_CAPA
]);
76 switch ((capa
>> 2) & 3) {
78 /* width_80p80 = true; */
81 ctx
->width_160
= true;
86 if (tb_band
[NL80211_BAND_ATTR_FREQS
]) {
87 nla_for_each_nested(nl_freq
, tb_band
[NL80211_BAND_ATTR_FREQS
], rem_freq
) {
90 nla_parse(tb_freq
, NL80211_FREQUENCY_ATTR_MAX
, nla_data(nl_freq
), nla_len(nl_freq
), NULL
);
92 if (!tb_freq
[NL80211_FREQUENCY_ATTR_FREQ
])
94 freq
= nla_get_u32(tb_freq
[NL80211_FREQUENCY_ATTR_FREQ
]);
95 printf("\t* %d MHz [%d] ", freq
, ieee80211_frequency_to_channel(freq
));
97 if (tb_freq
[NL80211_FREQUENCY_ATTR_DISABLED
]) {
98 printf("(disabled)\n");
103 if (tb_freq
[NL80211_FREQUENCY_ATTR_MAX_TX_POWER
])
104 printf("\t Maximum TX power: %.1f dBm\n", 0.01 * nla_get_u32(tb_freq
[NL80211_FREQUENCY_ATTR_MAX_TX_POWER
]));
106 /* If both flags are set assume an new kernel */
107 if (tb_freq
[NL80211_FREQUENCY_ATTR_NO_IR
] && tb_freq
[__NL80211_FREQUENCY_ATTR_NO_IBSS
]) {
108 printf("\t No IR\n");
109 } else if (tb_freq
[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN
]) {
110 printf("\t Passive scan\n");
111 } else if (tb_freq
[__NL80211_FREQUENCY_ATTR_NO_IBSS
]){
112 printf("\t No IBSS\n");
115 if (tb_freq
[NL80211_FREQUENCY_ATTR_RADAR
])
116 printf("\t Radar detection\n");
118 printf("\t Channel widths:");
119 if (!tb_freq
[NL80211_FREQUENCY_ATTR_NO_20MHZ
])
121 if (ctx
->width_40
&& !tb_freq
[NL80211_FREQUENCY_ATTR_NO_HT40_MINUS
])
123 if (ctx
->width_40
&& !tb_freq
[NL80211_FREQUENCY_ATTR_NO_HT40_PLUS
])
125 if (ctx
->width_80
&& !tb_freq
[NL80211_FREQUENCY_ATTR_NO_80MHZ
])
127 if (ctx
->width_160
&& !tb_freq
[NL80211_FREQUENCY_ATTR_NO_160MHZ
])
131 if (!tb_freq
[NL80211_FREQUENCY_ATTR_DISABLED
] && tb_freq
[NL80211_FREQUENCY_ATTR_DFS_STATE
]) {
132 enum nl80211_dfs_state state
= nla_get_u32(tb_freq
[NL80211_FREQUENCY_ATTR_DFS_STATE
]);
135 printf("\t DFS state: %s", dfs_state_name(state
));
136 if (tb_freq
[NL80211_FREQUENCY_ATTR_DFS_TIME
]) {
137 time
= nla_get_u32(tb_freq
[NL80211_FREQUENCY_ATTR_DFS_TIME
]);
138 printf(" (for %lu sec)", time
/ 1000);
141 if (tb_freq
[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME
])
142 printf("\t DFS CAC time: %u ms\n",
143 nla_get_u32(tb_freq
[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME
]));
153 static int handle_channels(struct nl80211_state
*state
, struct nl_msg
*msg
,
154 int argc
, char **argv
, enum id_input id
)
156 static struct channels_ctx ctx
= {
160 nla_put_flag(msg
, NL80211_ATTR_SPLIT_WIPHY_DUMP
);
161 nlmsg_hdr(msg
)->nlmsg_flags
|= NLM_F_DUMP
;
163 register_handler(print_channels_handler
, &ctx
);
167 TOPLEVEL(channels
, NULL
, NL80211_CMD_GET_WIPHY
, 0, CIB_PHY
, handle_channels
, "Show available channels.");
169 static int handle_name(struct nl80211_state
*state
,
171 int argc
, char **argv
,
177 NLA_PUT_STRING(msg
, NL80211_ATTR_WIPHY_NAME
, *argv
);
183 COMMAND(set
, name
, "<new name>", NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_name
,
184 "Rename this wireless device.");
186 static int handle_freq(struct nl80211_state
*state
, struct nl_msg
*msg
,
187 int argc
, char **argv
,
190 struct chandef chandef
;
193 res
= parse_freqchan(&chandef
, false, argc
, argv
, NULL
);
197 return put_chandef(msg
, &chandef
);
201 "<freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
202 "<control freq> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
203 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_freq
,
204 "Set frequency/channel the hardware is using, including HT\n"
207 "<freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
208 "<control freq> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
209 NL80211_CMD_SET_WIPHY
, 0, CIB_NETDEV
, handle_freq
, NULL
);
211 static int handle_chan(struct nl80211_state
*state
, struct nl_msg
*msg
,
212 int argc
, char **argv
,
215 struct chandef chandef
;
218 res
= parse_freqchan(&chandef
, true, argc
, argv
, NULL
);
222 return put_chandef(msg
, &chandef
);
224 COMMAND(set
, channel
, "<channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]",
225 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_chan
, NULL
);
226 COMMAND(set
, channel
, "<channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]",
227 NL80211_CMD_SET_WIPHY
, 0, CIB_NETDEV
, handle_chan
, NULL
);
229 static int handle_fragmentation(struct nl80211_state
*state
,
231 int argc
, char **argv
,
239 if (strcmp("off", argv
[0]) == 0)
246 frag
= strtoul(argv
[0], &end
, 10);
251 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_FRAG_THRESHOLD
, frag
);
257 COMMAND(set
, frag
, "<fragmentation threshold|off>",
258 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_fragmentation
,
259 "Set fragmentation threshold.");
261 static int handle_rts(struct nl80211_state
*state
,
263 int argc
, char **argv
,
271 if (strcmp("off", argv
[0]) == 0)
278 rts
= strtoul(argv
[0], &end
, 10);
283 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_RTS_THRESHOLD
, rts
);
289 COMMAND(set
, rts
, "<rts threshold|off>",
290 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_rts
,
291 "Set rts threshold.");
293 static int handle_retry(struct nl80211_state
*state
,
295 int argc
, char **argv
, enum id_input id
)
297 unsigned int retry_short
= 0, retry_long
= 0;
298 bool have_retry_s
= false, have_retry_l
= false;
304 } parser_state
= S_NONE
;
306 if (!argc
|| (argc
!= 2 && argc
!= 4))
309 for (i
= 0; i
< argc
; i
++) {
313 if (strcmp(argv
[i
], "short") == 0) {
316 parser_state
= S_SHORT
;
318 } else if (strcmp(argv
[i
], "long") == 0) {
321 parser_state
= S_LONG
;
324 tmpul
= strtoul(argv
[i
], &end
, 10);
327 if (!tmpul
|| tmpul
> 255)
329 switch (parser_state
) {
342 if (!have_retry_s
&& !have_retry_l
)
345 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_RETRY_SHORT
, retry_short
);
347 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_RETRY_LONG
, retry_long
);
353 COMMAND(set
, retry
, "[short <limit>] [long <limit>]",
354 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_retry
,
357 #ifndef NETNS_RUN_DIR
358 #define NETNS_RUN_DIR "/var/run/netns"
360 static int netns_get_fd(const char *name
)
362 char pathbuf
[MAXPATHLEN
];
363 const char *path
, *ptr
;
366 ptr
= strchr(name
, '/');
368 snprintf(pathbuf
, sizeof(pathbuf
), "%s/%s",
369 NETNS_RUN_DIR
, name
);
372 return open(path
, O_RDONLY
);
375 static int handle_netns(struct nl80211_state
*state
,
377 int argc
, char **argv
,
383 if (argc
< 1 || !*argv
[0])
387 NLA_PUT_U32(msg
, NL80211_ATTR_PID
,
388 strtoul(argv
[0], &end
, 10));
390 printf("Invalid parameter: pid(%s)\n", argv
[0]);
396 if (argc
!= 2 || strcmp(argv
[0], "name"))
399 if ((fd
= netns_get_fd(argv
[1])) >= 0) {
400 NLA_PUT_U32(msg
, NL80211_ATTR_NETNS_FD
, fd
);
403 printf("Invalid parameter: nsname(%s)\n", argv
[0]);
411 COMMAND(set
, netns
, "{ <pid> | name <nsname> }",
412 NL80211_CMD_SET_WIPHY_NETNS
, 0, CIB_PHY
, handle_netns
,
413 "Put this wireless device into a different network namespace:\n"
414 " <pid> - change network namespace by process id\n"
415 " <nsname> - change network namespace by name from "NETNS_RUN_DIR
"\n"
416 " or by absolute path (man ip-netns)\n");
418 static int handle_coverage(struct nl80211_state
*state
,
420 int argc
, char **argv
,
424 unsigned int coverage
;
431 coverage
= strtoul(argv
[0], &end
, 10);
438 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_COVERAGE_CLASS
, coverage
);
444 COMMAND(set
, coverage
, "<coverage class>",
445 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_coverage
,
446 "Set coverage class (1 for every 3 usec of air propagation time).\n"
447 "Valid values: 0 - 255.");
449 static int handle_distance(struct nl80211_state
*state
,
451 int argc
, char **argv
,
460 if (strcmp("auto", argv
[0]) == 0) {
461 NLA_PUT_FLAG(msg
, NL80211_ATTR_WIPHY_DYN_ACK
);
464 unsigned int distance
, coverage
;
466 distance
= strtoul(argv
[0], &end
, 10);
472 * Divide double the distance by the speed of light
473 * in m/usec (300) to get round-trip time in microseconds
474 * and then divide the result by three to get coverage class
475 * as specified in IEEE 802.11-2007 table 7-27.
476 * Values are rounded upwards.
478 coverage
= (distance
+ 449) / 450;
482 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_COVERAGE_CLASS
, coverage
);
489 COMMAND(set
, distance
, "<auto|distance>",
490 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_distance
,
491 "Enable ACK timeout estimation algorithm (dynack) or set appropriate\n"
492 "coverage class for given link distance in meters.\n"
493 "To disable dynack set valid value for coverage class.\n"
494 "Valid values: 0 - 114750");
496 static int handle_txpower(struct nl80211_state
*state
,
498 int argc
, char **argv
,
501 enum nl80211_tx_power_setting type
;
504 /* get the required args */
505 if (argc
!= 1 && argc
!= 2)
508 if (!strcmp(argv
[0], "auto"))
509 type
= NL80211_TX_POWER_AUTOMATIC
;
510 else if (!strcmp(argv
[0], "fixed"))
511 type
= NL80211_TX_POWER_FIXED
;
512 else if (!strcmp(argv
[0], "limit"))
513 type
= NL80211_TX_POWER_LIMITED
;
515 printf("Invalid parameter: %s\n", argv
[0]);
519 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_TX_POWER_SETTING
, type
);
521 if (type
!= NL80211_TX_POWER_AUTOMATIC
) {
524 printf("Missing TX power level argument.\n");
528 mbm
= strtol(argv
[1], &endptr
, 10);
531 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_TX_POWER_LEVEL
, mbm
);
532 } else if (argc
!= 1)
540 COMMAND(set
, txpower
, "<auto|fixed|limit> [<tx power in mBm>]",
541 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_txpower
,
542 "Specify transmit power level and setting type.");
543 COMMAND(set
, txpower
, "<auto|fixed|limit> [<tx power in mBm>]",
544 NL80211_CMD_SET_WIPHY
, 0, CIB_NETDEV
, handle_txpower
,
545 "Specify transmit power level and setting type.");
547 static int handle_antenna(struct nl80211_state
*state
,
549 int argc
, char **argv
,
553 uint32_t tx_ant
= 0, rx_ant
= 0;
555 if (argc
== 1 && strcmp(argv
[0], "all") == 0) {
558 } else if (argc
== 1) {
559 tx_ant
= rx_ant
= strtoul(argv
[0], &end
, 0);
563 else if (argc
== 2) {
564 tx_ant
= strtoul(argv
[0], &end
, 0);
567 rx_ant
= strtoul(argv
[1], &end
, 0);
573 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_ANTENNA_TX
, tx_ant
);
574 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_ANTENNA_RX
, rx_ant
);
581 COMMAND(set
, antenna
, "<bitmap> | all | <tx bitmap> <rx bitmap>",
582 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_antenna
,
583 "Set a bitmap of allowed antennas to use for TX and RX.\n"
584 "The driver may reject antenna configurations it cannot support.");