]> git.ipfire.org Git - thirdparty/iw.git/blame - util.c
update nl80211.h
[thirdparty/iw.git] / util.c
CommitLineData
748f8489 1#include <ctype.h>
51e9bd80
JB
2#include <netlink/attr.h>
3#include <errno.h>
4#include <stdbool.h>
3d1e8704 5#include "iw.h"
f5f7b1d0 6#include "nl80211.h"
3d1e8704 7
7f87d3cf 8void mac_addr_n2a(char *mac_addr, const unsigned char *arg)
3d1e8704 9{
53e5ce7a 10 int i, l;
3d1e8704
LCC
11
12 l = 0;
13 for (i = 0; i < ETH_ALEN ; i++) {
14 if (i == 0) {
53e5ce7a 15 sprintf(mac_addr+l, "%02x", arg[i]);
3d1e8704
LCC
16 l += 2;
17 } else {
53e5ce7a 18 sprintf(mac_addr+l, ":%02x", arg[i]);
3d1e8704
LCC
19 l += 3;
20 }
21 }
3d1e8704
LCC
22}
23
24int mac_addr_a2n(unsigned char *mac_addr, char *arg)
25{
26 int i;
27
28 for (i = 0; i < ETH_ALEN ; i++) {
29 int temp;
30 char *cp = strchr(arg, ':');
31 if (cp) {
32 *cp = 0;
33 cp++;
34 }
35 if (sscanf(arg, "%x", &temp) != 1)
36 return -1;
37 if (temp < 0 || temp > 255)
38 return -1;
39
40 mac_addr[i] = temp;
41 if (!cp)
42 break;
43 arg = cp;
44 }
45 if (i < ETH_ALEN - 1)
46 return -1;
47
48 return 0;
49}
541ef425 50
3ff24563
JB
51int parse_hex_mask(char *hexmask, unsigned char **result, size_t *result_len,
52 unsigned char **mask)
236d4191 53{
3ff24563
JB
54 size_t len = strlen(hexmask) / 2;
55 unsigned char *result_val;
56 unsigned char *result_mask = NULL;
57
236d4191
JB
58 int pos = 0;
59
3ff24563 60 *result_len = 0;
236d4191 61
3ff24563
JB
62 result_val = calloc(len + 2, 1);
63 if (!result_val)
64 goto error;
65 *result = result_val;
66 if (mask) {
67 result_mask = calloc(DIV_ROUND_UP(len, 8) + 2, 1);
68 if (!result_mask)
69 goto error;
70 *mask = result_mask;
71 }
236d4191
JB
72
73 while (1) {
3ff24563 74 char *cp = strchr(hexmask, ':');
236d4191
JB
75 if (cp) {
76 *cp = 0;
77 cp++;
78 }
236d4191 79
3ff24563
JB
80 if (result_mask && (strcmp(hexmask, "-") == 0 ||
81 strcmp(hexmask, "xx") == 0 ||
82 strcmp(hexmask, "--") == 0)) {
83 /* skip this byte and leave mask bit unset */
84 } else {
85 int temp, mask_pos;
86 char *end;
87
88 temp = strtoul(hexmask, &end, 16);
89 if (*end)
90 goto error;
91 if (temp < 0 || temp > 255)
92 goto error;
93 result_val[pos] = temp;
94
95 mask_pos = pos / 8;
96 if (result_mask)
97 result_mask[mask_pos] |= 1 << (pos % 8);
98 }
99
100 (*result_len)++;
101 pos++;
236d4191 102
236d4191
JB
103 if (!cp)
104 break;
3ff24563 105 hexmask = cp;
236d4191
JB
106 }
107
3ff24563 108 return 0;
236d4191 109 error:
3ff24563
JB
110 free(result_val);
111 free(result_mask);
112 return -1;
113}
114
115unsigned char *parse_hex(char *hex, size_t *outlen)
116{
117 unsigned char *result;
118
119 if (parse_hex_mask(hex, &result, outlen, NULL))
120 return NULL;
121 return result;
236d4191
JB
122}
123
541ef425
JB
124static const char *ifmodes[NL80211_IFTYPE_MAX + 1] = {
125 "unspecified",
126 "IBSS",
34e78ed0 127 "managed",
541ef425 128 "AP",
34e78ed0 129 "AP/VLAN",
541ef425 130 "WDS",
34e78ed0 131 "monitor",
a4464243
JB
132 "mesh point",
133 "P2P-client",
134 "P2P-GO",
add40bbd 135 "P2P-device",
3955e524 136 "outside context of a BSS",
ed9b77ec 137 "NAN",
541ef425
JB
138};
139
140static char modebuf[100];
141
142const char *iftype_name(enum nl80211_iftype iftype)
143{
a66b3a35 144 if (iftype <= NL80211_IFTYPE_MAX && ifmodes[iftype])
541ef425
JB
145 return ifmodes[iftype];
146 sprintf(modebuf, "Unknown mode (%d)", iftype);
147 return modebuf;
148}
379f8397 149
9990c1e9 150static const char *commands[NL80211_CMD_MAX + 1] = {
dc1f3fe8 151#include "nl80211-commands.inc"
9990c1e9
MH
152};
153
154static char cmdbuf[100];
155
156const char *command_name(enum nl80211_commands cmd)
157{
73780397 158 if (cmd <= NL80211_CMD_MAX && commands[cmd])
9990c1e9
MH
159 return commands[cmd];
160 sprintf(cmdbuf, "Unknown command (%d)", cmd);
161 return cmdbuf;
162}
163
58b46da2 164int ieee80211_channel_to_frequency(int chan, enum nl80211_band band)
379f8397 165{
58b46da2
BR
166 /* see 802.11 17.3.8.3.2 and Annex J
167 * there are overlapping channel numbers in 5GHz and 2GHz bands */
168 if (chan <= 0)
169 return 0; /* not supported */
170 switch (band) {
171 case NL80211_BAND_2GHZ:
172 if (chan == 14)
173 return 2484;
174 else if (chan < 14)
175 return 2407 + chan * 5;
176 break;
177 case NL80211_BAND_5GHZ:
178 if (chan >= 182 && chan <= 196)
179 return 4000 + chan * 5;
180 else
181 return 5000 + chan * 5;
182 break;
43789196 183 case NL80211_BAND_6GHZ:
b12fc8a8
PKC
184 /* see 802.11ax D6.1 27.3.23.2 */
185 if (chan == 2)
186 return 5935;
43789196 187 if (chan <= 253)
b12fc8a8 188 return 5950 + chan * 5;
43789196 189 break;
58b46da2 190 case NL80211_BAND_60GHZ:
b12fc8a8 191 if (chan < 7)
58b46da2
BR
192 return 56160 + chan * 2160;
193 break;
194 default:
195 ;
196 }
197 return 0; /* not supported */
379f8397
JB
198}
199
200int ieee80211_frequency_to_channel(int freq)
201{
f2d9f5b5
GI
202 if (freq < 1000)
203 return 0;
58b46da2 204 /* see 802.11-2007 17.3.8.3.2 and Annex J */
379f8397
JB
205 if (freq == 2484)
206 return 14;
b12fc8a8
PKC
207 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
208 else if (freq == 5935)
209 return 2;
58b46da2 210 else if (freq < 2484)
379f8397 211 return (freq - 2407) / 5;
58b46da2
BR
212 else if (freq >= 4910 && freq <= 4980)
213 return (freq - 4000) / 5;
b12fc8a8 214 else if (freq < 5950)
58b46da2 215 return (freq - 5000) / 5;
43789196 216 else if (freq <= 45000) /* DMG band lower limit */
b12fc8a8
PKC
217 /* see 802.11ax D6.1 27.3.23.2 */
218 return (freq - 5950) / 5;
43789196 219 else if (freq >= 58320 && freq <= 70200)
d56e86bc 220 return (freq - 56160) / 2160;
58b46da2
BR
221 else
222 return 0;
379f8397 223}
748f8489
JB
224
225void print_ssid_escaped(const uint8_t len, const uint8_t *data)
226{
227 int i;
228
229 for (i = 0; i < len; i++) {
3f612733 230 if (isprint(data[i]) && data[i] != ' ' && data[i] != '\\')
748f8489 231 printf("%c", data[i]);
3f612733
JB
232 else if (data[i] == ' ' &&
233 (i != 0 && i != len -1))
234 printf(" ");
748f8489
JB
235 else
236 printf("\\x%.2x", data[i]);
237 }
238}
51e9bd80
JB
239
240static int hex2num(char digit)
241{
242 if (!isxdigit(digit))
243 return -1;
244 if (isdigit(digit))
245 return digit - '0';
246 return tolower(digit) - 'a' + 10;
247}
248
9ad3cc24 249static int hex2byte(const char *hex)
51e9bd80
JB
250{
251 int d1, d2;
252
253 d1 = hex2num(hex[0]);
254 if (d1 < 0)
255 return -1;
256 d2 = hex2num(hex[1]);
257 if (d2 < 0)
258 return -1;
259 return (d1 << 4) | d2;
260}
261
60b6c638 262char *hex2bin(const char *hex, char *buf)
51e9bd80
JB
263{
264 char *result = buf;
265 int d;
266
267 while (hex[0]) {
268 d = hex2byte(hex);
269 if (d < 0)
270 return NULL;
271 buf[0] = d;
272 buf++;
273 hex += 2;
274 }
275
276 return result;
277}
278
6c2a0121
EG
279static int parse_akm_suite(const char *cipher_str)
280{
281
282 if (!strcmp(cipher_str, "PSK"))
283 return 0x000FAC02;
284 if (!strcmp(cipher_str, "FT/PSK"))
285 return 0x000FAC03;
286 if (!strcmp(cipher_str, "PSK/SHA-256"))
287 return 0x000FAC06;
288 return -EINVAL;
289}
290
291static int parse_cipher_suite(const char *cipher_str)
292{
293
294 if (!strcmp(cipher_str, "TKIP"))
0ed91f54 295 return WLAN_CIPHER_SUITE_TKIP;
d7924705 296 if (!strcmp(cipher_str, "CCMP") || !strcmp(cipher_str, "CCMP-128"))
0ed91f54 297 return WLAN_CIPHER_SUITE_CCMP;
d7924705 298 if (!strcmp(cipher_str, "GCMP") || !strcmp(cipher_str, "GCMP-128"))
0ed91f54 299 return WLAN_CIPHER_SUITE_GCMP;
6c2a0121 300 if (!strcmp(cipher_str, "GCMP-256"))
0ed91f54 301 return WLAN_CIPHER_SUITE_GCMP_256;
6c2a0121 302 if (!strcmp(cipher_str, "CCMP-256"))
0ed91f54 303 return WLAN_CIPHER_SUITE_CCMP_256;
6c2a0121
EG
304 return -EINVAL;
305}
306
0e39f109 307int parse_keys(struct nl_msg *msg, char **argv[], int *argc)
51e9bd80
JB
308{
309 struct nlattr *keys;
310 int i = 0;
041581ce 311 bool have_default = false;
0e39f109 312 char *arg = **argv;
51e9bd80 313 char keybuf[13];
6c2a0121 314 int pos = 0;
51e9bd80 315
0e39f109 316 if (!*argc)
51e9bd80
JB
317 return 1;
318
6c2a0121
EG
319 if (!memcmp(&arg[pos], "psk", 3)) {
320 char psk_keybuf[32];
321 int cipher_suite, akm_suite;
322
0e39f109 323 if (*argc < 4)
6c2a0121
EG
324 goto explain;
325
326 pos+=3;
327 if (arg[pos] != ':')
328 goto explain;
329 pos++;
330
331 NLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, NL80211_WPA_VERSION_2);
332
333 if (strlen(&arg[pos]) != (sizeof(psk_keybuf) * 2) || !hex2bin(&arg[pos], psk_keybuf)) {
334 printf("Bad PSK\n");
335 return -EINVAL;
336 }
337
338 NLA_PUT(msg, NL80211_ATTR_PMK, 32, psk_keybuf);
339 NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, NL80211_AUTHTYPE_OPEN_SYSTEM);
340
0e39f109
EG
341 *argv += 1;
342 *argc -= 1;
343 arg = **argv;
6c2a0121
EG
344
345 akm_suite = parse_akm_suite(arg);
346 if (akm_suite < 0)
347 goto explain;
348
349 NLA_PUT_U32(msg, NL80211_ATTR_AKM_SUITES, akm_suite);
350
0e39f109
EG
351 *argv += 1;
352 *argc -= 1;
353 arg = **argv;
6c2a0121
EG
354
355 cipher_suite = parse_cipher_suite(arg);
356 if (cipher_suite < 0)
357 goto explain;
358
359 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, cipher_suite);
360
0e39f109
EG
361 *argv += 1;
362 *argc -= 1;
363 arg = **argv;
6c2a0121
EG
364
365 cipher_suite = parse_cipher_suite(arg);
366 if (cipher_suite < 0)
367 goto explain;
368
369 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher_suite);
370
d4f1ea11
IP
371 *argv += 1;
372 *argc -= 1;
6c2a0121
EG
373 return 0;
374 }
375
51e9bd80
JB
376 NLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY);
377
378 keys = nla_nest_start(msg, NL80211_ATTR_KEYS);
379 if (!keys)
380 return -ENOBUFS;
381
382 do {
6c2a0121 383 int keylen;
51e9bd80
JB
384 struct nlattr *key = nla_nest_start(msg, ++i);
385 char *keydata;
386
0e39f109 387 arg = **argv;
6c2a0121
EG
388 pos = 0;
389
51e9bd80
JB
390 if (!key)
391 return -ENOBUFS;
392
393 if (arg[pos] == 'd') {
394 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);
395 pos++;
396 if (arg[pos] == ':')
397 pos++;
041581ce 398 have_default = true;
51e9bd80
JB
399 }
400
401 if (!isdigit(arg[pos]))
402 goto explain;
403 NLA_PUT_U8(msg, NL80211_KEY_IDX, arg[pos++] - '0');
404 if (arg[pos++] != ':')
405 goto explain;
406 keydata = arg + pos;
407 switch (strlen(keydata)) {
408 case 10:
409 keydata = hex2bin(keydata, keybuf);
6ab936f0 410 /* fall through */
51e9bd80 411 case 5:
0ed91f54
JB
412 NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
413 WLAN_CIPHER_SUITE_WEP40);
51e9bd80
JB
414 keylen = 5;
415 break;
416 case 26:
417 keydata = hex2bin(keydata, keybuf);
6ab936f0 418 /* fall through */
51e9bd80 419 case 13:
0ed91f54
JB
420 NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
421 WLAN_CIPHER_SUITE_WEP104);
51e9bd80
JB
422 keylen = 13;
423 break;
424 default:
425 goto explain;
426 }
427
428 if (!keydata)
429 goto explain;
430
431 NLA_PUT(msg, NL80211_KEY_DATA, keylen, keydata);
432
0e39f109
EG
433 *argv += 1;
434 *argc -= 1;
041581ce
JB
435
436 /* one key should be TX key */
0e39f109 437 if (!have_default && !*argc)
041581ce
JB
438 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);
439
440 nla_nest_end(msg, key);
0e39f109 441 } while (*argc);
51e9bd80
JB
442
443 nla_nest_end(msg, keys);
444
445 return 0;
446 nla_put_failure:
447 return -ENOBUFS;
448 explain:
449 fprintf(stderr, "key must be [d:]index:data where\n"
450 " 'd:' means default (transmit) key\n"
451 " 'index:' is a single digit (0-3)\n"
452 " 'data' must be 5 or 13 ascii chars\n"
453 " or 10 or 26 hex digits\n"
6c2a0121
EG
454 "for example: d:2:6162636465 is the same as d:2:abcde\n"
455 "or psk:data <AKM Suite> <pairwise CIPHER> <groupwise CIPHER> where\n"
456 " 'data' is the PSK (output of wpa_passphrase and the CIPHER can be CCMP or GCMP\n"
457 "for example: psk:0123456789abcdef PSK CCMP CCMP\n"
458 "The allowed AKM suites are PSK, FT/PSK, PSK/SHA-256\n"
459 "The allowed Cipher suites are TKIP, CCMP, GCMP, GCMP-256, CCMP-256\n");
51e9bd80
JB
460 return 2;
461}
deb3501c 462
c37f6c64 463enum nl80211_chan_width str_to_bw(const char *str)
997c60fd
BB
464{
465 static const struct {
466 const char *name;
467 unsigned int val;
468 } bwmap[] = {
469 { .name = "5", .val = NL80211_CHAN_WIDTH_5, },
470 { .name = "10", .val = NL80211_CHAN_WIDTH_10, },
471 { .name = "20", .val = NL80211_CHAN_WIDTH_20, },
472 { .name = "40", .val = NL80211_CHAN_WIDTH_40, },
473 { .name = "80", .val = NL80211_CHAN_WIDTH_80, },
474 { .name = "80+80", .val = NL80211_CHAN_WIDTH_80P80, },
475 { .name = "160", .val = NL80211_CHAN_WIDTH_160, },
81d112f1 476 { .name = "320", .val = NL80211_CHAN_WIDTH_320, },
997c60fd 477 };
c37f6c64
JB
478 unsigned int i;
479
480 for (i = 0; i < ARRAY_SIZE(bwmap); i++) {
481 if (strcasecmp(bwmap[i].name, str) == 0)
482 return bwmap[i].val;
483 }
484
485 return NL80211_CHAN_WIDTH_20_NOHT;
486}
487
488static int parse_freqs(struct chandef *chandef, int argc, char **argv,
a32046bc 489 int *parsed, bool freq_in_khz)
c37f6c64 490{
997c60fd 491 uint32_t freq;
997c60fd 492 char *end;
4871fcf5 493 bool need_cf1 = false, need_cf2 = false;
997c60fd
BB
494
495 if (argc < 1)
496 return 0;
497
c37f6c64 498 chandef->width = str_to_bw(argv[0]);
997c60fd 499
4871fcf5
JB
500 switch (chandef->width) {
501 case NL80211_CHAN_WIDTH_20_NOHT:
502 /* First argument was not understood, give up gracefully. */
997c60fd 503 return 0;
4871fcf5
JB
504 case NL80211_CHAN_WIDTH_20:
505 case NL80211_CHAN_WIDTH_5:
506 case NL80211_CHAN_WIDTH_10:
507 break;
508 case NL80211_CHAN_WIDTH_80P80:
509 need_cf2 = true;
510 /* fall through */
511 case NL80211_CHAN_WIDTH_40:
512 case NL80211_CHAN_WIDTH_80:
513 case NL80211_CHAN_WIDTH_160:
5a71b722 514 case NL80211_CHAN_WIDTH_320:
4871fcf5
JB
515 need_cf1 = true;
516 break;
f718f11d
JB
517 case NL80211_CHAN_WIDTH_1:
518 case NL80211_CHAN_WIDTH_2:
519 case NL80211_CHAN_WIDTH_4:
520 case NL80211_CHAN_WIDTH_8:
521 case NL80211_CHAN_WIDTH_16:
522 /* can't happen yet */
523 break;
4871fcf5 524 }
997c60fd 525
c37f6c64
JB
526 *parsed += 1;
527
4871fcf5 528 if (!need_cf1)
997c60fd
BB
529 return 0;
530
4871fcf5
JB
531 if (argc < 2)
532 return 1;
533
997c60fd
BB
534 /* center freq 1 */
535 if (!*argv[1])
4871fcf5 536 return 1;
997c60fd
BB
537 freq = strtoul(argv[1], &end, 10);
538 if (*end)
4871fcf5 539 return 1;
997c60fd
BB
540 *parsed += 1;
541
a32046bc
GI
542 if (freq_in_khz) {
543 chandef->center_freq1 = freq / 1000;
544 chandef->center_freq1_offset = freq % 1000;
545 } else {
546 chandef->center_freq1 = freq;
547 chandef->center_freq1_offset = 0;
548 }
997c60fd 549
4871fcf5 550 if (!need_cf2)
997c60fd
BB
551 return 0;
552
4871fcf5
JB
553 if (argc < 3)
554 return 1;
555
997c60fd
BB
556 /* center freq 2 */
557 if (!*argv[2])
4871fcf5 558 return 1;
997c60fd
BB
559 freq = strtoul(argv[2], &end, 10);
560 if (*end)
4871fcf5 561 return 1;
a32046bc
GI
562
563 if (freq_in_khz)
564 chandef->center_freq2 = freq / 1000;
565 else
566 chandef->center_freq2 = freq;
997c60fd
BB
567
568 *parsed += 1;
569
570 return 0;
571}
572
573
574/**
575 * parse_freqchan - Parse frequency or channel definition
576 *
577 * @chandef: chandef structure to be filled in
578 * @chan: Boolean whether to parse a channel or frequency based specifier
579 * @argc: Number of arguments
580 * @argv: Array of string arguments
581 * @parsed: Pointer to return the number of used arguments, or NULL to error
582 * out if any argument is left unused.
a32046bc 583 * @freq_in_khz: Boolean whether to parse the frequency in kHz or default as MHz
997c60fd
BB
584 *
585 * The given chandef structure will be filled in from the command line
586 * arguments. argc/argv will be updated so that further arguments from the
587 * command line can be parsed.
588 *
4871fcf5
JB
589 * Note that despite the fact that the function knows how many center freqs
590 * are needed, there's an ambiguity if the next argument after this is an
591 * integer argument, since the valid channel width values are interpreted
592 * as such, rather than a following argument. This can be avoided by the
593 * user by giving "NOHT" instead.
997c60fd
BB
594 *
595 * The working specifier if chan is set are:
b6f2dac4 596 * <channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz|160MHz]
997c60fd
BB
597 *
598 * And if frequency is set:
997e5f13 599 * <freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz|160MHz|320MHz]
997c60fd
BB
600 * <control freq> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]
601 *
602 * If the mode/channel width is not given the NOHT is assumed.
603 *
604 * Return: Number of used arguments, zero or negative error number otherwise
605 */
606int parse_freqchan(struct chandef *chandef, bool chan, int argc, char **argv,
a32046bc 607 int *parsed, bool freq_in_khz)
997c60fd
BB
608{
609 char *end;
610 static const struct chanmode chanmode[] = {
611 { .name = "HT20",
612 .width = NL80211_CHAN_WIDTH_20,
613 .freq1_diff = 0,
614 .chantype = NL80211_CHAN_HT20 },
615 { .name = "HT40+",
616 .width = NL80211_CHAN_WIDTH_40,
617 .freq1_diff = 10,
618 .chantype = NL80211_CHAN_HT40PLUS },
619 { .name = "HT40-",
620 .width = NL80211_CHAN_WIDTH_40,
621 .freq1_diff = -10,
622 .chantype = NL80211_CHAN_HT40MINUS },
623 { .name = "NOHT",
624 .width = NL80211_CHAN_WIDTH_20_NOHT,
625 .freq1_diff = 0,
626 .chantype = NL80211_CHAN_NO_HT },
627 { .name = "5MHz",
628 .width = NL80211_CHAN_WIDTH_5,
629 .freq1_diff = 0,
630 .chantype = -1 },
631 { .name = "10MHz",
632 .width = NL80211_CHAN_WIDTH_10,
633 .freq1_diff = 0,
634 .chantype = -1 },
635 { .name = "80MHz",
636 .width = NL80211_CHAN_WIDTH_80,
637 .freq1_diff = 0,
638 .chantype = -1 },
b6f2dac4
T
639 { .name = "160MHz",
640 .width = NL80211_CHAN_WIDTH_160,
641 .freq1_diff = 0,
642 .chantype = -1 },
5a71b722
IP
643 { .name = "320MHz",
644 .width = NL80211_CHAN_WIDTH_320,
645 .freq1_diff = 0,
646 .chantype = -1 },
a32046bc
GI
647 { .name = "1MHz",
648 .width = NL80211_CHAN_WIDTH_1,
649 .freq1_diff = 0,
650 .chantype = -1 },
651 { .name = "2MHz",
652 .width = NL80211_CHAN_WIDTH_2,
653 .freq1_diff = 0,
654 .chantype = -1 },
655 { .name = "4MHz",
656 .width = NL80211_CHAN_WIDTH_4,
657 .freq1_diff = 0,
658 .chantype = -1 },
659 { .name = "8MHz",
660 .width = NL80211_CHAN_WIDTH_8,
661 .freq1_diff = 0,
662 .chantype = -1 },
663 { .name = "16MHz",
664 .width = NL80211_CHAN_WIDTH_16,
665 .freq1_diff = 0,
666 .chantype = -1 },
667
997c60fd
BB
668 };
669 const struct chanmode *chanmode_selected = NULL;
a32046bc 670 unsigned int freq, freq_offset = 0;
997c60fd
BB
671 unsigned int i;
672 int _parsed = 0;
673 int res = 0;
674
675 if (argc < 1)
676 return 1;
677
678 if (!argv[0])
679 goto out;
a32046bc 680
997c60fd 681 freq = strtoul(argv[0], &end, 10);
a32046bc
GI
682
683 if (freq_in_khz) {
684 freq_offset = freq % 1000;
685 freq = freq / 1000;
686 }
687
997c60fd
BB
688 if (*end) {
689 res = 1;
690 goto out;
691 }
692
693 _parsed += 1;
694
695 memset(chandef, 0, sizeof(struct chandef));
696
697 if (chan) {
698 enum nl80211_band band;
699
700 band = freq <= 14 ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
701 freq = ieee80211_channel_to_frequency(freq, band);
702 }
703 chandef->control_freq = freq;
a32046bc 704 chandef->control_freq_offset = freq_offset;
997c60fd
BB
705 /* Assume 20MHz NOHT channel for now. */
706 chandef->center_freq1 = freq;
a32046bc 707 chandef->center_freq1_offset = freq_offset;
997c60fd
BB
708
709 /* Try to parse HT mode definitions */
710 if (argc > 1) {
711 for (i = 0; i < ARRAY_SIZE(chanmode); i++) {
712 if (strcasecmp(chanmode[i].name, argv[1]) == 0) {
713 chanmode_selected = &chanmode[i];
714 _parsed += 1;
715 break;
716 }
717 }
718 }
719
a32046bc
GI
720 /* Set channel width's default value */
721 if (chandef->control_freq < 1000)
722 chandef->width = NL80211_CHAN_WIDTH_16;
723 else
724 chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
725
997c60fd
BB
726 /* channel mode given, use it and return. */
727 if (chanmode_selected) {
728 chandef->center_freq1 = get_cf1(chanmode_selected, freq);
a32046bc
GI
729
730 /* For non-S1G frequency */
731 if (chandef->center_freq1 > 1000)
732 chandef->center_freq1_offset = 0;
733
997c60fd
BB
734 chandef->width = chanmode_selected->width;
735 goto out;
736 }
737
738 /* This was a only a channel definition, nothing further may follow. */
739 if (chan)
740 goto out;
741
a32046bc 742 res = parse_freqs(chandef, argc - 1, argv + 1, &_parsed, freq_in_khz);
997c60fd
BB
743
744 out:
745 /* Error out if parsed is NULL. */
746 if (!parsed && _parsed != argc)
747 return 1;
748
749 if (parsed)
750 *parsed = _parsed;
751
752 return res;
753}
754
755int put_chandef(struct nl_msg *msg, struct chandef *chandef)
756{
757 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, chandef->control_freq);
a32046bc
GI
758 NLA_PUT_U32(msg,
759 NL80211_ATTR_WIPHY_FREQ_OFFSET,
760 chandef->control_freq_offset);
997c60fd
BB
761 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH, chandef->width);
762
763 switch (chandef->width) {
764 case NL80211_CHAN_WIDTH_20_NOHT:
765 NLA_PUT_U32(msg,
766 NL80211_ATTR_WIPHY_CHANNEL_TYPE,
767 NL80211_CHAN_NO_HT);
768 break;
769 case NL80211_CHAN_WIDTH_20:
770 NLA_PUT_U32(msg,
771 NL80211_ATTR_WIPHY_CHANNEL_TYPE,
772 NL80211_CHAN_HT20);
773 break;
774 case NL80211_CHAN_WIDTH_40:
775 if (chandef->control_freq > chandef->center_freq1)
776 NLA_PUT_U32(msg,
777 NL80211_ATTR_WIPHY_CHANNEL_TYPE,
778 NL80211_CHAN_HT40MINUS);
779 else
780 NLA_PUT_U32(msg,
781 NL80211_ATTR_WIPHY_CHANNEL_TYPE,
782 NL80211_CHAN_HT40PLUS);
783 break;
784 default:
785 break;
786 }
787
788 if (chandef->center_freq1)
789 NLA_PUT_U32(msg,
790 NL80211_ATTR_CENTER_FREQ1,
791 chandef->center_freq1);
792
a32046bc
GI
793 if (chandef->center_freq1_offset)
794 NLA_PUT_U32(msg,
795 NL80211_ATTR_CENTER_FREQ1_OFFSET,
796 chandef->center_freq1_offset);
797
997c60fd
BB
798 if (chandef->center_freq2)
799 NLA_PUT_U32(msg,
800 NL80211_ATTR_CENTER_FREQ2,
801 chandef->center_freq2);
802
803 return 0;
804
805 nla_put_failure:
806 return -ENOBUFS;
807}
808
7ddfb679 809static void print_mcs_index(const __u8 *mcs)
deb3501c 810{
9fea9777 811 int mcs_bit, prev_bit = -2, prev_cont = 0;
04953e90
JB
812
813 for (mcs_bit = 0; mcs_bit <= 76; mcs_bit++) {
814 unsigned int mcs_octet = mcs_bit/8;
815 unsigned int MCS_RATE_BIT = 1 << mcs_bit % 8;
816 bool mcs_rate_idx_set;
817
818 mcs_rate_idx_set = !!(mcs[mcs_octet] & MCS_RATE_BIT);
819
820 if (!mcs_rate_idx_set)
821 continue;
822
823 if (prev_bit != mcs_bit - 1) {
824 if (prev_bit != -2)
825 printf("%d, ", prev_bit);
826 else
827 printf(" ");
828 printf("%d", mcs_bit);
829 prev_cont = 0;
830 } else if (!prev_cont) {
831 printf("-");
832 prev_cont = 1;
833 }
834
835 prev_bit = mcs_bit;
836 }
deb3501c 837
04953e90
JB
838 if (prev_cont)
839 printf("%d", prev_bit);
840 printf("\n");
deb3501c 841}
0950993f
LR
842
843/*
844 * There are only 4 possible values, we just use a case instead of computing it,
845 * but technically this can also be computed through the formula:
846 *
847 * Max AMPDU length = (2 ^ (13 + exponent)) - 1 bytes
848 */
849static __u32 compute_ampdu_length(__u8 exponent)
850{
851 switch (exponent) {
852 case 0: return 8191; /* (2 ^(13 + 0)) -1 */
853 case 1: return 16383; /* (2 ^(13 + 1)) -1 */
854 case 2: return 32767; /* (2 ^(13 + 2)) -1 */
855 case 3: return 65535; /* (2 ^(13 + 3)) -1 */
856 default: return 0;
857 }
858}
859
860static const char *print_ampdu_space(__u8 space)
861{
862 switch (space) {
863 case 0: return "No restriction";
864 case 1: return "1/4 usec";
865 case 2: return "1/2 usec";
866 case 3: return "1 usec";
867 case 4: return "2 usec";
868 case 5: return "4 usec";
869 case 6: return "8 usec";
870 case 7: return "16 usec";
871 default:
7ae93cd5 872 return "BUG (spacing more than 3 bits!)";
0950993f
LR
873 }
874}
875
876void print_ampdu_length(__u8 exponent)
877{
04953e90 878 __u32 max_ampdu_length;
0950993f
LR
879
880 max_ampdu_length = compute_ampdu_length(exponent);
881
882 if (max_ampdu_length) {
883 printf("\t\tMaximum RX AMPDU length %d bytes (exponent: 0x0%02x)\n",
884 max_ampdu_length, exponent);
3f362f8b 885 } else {
0950993f
LR
886 printf("\t\tMaximum RX AMPDU length: unrecognized bytes "
887 "(exponent: %d)\n", exponent);
888 }
889}
890
891void print_ampdu_spacing(__u8 spacing)
892{
3f362f8b
NB
893 printf("\t\tMinimum RX AMPDU time spacing: %s (0x%02x)\n",
894 print_ampdu_space(spacing), spacing);
0950993f 895}
357c1a5d
LR
896
897void print_ht_capability(__u16 cap)
898{
899#define PRINT_HT_CAP(_cond, _str) \
900 do { \
901 if (_cond) \
902 printf("\t\t\t" _str "\n"); \
903 } while (0)
904
905 printf("\t\tCapabilities: 0x%02x\n", cap);
906
028c0de5 907 PRINT_HT_CAP((cap & BIT(0)), "RX LDPC");
357c1a5d
LR
908 PRINT_HT_CAP((cap & BIT(1)), "HT20/HT40");
909 PRINT_HT_CAP(!(cap & BIT(1)), "HT20");
910
911 PRINT_HT_CAP(((cap >> 2) & 0x3) == 0, "Static SM Power Save");
912 PRINT_HT_CAP(((cap >> 2) & 0x3) == 1, "Dynamic SM Power Save");
913 PRINT_HT_CAP(((cap >> 2) & 0x3) == 3, "SM Power Save disabled");
914
915 PRINT_HT_CAP((cap & BIT(4)), "RX Greenfield");
916 PRINT_HT_CAP((cap & BIT(5)), "RX HT20 SGI");
917 PRINT_HT_CAP((cap & BIT(6)), "RX HT40 SGI");
918 PRINT_HT_CAP((cap & BIT(7)), "TX STBC");
919
920 PRINT_HT_CAP(((cap >> 8) & 0x3) == 0, "No RX STBC");
921 PRINT_HT_CAP(((cap >> 8) & 0x3) == 1, "RX STBC 1-stream");
922 PRINT_HT_CAP(((cap >> 8) & 0x3) == 2, "RX STBC 2-streams");
923 PRINT_HT_CAP(((cap >> 8) & 0x3) == 3, "RX STBC 3-streams");
924
925 PRINT_HT_CAP((cap & BIT(10)), "HT Delayed Block Ack");
926
c79c7464
CL
927 PRINT_HT_CAP(!(cap & BIT(11)), "Max AMSDU length: 3839 bytes");
928 PRINT_HT_CAP((cap & BIT(11)), "Max AMSDU length: 7935 bytes");
357c1a5d
LR
929
930 /*
931 * For beacons and probe response this would mean the BSS
932 * does or does not allow the usage of DSSS/CCK HT40.
933 * Otherwise it means the STA does or does not use
934 * DSSS/CCK HT40.
935 */
936 PRINT_HT_CAP((cap & BIT(12)), "DSSS/CCK HT40");
937 PRINT_HT_CAP(!(cap & BIT(12)), "No DSSS/CCK HT40");
938
939 /* BIT(13) is reserved */
940
941 PRINT_HT_CAP((cap & BIT(14)), "40 MHz Intolerant");
942
943 PRINT_HT_CAP((cap & BIT(15)), "L-SIG TXOP protection");
944#undef PRINT_HT_CAP
945}
7ddfb679
JB
946
947void print_ht_mcs(const __u8 *mcs)
948{
949 /* As defined in 7.3.2.57.4 Supported MCS Set field */
950 unsigned int tx_max_num_spatial_streams, max_rx_supp_data_rate;
951 bool tx_mcs_set_defined, tx_mcs_set_equal, tx_unequal_modulation;
952
5ba6a62b 953 max_rx_supp_data_rate = (mcs[10] | ((mcs[11] & 0x3) << 8));
7ddfb679
JB
954 tx_mcs_set_defined = !!(mcs[12] & (1 << 0));
955 tx_mcs_set_equal = !(mcs[12] & (1 << 1));
956 tx_max_num_spatial_streams = ((mcs[12] >> 2) & 3) + 1;
957 tx_unequal_modulation = !!(mcs[12] & (1 << 4));
958
959 if (max_rx_supp_data_rate)
960 printf("\t\tHT Max RX data rate: %d Mbps\n", max_rx_supp_data_rate);
961 /* XXX: else see 9.6.0e.5.3 how to get this I think */
962
963 if (tx_mcs_set_defined) {
964 if (tx_mcs_set_equal) {
2a79feb0 965 printf("\t\tHT TX/RX MCS rate indexes supported:");
7ddfb679
JB
966 print_mcs_index(mcs);
967 } else {
968 printf("\t\tHT RX MCS rate indexes supported:");
969 print_mcs_index(mcs);
970
971 if (tx_unequal_modulation)
972 printf("\t\tTX unequal modulation supported\n");
973 else
974 printf("\t\tTX unequal modulation not supported\n");
975
976 printf("\t\tHT TX Max spatial streams: %d\n",
977 tx_max_num_spatial_streams);
978
979 printf("\t\tHT TX MCS rate indexes supported may differ\n");
980 }
981 } else {
982 printf("\t\tHT RX MCS rate indexes supported:");
983 print_mcs_index(mcs);
089bb35d 984 printf("\t\tHT TX MCS rate indexes are undefined\n");
7ddfb679
JB
985 }
986}
54eb1613 987
00a29858
MB
988struct vht_nss_ratio {
989 bool valid;
990 int bw_20;
991 int bw_40;
992 int bw_80;
993 int bw_160;
994 int bw_80_80;
995};
996
997/*
998 * indexed by [chan_width][ext_nss_bw], ratio in 1/4 unit
999 */
1000static const struct vht_nss_ratio nss_ratio_tbl[3][4] = {
1001 {
1002 /* chan_width == 0, ext_nss_bw == 0 */
1003 {
1004 .valid = true,
1005 .bw_20 = 4,
1006 .bw_40 = 4,
1007 .bw_80 = 4,
1008 },
1009 /* chan_width == 0, ext_nss_bw == 1 */
1010 {
1011 .valid = true,
1012 .bw_20 = 4,
1013 .bw_40 = 4,
1014 .bw_80 = 4,
1015 .bw_160 = 2,
1016 },
1017 /* chan_width == 0, ext_nss_bw == 2 */
1018 {
1019 .valid = true,
1020 .bw_20 = 4,
1021 .bw_40 = 4,
1022 .bw_80 = 4,
1023 .bw_160 = 2,
1024 .bw_80_80 = 2,
1025 },
1026 /* chan_width == 0, ext_nss_bw == 3 */
1027 {
1028 .valid = true,
1029 .bw_20 = 4,
1030 .bw_40 = 4,
1031 .bw_80 = 4,
1032 .bw_160 = 3,
1033 .bw_80_80 = 3,
1034 },
1035 },
1036 {
1037 /* chan_width == 1, ext_nss_bw == 0 */
1038 {
1039 .valid = true,
1040 .bw_20 = 4,
1041 .bw_40 = 4,
1042 .bw_80 = 4,
1043 .bw_160 = 4,
1044 },
1045 /* chan_width == 1, ext_nss_bw == 1 */
1046 {
1047 .valid = true,
1048 .bw_20 = 4,
1049 .bw_40 = 4,
1050 .bw_80 = 4,
1051 .bw_160 = 4,
1052 .bw_80_80 = 2,
1053 },
1054 /* chan_width == 1, ext_nss_bw == 2 */
1055 {
1056 .valid = true,
1057 .bw_20 = 4,
1058 .bw_40 = 4,
1059 .bw_80 = 4,
1060 .bw_160 = 4,
1061 .bw_80_80 = 3,
1062 },
1063 /* chan_width == 1, ext_nss_bw == 3 */
1064 {
1065 .valid = true,
1066 .bw_20 = 8,
1067 .bw_40 = 8,
1068 .bw_80 = 8,
1069 .bw_160 = 8,
1070 .bw_80_80 = 1,
1071 },
1072 },
1073 {
1074 /* chan_width == 2, ext_nss_bw == 0 */
1075 {
1076 .valid = true,
1077 .bw_20 = 4,
1078 .bw_40 = 4,
1079 .bw_80 = 4,
1080 .bw_160 = 4,
1081 .bw_80_80 = 4,
1082 },
1083 /* chan_width == 2, ext_nss_bw == 1 */
1084 {},
1085 /* chan_width == 2, ext_nss_bw == 2 */
1086 {},
1087 /* chan_width == 2, ext_nss_bw == 3 */
1088 {
1089 .valid = true,
1090 .bw_20 = 8,
1091 .bw_40 = 8,
1092 .bw_80 = 8,
1093 .bw_160 = 4,
1094 .bw_80_80 = 4,
1095 },
1096 },
1097};
1098
1099static void print_nss_ratio_value(int ratio)
1100{
1101 const char *rstr;
1102
1103 switch (ratio) {
1104 case 4:
1105 return;
1106 case 3:
1107 rstr = "3/4";
1108 break;
1109 case 2:
1110 rstr = "1/2";
1111 break;
1112 case 8:
1113 rstr = "x2";
1114 break;
1115 default:
1116 rstr = "undef";
1117 break;
1118 }
1119
1120 printf("(%s NSS) ", rstr);
1121}
1122
1123static void print_nss_ratio(const char *str, bool force_show, int ratio)
1124{
1125 if (!ratio)
1126 return;
1127 if (ratio == 4) {
1128 if (force_show)
1129 printf("%s ", str);
1130 } else {
1131 printf("%s ", str);
1132 print_nss_ratio_value(ratio);
1133 }
1134}
1135
54eb1613
JB
1136void print_vht_info(__u32 capa, const __u8 *mcs)
1137{
1138 __u16 tmp;
00a29858
MB
1139 __u32 supp_chan_width, ext_nss_bw;
1140 const struct vht_nss_ratio *nss_tbl;
54eb1613
JB
1141 int i;
1142
1143 printf("\t\tVHT Capabilities (0x%.8x):\n", capa);
1144
1145#define PRINT_VHT_CAPA(_bit, _str) \
1146 do { \
1147 if (capa & BIT(_bit)) \
1148 printf("\t\t\t" _str "\n"); \
1149 } while (0)
1150
1151 printf("\t\t\tMax MPDU length: ");
1152 switch (capa & 3) {
1153 case 0: printf("3895\n"); break;
1154 case 1: printf("7991\n"); break;
1155 case 2: printf("11454\n"); break;
1156 case 3: printf("(reserved)\n");
1157 }
00a29858 1158
54eb1613 1159 printf("\t\t\tSupported Channel Width: ");
00a29858
MB
1160 supp_chan_width = (capa >> 2) & 3;
1161 ext_nss_bw = (capa >> 30) & 3;
1162 nss_tbl = &nss_ratio_tbl[supp_chan_width][ext_nss_bw];
1163
1164 if (!nss_tbl->valid)
1165 printf("(reserved)\n");
1166 else if (nss_tbl->bw_20 == 4 &&
1167 nss_tbl->bw_40 == 4 &&
1168 nss_tbl->bw_80 == 4 &&
1169 (!nss_tbl->bw_160 || nss_tbl->bw_160 == 4) &&
1170 (!nss_tbl->bw_80_80 || nss_tbl->bw_80_80 == 4)) {
1171 /* old style print format */
1172 switch (supp_chan_width) {
1173 case 0: printf("neither 160 nor 80+80\n"); break;
1174 case 1: printf("160 MHz\n"); break;
1175 case 2: printf("160 MHz, 80+80 MHz\n"); break;
1176 }
1177 } else {
1178 print_nss_ratio("20Mhz", false, nss_tbl->bw_20);
1179 print_nss_ratio("40Mhz", false, nss_tbl->bw_40);
1180 print_nss_ratio("80Mhz", false, nss_tbl->bw_80);
1181 print_nss_ratio("160Mhz", false, nss_tbl->bw_160);
1182 print_nss_ratio("80+80Mhz", false, nss_tbl->bw_80_80);
1183 printf("\n");
54eb1613 1184 }
00a29858 1185
54eb1613
JB
1186 PRINT_VHT_CAPA(4, "RX LDPC");
1187 PRINT_VHT_CAPA(5, "short GI (80 MHz)");
1188 PRINT_VHT_CAPA(6, "short GI (160/80+80 MHz)");
1189 PRINT_VHT_CAPA(7, "TX STBC");
1190 /* RX STBC */
1191 PRINT_VHT_CAPA(11, "SU Beamformer");
1192 PRINT_VHT_CAPA(12, "SU Beamformee");
1193 /* compressed steering */
1194 /* # of sounding dimensions */
1195 PRINT_VHT_CAPA(19, "MU Beamformer");
1196 PRINT_VHT_CAPA(20, "MU Beamformee");
1197 PRINT_VHT_CAPA(21, "VHT TXOP PS");
1198 PRINT_VHT_CAPA(22, "+HTC-VHT");
1199 /* max A-MPDU */
1200 /* VHT link adaptation */
75271051
MB
1201 PRINT_VHT_CAPA(28, "RX antenna pattern consistency");
1202 PRINT_VHT_CAPA(29, "TX antenna pattern consistency");
54eb1613
JB
1203
1204 printf("\t\tVHT RX MCS set:\n");
1205 tmp = mcs[0] | (mcs[1] << 8);
1206 for (i = 1; i <= 8; i++) {
1207 printf("\t\t\t%d streams: ", i);
1208 switch ((tmp >> ((i-1)*2) ) & 3) {
1209 case 0: printf("MCS 0-7\n"); break;
1210 case 1: printf("MCS 0-8\n"); break;
1211 case 2: printf("MCS 0-9\n"); break;
1212 case 3: printf("not supported\n"); break;
1213 }
1214 }
1215 tmp = mcs[2] | (mcs[3] << 8);
1216 printf("\t\tVHT RX highest supported: %d Mbps\n", tmp & 0x1fff);
1217
1218 printf("\t\tVHT TX MCS set:\n");
1219 tmp = mcs[4] | (mcs[5] << 8);
1220 for (i = 1; i <= 8; i++) {
1221 printf("\t\t\t%d streams: ", i);
1222 switch ((tmp >> ((i-1)*2) ) & 3) {
1223 case 0: printf("MCS 0-7\n"); break;
1224 case 1: printf("MCS 0-8\n"); break;
1225 case 2: printf("MCS 0-9\n"); break;
1226 case 3: printf("not supported\n"); break;
1227 }
1228 }
1229 tmp = mcs[6] | (mcs[7] << 8);
1230 printf("\t\tVHT TX highest supported: %d Mbps\n", tmp & 0x1fff);
00a29858
MB
1231
1232 printf("\t\tVHT extended NSS: %ssupported\n",
1233 (tmp & (1 << 13)) ? "" : "not ");
54eb1613 1234}
492354de 1235
5735e584
BN
1236static void __print_he_capa(const __u16 *mac_cap,
1237 const __u16 *phy_cap,
1238 const __u16 *mcs_set, size_t mcs_len,
9e38deec
BN
1239 const __u8 *ppet, int ppet_len,
1240 bool indent)
c741be9f 1241{
17e8564a 1242 size_t mcs_used;
c741be9f 1243 int i;
9e38deec 1244 const char *pre = indent ? "\t" : "";
c741be9f
JC
1245
1246 #define PRINT_HE_CAP(_var, _idx, _bit, _str) \
1247 do { \
1248 if (_var[_idx] & BIT(_bit)) \
9e38deec 1249 printf("%s\t\t\t" _str "\n", pre); \
c741be9f
JC
1250 } while (0)
1251
1252 #define PRINT_HE_CAP_MASK(_var, _idx, _shift, _mask, _str) \
1253 do { \
1254 if ((_var[_idx] >> _shift) & _mask) \
9e38deec 1255 printf("%s\t\t\t" _str ": %d\n", pre, (_var[_idx] >> _shift) & _mask); \
c741be9f
JC
1256 } while (0)
1257
1258 #define PRINT_HE_MAC_CAP(...) PRINT_HE_CAP(mac_cap, __VA_ARGS__)
1259 #define PRINT_HE_MAC_CAP_MASK(...) PRINT_HE_CAP_MASK(mac_cap, __VA_ARGS__)
1260 #define PRINT_HE_PHY_CAP(...) PRINT_HE_CAP(phy_cap, __VA_ARGS__)
1261 #define PRINT_HE_PHY_CAP0(_idx, _bit, ...) PRINT_HE_CAP(phy_cap, _idx, _bit + 8, __VA_ARGS__)
1262 #define PRINT_HE_PHY_CAP_MASK(...) PRINT_HE_CAP_MASK(phy_cap, __VA_ARGS__)
1263
9e38deec 1264 printf("%s\t\tHE MAC Capabilities (0x", pre);
c741be9f
JC
1265 for (i = 0; i < 3; i++)
1266 printf("%04x", mac_cap[i]);
1267 printf("):\n");
1268
1269 PRINT_HE_MAC_CAP(0, 0, "+HTC HE Supported");
1270 PRINT_HE_MAC_CAP(0, 1, "TWT Requester");
1271 PRINT_HE_MAC_CAP(0, 2, "TWT Responder");
1272 PRINT_HE_MAC_CAP_MASK(0, 3, 0x3, "Dynamic BA Fragementation Level");
1273 PRINT_HE_MAC_CAP_MASK(0, 5, 0x7, "Maximum number of MSDUS Fragments");
1274 PRINT_HE_MAC_CAP_MASK(0, 8, 0x3, "Minimum Payload size of 128 bytes");
1275 PRINT_HE_MAC_CAP_MASK(0, 10, 0x3, "Trigger Frame MAC Padding Duration");
1276 PRINT_HE_MAC_CAP_MASK(0, 12, 0x7, "Multi-TID Aggregation Support");
1277
1278 PRINT_HE_MAC_CAP(1, 1, "All Ack");
1279 PRINT_HE_MAC_CAP(1, 2, "TRS");
1280 PRINT_HE_MAC_CAP(1, 3, "BSR");
1281 PRINT_HE_MAC_CAP(1, 4, "Broadcast TWT");
1282 PRINT_HE_MAC_CAP(1, 5, "32-bit BA Bitmap");
1283 PRINT_HE_MAC_CAP(1, 6, "MU Cascading");
1284 PRINT_HE_MAC_CAP(1, 7, "Ack-Enabled Aggregation");
1285 PRINT_HE_MAC_CAP(1, 9, "OM Control");
1286 PRINT_HE_MAC_CAP(1, 10, "OFDMA RA");
1287 PRINT_HE_MAC_CAP_MASK(1, 11, 0x3, "Maximum A-MPDU Length Exponent");
1288 PRINT_HE_MAC_CAP(1, 13, "A-MSDU Fragmentation");
1289 PRINT_HE_MAC_CAP(1, 14, "Flexible TWT Scheduling");
1290 PRINT_HE_MAC_CAP(1, 15, "RX Control Frame to MultiBSS");
1291
1292 PRINT_HE_MAC_CAP(2, 0, "BSRP BQRP A-MPDU Aggregation");
1293 PRINT_HE_MAC_CAP(2, 1, "QTP");
1294 PRINT_HE_MAC_CAP(2, 2, "BQR");
1295 PRINT_HE_MAC_CAP(2, 3, "SRP Responder Role");
1296 PRINT_HE_MAC_CAP(2, 4, "NDP Feedback Report");
1297 PRINT_HE_MAC_CAP(2, 5, "OPS");
1298 PRINT_HE_MAC_CAP(2, 6, "A-MSDU in A-MPDU");
1299 PRINT_HE_MAC_CAP_MASK(2, 7, 7, "Multi-TID Aggregation TX");
1300 PRINT_HE_MAC_CAP(2, 10, "HE Subchannel Selective Transmission");
1301 PRINT_HE_MAC_CAP(2, 11, "UL 2x996-Tone RU");
1302 PRINT_HE_MAC_CAP(2, 12, "OM Control UL MU Data Disable RX");
1303
9e38deec 1304 printf("%s\t\tHE PHY Capabilities: (0x", pre);
c741be9f
JC
1305 for (i = 0; i < 11; i++)
1306 printf("%02x", ((__u8 *)phy_cap)[i + 1]);
1307 printf("):\n");
1308
1309 PRINT_HE_PHY_CAP0(0, 1, "HE40/2.4GHz");
1310 PRINT_HE_PHY_CAP0(0, 2, "HE40/HE80/5GHz");
1311 PRINT_HE_PHY_CAP0(0, 3, "HE160/5GHz");
1312 PRINT_HE_PHY_CAP0(0, 4, "HE160/HE80+80/5GHz");
1313 PRINT_HE_PHY_CAP0(0, 5, "242 tone RUs/2.4GHz");
1314 PRINT_HE_PHY_CAP0(0, 6, "242 tone RUs/5GHz");
1315
1316 PRINT_HE_PHY_CAP_MASK(1, 0, 0xf, "Punctured Preamble RX");
1317 PRINT_HE_PHY_CAP_MASK(1, 4, 0x1, "Device Class");
1318 PRINT_HE_PHY_CAP(1, 5, "LDPC Coding in Payload");
1319 PRINT_HE_PHY_CAP(1, 6, "HE SU PPDU with 1x HE-LTF and 0.8us GI");
1320 PRINT_HE_PHY_CAP_MASK(1, 7, 0x3, "Midamble Rx Max NSTS");
1321 PRINT_HE_PHY_CAP(1, 9, "NDP with 4x HE-LTF and 3.2us GI");
1322 PRINT_HE_PHY_CAP(1, 10, "STBC Tx <= 80MHz");
1323 PRINT_HE_PHY_CAP(1, 11, "STBC Rx <= 80MHz");
1324 PRINT_HE_PHY_CAP(1, 12, "Doppler Tx");
1325 PRINT_HE_PHY_CAP(1, 13, "Doppler Rx");
1326 PRINT_HE_PHY_CAP(1, 14, "Full Bandwidth UL MU-MIMO");
1327 PRINT_HE_PHY_CAP(1, 15, "Partial Bandwidth UL MU-MIMO");
1328
1329 PRINT_HE_PHY_CAP_MASK(2, 0, 0x3, "DCM Max Constellation");
1330 PRINT_HE_PHY_CAP_MASK(2, 2, 0x1, "DCM Max NSS Tx");
1331 PRINT_HE_PHY_CAP_MASK(2, 3, 0x3, "DCM Max Constellation Rx");
1332 PRINT_HE_PHY_CAP_MASK(2, 5, 0x1, "DCM Max NSS Rx");
1333 PRINT_HE_PHY_CAP(2, 6, "Rx HE MU PPDU from Non-AP STA");
1334 PRINT_HE_PHY_CAP(2, 7, "SU Beamformer");
1335 PRINT_HE_PHY_CAP(2, 8, "SU Beamformee");
1336 PRINT_HE_PHY_CAP(2, 9, "MU Beamformer");
1337 PRINT_HE_PHY_CAP_MASK(2, 10, 0x7, "Beamformee STS <= 80Mhz");
1338 PRINT_HE_PHY_CAP_MASK(2, 13, 0x7, "Beamformee STS > 80Mhz");
1339
1340 PRINT_HE_PHY_CAP_MASK(3, 0, 0x7, "Sounding Dimensions <= 80Mhz");
1341 PRINT_HE_PHY_CAP_MASK(3, 3, 0x7, "Sounding Dimensions > 80Mhz");
1342 PRINT_HE_PHY_CAP(3, 6, "Ng = 16 SU Feedback");
1343 PRINT_HE_PHY_CAP(3, 7, "Ng = 16 MU Feedback");
1344 PRINT_HE_PHY_CAP(3, 8, "Codebook Size SU Feedback");
1345 PRINT_HE_PHY_CAP(3, 9, "Codebook Size MU Feedback");
1346 PRINT_HE_PHY_CAP(3, 10, "Triggered SU Beamforming Feedback");
1347 PRINT_HE_PHY_CAP(3, 11, "Triggered MU Beamforming Feedback");
1348 PRINT_HE_PHY_CAP(3, 12, "Triggered CQI Feedback");
1349 PRINT_HE_PHY_CAP(3, 13, "Partial Bandwidth Extended Range");
1350 PRINT_HE_PHY_CAP(3, 14, "Partial Bandwidth DL MU-MIMO");
1351 PRINT_HE_PHY_CAP(3, 15, "PPE Threshold Present");
1352
1353 PRINT_HE_PHY_CAP(4, 0, "SRP-based SR");
1354 PRINT_HE_PHY_CAP(4, 1, "Power Boost Factor ar");
1355 PRINT_HE_PHY_CAP(4, 2, "HE SU PPDU & HE PPDU 4x HE-LTF 0.8us GI");
1356 PRINT_HE_PHY_CAP_MASK(4, 3, 0x7, "Max NC");
1357 PRINT_HE_PHY_CAP(4, 6, "STBC Tx > 80MHz");
1358 PRINT_HE_PHY_CAP(4, 7, "STBC Rx > 80MHz");
1359 PRINT_HE_PHY_CAP(4, 8, "HE ER SU PPDU 4x HE-LTF 0.8us GI");
1360 PRINT_HE_PHY_CAP(4, 9, "20MHz in 40MHz HE PPDU 2.4GHz");
1361 PRINT_HE_PHY_CAP(4, 10, "20MHz in 160/80+80MHz HE PPDU");
1362 PRINT_HE_PHY_CAP(4, 11, "80MHz in 160/80+80MHz HE PPDU");
1363 PRINT_HE_PHY_CAP(4, 12, "HE ER SU PPDU 1x HE-LTF 0.8us GI");
1364 PRINT_HE_PHY_CAP(4, 13, "Midamble Rx 2x & 1x HE-LTF");
1365 PRINT_HE_PHY_CAP_MASK(4, 14, 0x3, "DCM Max BW");
1366
1367 PRINT_HE_PHY_CAP(5, 0, "Longer Than 16HE SIG-B OFDM Symbols");
1368 PRINT_HE_PHY_CAP(5, 1, "Non-Triggered CQI Feedback");
1369 PRINT_HE_PHY_CAP(5, 2, "TX 1024-QAM");
1370 PRINT_HE_PHY_CAP(5, 3, "RX 1024-QAM");
1371 PRINT_HE_PHY_CAP(5, 4, "RX Full BW SU Using HE MU PPDU with Compression SIGB");
1372 PRINT_HE_PHY_CAP(5, 5, "RX Full BW SU Using HE MU PPDU with Non-Compression SIGB");
1373
17e8564a 1374 mcs_used = 0;
c741be9f
JC
1375 for (i = 0; i < 3; i++) {
1376 __u8 phy_cap_support[] = { BIT(1) | BIT(2), BIT(3), BIT(4) };
1377 char *bw[] = { "<= 80", "160", "80+80" };
1378 int j;
1379
1380 if ((phy_cap[0] & (phy_cap_support[i] << 8)) == 0)
1381 continue;
1382
5735e584
BN
1383 /* Supports more, but overflow? Abort. */
1384 if ((i * 2 + 2) * sizeof(mcs_set[0]) >= mcs_len)
1385 return;
1386
c741be9f
JC
1387 for (j = 0; j < 2; j++) {
1388 int k;
9e38deec 1389 printf("%s\t\tHE %s MCS and NSS set %s MHz\n", pre, j ? "TX" : "RX", bw[i]);
c741be9f
JC
1390 for (k = 0; k < 8; k++) {
1391 __u16 mcs = mcs_set[(i * 2) + j];
1392 mcs >>= k * 2;
1393 mcs &= 0x3;
9e38deec 1394 printf("%s\t\t\t%d streams: ", pre, k + 1);
c741be9f
JC
1395 if (mcs == 3)
1396 printf("not supported\n");
1397 else
1398 printf("MCS 0-%d\n", 7 + (mcs * 2));
1399 }
1400
1401 }
17e8564a
BN
1402 mcs_used += 2 * sizeof(mcs_set[0]);
1403 }
1404
1405 /* Caller didn't provide ppet; infer it, if there's trailing space. */
1406 if (!ppet) {
4b25ae35 1407 ppet = (const void *)((const __u8 *)mcs_set + mcs_used);
17e8564a
BN
1408 if (mcs_used < mcs_len)
1409 ppet_len = mcs_len - mcs_used;
1410 else
1411 ppet_len = 0;
c741be9f
JC
1412 }
1413
5735e584 1414 if (ppet_len && (phy_cap[3] & BIT(15))) {
9e38deec 1415 printf("%s\t\tPPE Threshold ", pre);
5735e584
BN
1416 for (i = 0; i < ppet_len; i++)
1417 if (ppet[i])
1418 printf("0x%02x ", ppet[i]);
1419 printf("\n");
1420 }
1421}
1422
a6cedc6d
JB
1423void print_iftype_list(const char *name, const char *pfx, struct nlattr *attr)
1424{
1425 struct nlattr *ift;
1426 int rem;
1427
1428 printf("%s:\n", name);
1429 nla_for_each_nested(ift, attr, rem)
1430 printf("%s * %s\n", pfx, iftype_name(nla_type(ift)));
1431}
1432
1433void print_iftype_line(struct nlattr *attr)
1434{
1435 struct nlattr *ift;
1436 bool first = true;
1437 int rem;
1438
1439 nla_for_each_nested(ift, attr, rem) {
1440 if (first)
1441 first = false;
1442 else
1443 printf(", ");
1444 printf("%s", iftype_name(nla_type(ift)));
1445 }
1446}
1447
5735e584
BN
1448void print_he_info(struct nlattr *nl_iftype)
1449{
1450 struct nlattr *tb[NL80211_BAND_IFTYPE_ATTR_MAX + 1];
5735e584
BN
1451 __u16 mac_cap[3] = { 0 };
1452 __u16 phy_cap[6] = { 0 };
1453 __u16 mcs_set[6] = { 0 };
1454 __u8 ppet[25] = { 0 };
1455 size_t len;
5735e584
BN
1456 int mcs_len = 0, ppet_len = 0;
1457
1458 nla_parse(tb, NL80211_BAND_IFTYPE_ATTR_MAX,
1459 nla_data(nl_iftype), nla_len(nl_iftype), NULL);
1460
1461 if (!tb[NL80211_BAND_IFTYPE_ATTR_IFTYPES])
1462 return;
1463
a6cedc6d
JB
1464 printf("\t\tHE Iftypes: ");
1465 print_iftype_line(tb[NL80211_BAND_IFTYPE_ATTR_IFTYPES]);
5735e584
BN
1466 printf("\n");
1467
1468 if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC]) {
1469 len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC]);
1470 if (len > sizeof(mac_cap))
1471 len = sizeof(mac_cap);
1472 memcpy(mac_cap,
1473 nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC]),
1474 len);
1475 }
1476
1477 if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]) {
1478 len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]);
1479
1480 if (len > sizeof(phy_cap) - 1)
1481 len = sizeof(phy_cap) - 1;
1482 memcpy(&((__u8 *)phy_cap)[1],
1483 nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]),
1484 len);
1485 }
1486
1487 if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET]) {
1488 len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET]);
1489 if (len > sizeof(mcs_set))
1490 len = sizeof(mcs_set);
1491 memcpy(mcs_set,
1492 nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET]),
1493 len);
1494 mcs_len = len;
1495 }
1496
c741be9f
JC
1497 if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE]) {
1498 len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE]);
1499 if (len > sizeof(ppet))
1500 len = sizeof(ppet);
1501 memcpy(ppet,
1502 nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE]),
1503 len);
5735e584 1504 ppet_len = len;
c741be9f
JC
1505 }
1506
9e38deec
BN
1507 __print_he_capa(mac_cap, phy_cap, mcs_set, mcs_len, ppet, ppet_len,
1508 true);
c741be9f
JC
1509}
1510
5a71b722
IP
1511static void __print_eht_capa(int band,
1512 const __u8 *mac_cap,
1513 const __u32 *phy_cap,
1514 const __u8 *mcs_set, size_t mcs_len,
1515 const __u8 *ppet, size_t ppet_len,
1516 const __u16 *he_phy_cap,
1517 bool indent)
1518{
1519 unsigned int i;
1520 const char *pre = indent ? "\t" : "";
1521 const char *mcs[] = { "0-7", "8-9", "10-11", "12-13"};
1522
1523 #define PRINT_EHT_CAP(_var, _idx, _bit, _str) \
1524 do { \
1525 if (_var[_idx] & BIT(_bit)) \
1526 printf("%s\t\t\t" _str "\n", pre); \
1527 } while (0)
1528
1529 #define PRINT_EHT_CAP_MASK(_var, _idx, _shift, _mask, _str) \
1530 do { \
1531 if ((_var[_idx] >> _shift) & _mask) \
1532 printf("%s\t\t\t" _str ": %d\n", pre, (_var[_idx] >> _shift) & _mask); \
1533 } while (0)
1534
1535 #define PRINT_EHT_MAC_CAP(...) PRINT_EHT_CAP(mac_cap, __VA_ARGS__)
1536 #define PRINT_EHT_PHY_CAP(...) PRINT_EHT_CAP(phy_cap, __VA_ARGS__)
1537 #define PRINT_EHT_PHY_CAP_MASK(...) PRINT_EHT_CAP_MASK(phy_cap, __VA_ARGS__)
1538
1539 printf("%s\t\tEHT MAC Capabilities (0x", pre);
1540 for (i = 0; i < 2; i++)
1541 printf("%02x", mac_cap[i]);
1542 printf("):\n");
1543
1544 PRINT_EHT_MAC_CAP(0, 0, "NSEP priority access Supported");
1545 PRINT_EHT_MAC_CAP(0, 1, "EHT OM Control Supported");
1546 PRINT_EHT_MAC_CAP(0, 2, "Triggered TXOP Sharing Supported");
1547 PRINT_EHT_MAC_CAP(0, 3, "ARR Supported");
1548
1549 printf("%s\t\tEHT PHY Capabilities: (0x", pre);
1550 for (i = 0; i < 8; i++)
1551 printf("%02x", ((__u8 *)phy_cap)[i]);
1552 printf("):\n");
1553
1554 PRINT_EHT_PHY_CAP(0, 1, "320MHz in 6GHz Supported");
1555 PRINT_EHT_PHY_CAP(0, 2, "242-tone RU in BW wider than 20MHz Supported");
1556 PRINT_EHT_PHY_CAP(0, 3, "NDP With EHT-LTF And 3.2 µs GI");
1557 PRINT_EHT_PHY_CAP(0, 4, "Partial Bandwidth UL MU-MIMO");
1558 PRINT_EHT_PHY_CAP(0, 5, "SU Beamformer");
1559 PRINT_EHT_PHY_CAP(0, 6, "SU Beamformee");
1560 PRINT_EHT_PHY_CAP_MASK(0, 7, 0x7, "Beamformee SS (80MHz)");
1561 PRINT_EHT_PHY_CAP_MASK(0, 10, 0x7, "Beamformee SS (160MHz)");
1562 PRINT_EHT_PHY_CAP_MASK(0, 13, 0x7, "Beamformee SS (320MHz)");
1563
1564 PRINT_EHT_PHY_CAP_MASK(0, 16, 0x7, "Number Of Sounding Dimensions (80MHz)");
1565 PRINT_EHT_PHY_CAP_MASK(0, 19, 0x7, "Number Of Sounding Dimensions (160MHz)");
1566 PRINT_EHT_PHY_CAP_MASK(0, 22, 0x7, "Number Of Sounding Dimensions (320MHz)");
1567 PRINT_EHT_PHY_CAP(0, 25, "Ng = 16 SU Feedback");
1568 PRINT_EHT_PHY_CAP(0, 26, "Ng = 16 MU Feedback");
1569 PRINT_EHT_PHY_CAP(0, 27, "Codebook size (4, 2) SU Feedback");
1570 PRINT_EHT_PHY_CAP(0, 28, "Codebook size (7, 5) MU Feedback");
1571 PRINT_EHT_PHY_CAP(0, 29, "Triggered SU Beamforming Feedback");
1572 PRINT_EHT_PHY_CAP(0, 30, "Triggered MU Beamforming Partial BW Feedback");
1573 PRINT_EHT_PHY_CAP(0, 31, "Triggered CQI Feedback");
1574
1575 PRINT_EHT_PHY_CAP(1, 0, "Partial Bandwidth DL MU-MIMO");
1576 PRINT_EHT_PHY_CAP(1, 1, "PSR-Based SR Support");
1577 PRINT_EHT_PHY_CAP(1, 2, "Power Boost Factor Support");
1578 PRINT_EHT_PHY_CAP(1, 3, "EHT MU PPDU With 4 EHT-LTF And 0.8 µs GI");
1579 PRINT_EHT_PHY_CAP_MASK(1, 4, 0xf, "Max Nc");
1580 PRINT_EHT_PHY_CAP(1, 8, "Non-Triggered CQI Feedback");
1581
1582 PRINT_EHT_PHY_CAP(1, 9, "Tx 1024-QAM And 4096-QAM < 242-tone RU");
1583 PRINT_EHT_PHY_CAP(1, 10, "Rx 1024-QAM And 4096-QAM < 242-tone RU");
1584 PRINT_EHT_PHY_CAP(1, 11, "PPE Thresholds Present");
1585 PRINT_EHT_PHY_CAP_MASK(1, 12, 0x3, "Common Nominal Packet Padding");
1586 PRINT_EHT_PHY_CAP_MASK(1, 14, 0x1f, "Maximum Number Of Supported EHT-LTFs");
1587 PRINT_EHT_PHY_CAP_MASK(1, 19, 0xf, "Support of MCS 15");
1588 PRINT_EHT_PHY_CAP(1, 23, "Support Of EHT DUP In 6 GHz");
1589 PRINT_EHT_PHY_CAP(1, 24, "Support For 20MHz Rx NDP With Wider Bandwidth");
1590 PRINT_EHT_PHY_CAP(1, 25, "Non-OFDMA UL MU-MIMO (80MHz)");
1591 PRINT_EHT_PHY_CAP(1, 26, "Non-OFDMA UL MU-MIMO (160MHz)");
1592 PRINT_EHT_PHY_CAP(1, 27, "Non-OFDMA UL MU-MIMO (320MHz)");
1593 PRINT_EHT_PHY_CAP(1, 28, "MU Beamformer (80MHz)");
1594 PRINT_EHT_PHY_CAP(1, 29, "MU Beamformer (160MHz)");
1595 PRINT_EHT_PHY_CAP(1, 30, "MU Beamformer (320MHz)");
1596
1597 printf("%s\t\tEHT MCS/NSS: (0x", pre);
1598 for (i = 0; i < mcs_len; i++)
1599 printf("%02x", ((__u8 *)mcs_set)[i]);
1600 printf("):\n");
1601
1602 if (!(he_phy_cap[0] & ((BIT(2) | BIT(3) | BIT(4)) << 8))){
1603 for (i = 0; i < 4; i++)
1604 printf("%s\t\tEHT bw=20 MHz, max NSS for MCS %s: Rx=%u, Tx=%u\n",
1605 pre, mcs[i],
1606 mcs_set[i] & 0xf, mcs_set[i] >> 4);
cf26fc9a
BG
1607 } else {
1608 if (he_phy_cap[0] & (BIT(2) << 8)) {
1609 for (i = 0; i < 3; i++)
1610 printf("%s\t\tEHT bw <= 80 MHz, max NSS for MCS %s: Rx=%u, Tx=%u\n",
1611 pre, mcs[i + 1],
1612 mcs_set[i] & 0xf, mcs_set[i] >> 4);
1613 }
1614 mcs_set += 3;
5a71b722 1615
cf26fc9a
BG
1616 if (he_phy_cap[0] & (BIT(3) << 8)) {
1617 for (i = 0; i < 3; i++)
1618 printf("%s\t\tEHT bw=160 MHz, max NSS for MCS %s: Rx=%u, Tx=%u\n",
1619 pre, mcs[i + 1],
1620 mcs_set[i] & 0xf, mcs_set[i] >> 4);
1621 }
5a71b722 1622
cf26fc9a
BG
1623 mcs_set += 3;
1624 if (band == NL80211_BAND_6GHZ && (phy_cap[0] & BIT(1))) {
1625 for (i = 0; i < 3; i++)
1626 printf("%s\t\tEHT bw=320 MHz, max NSS for MCS %s: Rx=%u, Tx=%u\n",
1627 pre, mcs[i + 1],
1628 mcs_set[i] & 0xf, mcs_set[i] >> 4);
1629 }
5a71b722
IP
1630 }
1631
1632 if (ppet && ppet_len && (phy_cap[1] & BIT(11))) {
1633 printf("%s\t\tEHT PPE Thresholds ", pre);
1634 for (i = 0; i < ppet_len; i++)
1635 if (ppet[i])
1636 printf("0x%02x ", ppet[i]);
1637 printf("\n");
1638 }
1639}
1640
1641void print_eht_info(struct nlattr *nl_iftype, int band)
1642{
1643 struct nlattr *tb[NL80211_BAND_IFTYPE_ATTR_MAX + 1];
1644 __u8 mac_cap[2] = { 0 };
1645 __u32 phy_cap[2] = { 0 };
1646 __u8 mcs_set[13] = { 0 };
1647 __u8 ppet[31] = { 0 };
1648 __u16 he_phy_cap[6] = { 0 };
1649 size_t len, mcs_len = 0, ppet_len = 0;
1650
1651 nla_parse(tb, NL80211_BAND_IFTYPE_ATTR_MAX,
1652 nla_data(nl_iftype), nla_len(nl_iftype), NULL);
1653
f5e3b43d
JB
1654 if (!tb[NL80211_BAND_IFTYPE_ATTR_IFTYPES] ||
1655 !tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC])
5a71b722
IP
1656 return;
1657
1658 printf("\t\tEHT Iftypes: ");
1659 print_iftype_line(tb[NL80211_BAND_IFTYPE_ATTR_IFTYPES]);
1660 printf("\n");
1661
1662 if (tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC]) {
1663 len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC]);
1664 if (len > sizeof(mac_cap))
1665 len = sizeof(mac_cap);
1666 memcpy(mac_cap,
1667 nla_data(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC]),
1668 len);
1669 }
1670
1671 if (tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY]) {
1672 len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY]);
1673
1674 if (len > sizeof(phy_cap))
1675 len = sizeof(phy_cap);
1676
1677 memcpy(phy_cap,
1678 nla_data(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY]),
1679 len);
1680 }
1681
1682 if (tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET]) {
1683 len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET]);
1684 if (len > sizeof(mcs_set))
1685 len = sizeof(mcs_set);
1686 memcpy(mcs_set,
1687 nla_data(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET]),
1688 len);
1689
1690 // Assume that all parts of the MCS set are present
1691 mcs_len = sizeof(mcs_set);
1692 }
1693
1694 if (tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE]) {
1695 len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE]);
1696 if (len > sizeof(ppet))
1697 len = sizeof(ppet);
1698 memcpy(ppet,
1699 nla_data(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE]),
1700 len);
1701 ppet_len = len;
1702 }
1703
1704 if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]) {
1705 len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]);
1706
1707 if (len > sizeof(he_phy_cap) - 1)
1708 len = sizeof(he_phy_cap) - 1;
1709 memcpy(&((__u8 *)he_phy_cap)[1],
1710 nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]),
1711 len);
1712 }
1713
1714 __print_eht_capa(band, mac_cap, phy_cap, mcs_set, mcs_len, ppet, ppet_len,
1715 he_phy_cap, true);
1716}
1717
17e8564a
BN
1718void print_he_capability(const uint8_t *ie, int len)
1719{
1720 const void *mac_cap, *phy_cap, *mcs_set;
1721 int mcs_len;
1722 int i = 0;
1723
1724 mac_cap = &ie[i];
1725 i += 6;
1726
1727 phy_cap = &ie[i];
1728 i += 11;
1729
1730 mcs_set = &ie[i];
1731 mcs_len = len - i;
1732
9e38deec 1733 __print_he_capa(mac_cap, phy_cap - 1, mcs_set, mcs_len, NULL, 0, false);
17e8564a
BN
1734}
1735
492354de
JD
1736void iw_hexdump(const char *prefix, const __u8 *buf, size_t size)
1737{
0ee571d5 1738 size_t i;
492354de
JD
1739
1740 printf("%s: ", prefix);
1741 for (i = 0; i < size; i++) {
1742 if (i && i % 16 == 0)
1743 printf("\n%s: ", prefix);
1744 printf("%02x ", buf[i]);
1745 }
1746 printf("\n\n");
1747}
c1b2b633
SE
1748
1749int get_cf1(const struct chanmode *chanmode, unsigned long freq)
1750{
1751 unsigned int cf1 = freq, j;
c56036a4
PKC
1752 unsigned int bw80[] = { 5180, 5260, 5500, 5580, 5660, 5745,
1753 5955, 6035, 6115, 6195, 6275, 6355,
1754 6435, 6515, 6595, 6675, 6755, 6835,
1755 6195, 6995 };
a4e5418a
DW
1756 unsigned int bw160[] = { 5180, 5500, 5955, 6115, 6275, 6435,
1757 6595, 6755, 6915 };
997e5f13
MG
1758 /* based on 11be D2 E.1 Country information and operating classes */
1759 unsigned int bw320[] = {5955, 6115, 6275, 6435, 6595, 6755};
c1b2b633
SE
1760
1761 switch (chanmode->width) {
1762 case NL80211_CHAN_WIDTH_80:
1763 /* setup center_freq1 */
c56036a4
PKC
1764 for (j = 0; j < ARRAY_SIZE(bw80); j++) {
1765 if (freq >= bw80[j] && freq < bw80[j] + 80)
c1b2b633
SE
1766 break;
1767 }
1768
c56036a4 1769 if (j == ARRAY_SIZE(bw80))
c1b2b633
SE
1770 break;
1771
c56036a4 1772 cf1 = bw80[j] + 30;
c1b2b633 1773 break;
b6f2dac4
T
1774 case NL80211_CHAN_WIDTH_160:
1775 /* setup center_freq1 */
a4e5418a
DW
1776 for (j = 0; j < ARRAY_SIZE(bw160); j++) {
1777 if (freq >= bw160[j] && freq < bw160[j] + 160)
b6f2dac4
T
1778 break;
1779 }
1780
a4e5418a 1781 if (j == ARRAY_SIZE(bw160))
b6f2dac4
T
1782 break;
1783
a4e5418a 1784 cf1 = bw160[j] + 70;
b6f2dac4 1785 break;
997e5f13
MG
1786 case NL80211_CHAN_WIDTH_320:
1787 /* setup center_freq1 */
1788 for (j = 0; j < ARRAY_SIZE(bw320); j++) {
1789 if (freq >= bw320[j] && freq < bw320[j] + 160)
1790 break;
1791 }
1792
1793 if (j == ARRAY_SIZE(bw320))
1794 break;
1795
1796 cf1 = bw320[j] + 150;
1797 break;
c1b2b633
SE
1798 default:
1799 cf1 = freq + chanmode->freq1_diff;
1800 break;
1801 }
1802
1803 return cf1;
1804}
3c0117c1
JB
1805
1806int parse_random_mac_addr(struct nl_msg *msg, char *addrs)
1807{
1808 char *a_addr, *a_mask, *sep;
1809 unsigned char addr[ETH_ALEN], mask[ETH_ALEN];
1810
1811 if (!*addrs) {
1812 /* randomise all but the multicast bit */
1813 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN,
1814 "\x00\x00\x00\x00\x00\x00");
1815 NLA_PUT(msg, NL80211_ATTR_MAC_MASK, ETH_ALEN,
1816 "\x01\x00\x00\x00\x00\x00");
1817 return 0;
1818 }
1819
1820 if (*addrs != '=')
1821 return 1;
1822
1823 addrs++;
1824 sep = strchr(addrs, '/');
1825 a_addr = addrs;
1826
1827 if (!sep)
1828 return 1;
1829
1830 *sep = 0;
1831 a_mask = sep + 1;
1832 if (mac_addr_a2n(addr, a_addr) || mac_addr_a2n(mask, a_mask))
1833 return 1;
1834
1835 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
1836 NLA_PUT(msg, NL80211_ATTR_MAC_MASK, ETH_ALEN, mask);
1837
1838 return 0;
1839 nla_put_failure:
1840 return -ENOBUFS;
1841}
1bc6ab0a
GI
1842
1843char *s1g_ss_max_support(__u8 maxss)
1844{
1845 switch (maxss) {
1846 case 0: return "Max S1G-MCS 2";
1847 case 1: return "Max S1G-MCS 7";
1848 case 2: return "Max S1G-MCS 9";
1849 case 3: return "Not supported";
1850 default: return "";
1851 }
1852}
1853
1854char *s1g_ss_min_support(__u8 minss)
1855{
1856 switch (minss) {
1857 case 0: return "no minimum restriction";
1858 case 1: return "MCS 0 not recommended";
1859 case 2: return "MCS 0 and 1 not recommended";
1860 case 3: return "invalid";
1861 default: return "";
1862 }
1863}
1864
1865void print_s1g_capability(const uint8_t *caps)
1866{
1867#define PRINT_S1G_CAP(_cond, _str) \
1868 do { \
1869 if (_cond) \
1870 printf("\t\t\t" _str "\n"); \
1871 } while (0)
1872
1873 static char buf[20];
1874 int offset = 0;
1875 uint8_t cap = caps[0];
1876
1877 /* S1G Capabilities Information subfield */
1878 if (cap)
1879 printf("\t\tByte[0]: 0x%02x\n", cap);
1880
1881 PRINT_S1G_CAP((cap & BIT(0)), "S1G PHY: S1G_LONG PPDU Format");
1882
1883 if ((cap >> 1) & 0x1f) {
1884 offset = sprintf(buf, "SGI support:");
1885 offset += sprintf(buf + offset, "%s", ((cap >> 1) & 0x1) ? " 1" : "");
1886 offset += sprintf(buf + offset, "%s", ((cap >> 1) & 0x2) ? " 2" : "");
1887 offset += sprintf(buf + offset, "%s", ((cap >> 1) & 0x4) ? " 4" : "");
1888 offset += sprintf(buf + offset, "%s", ((cap >> 1) & 0x8) ? " 8" : "");
1889 offset += sprintf(buf + offset, "%s", ((cap >> 1) & 0x10) ? " 16" : "");
1890 offset += sprintf(buf + offset, " MHz");
1891 printf("\t\t\t%s\n", buf);
1892 }
1893
1894 PRINT_S1G_CAP(((cap >> 6) & 0x3) == 0x0, "Channel width: 1, 2 MHz");
1895 PRINT_S1G_CAP(((cap >> 6) & 0x3) == 0x1, "Channel width: 1, 2, 4 MHz");
1896 PRINT_S1G_CAP(((cap >> 6) & 0x3) == 0x2, "Channel width: 1, 2, 4, 8 MHz");
1897 PRINT_S1G_CAP(((cap >> 6) & 0x3) == 0x3, "Channel width: 1, 2, 4, 8, 16 MHz");
1898
1899 cap = caps[1];
1900
1901 if (cap)
1902 printf("\t\tByte[1]: 0x%02x\n", cap);
1903
1904 PRINT_S1G_CAP((cap & BIT(0)), "Rx LDPC");
1905 PRINT_S1G_CAP((cap & BIT(1)), "Tx STBC");
1906 PRINT_S1G_CAP((cap & BIT(2)), "Rx STBC");
1907 PRINT_S1G_CAP((cap & BIT(3)), "SU Beamformer");
1908 PRINT_S1G_CAP((cap & BIT(4)), "SU Beamformee");
1909 if (cap & BIT(4))
1910 printf("\t\t\tBeamformee STS: %d\n", (cap >> 5) + 1);
1911
1912 cap = caps[2];
1913 printf("\t\tByte[2]: 0x%02x\n", cap);
1914
1915 if (caps[1] & BIT(3))
1916 printf("\t\t\tSounding dimensions: %d\n", (cap & 0x7) + 1);
1917
1918 PRINT_S1G_CAP((cap & BIT(3)), "MU Beamformer");
1919 PRINT_S1G_CAP((cap & BIT(4)), "MU Beamformee");
1920 PRINT_S1G_CAP((cap & BIT(5)), "+HTC-VHT Capable");
1921 PRINT_S1G_CAP(((cap >> 6) & 0x3) == 0x0, "No support for Traveling Pilot");
1922 PRINT_S1G_CAP(((cap >> 6) & 0x3) == 0x1, "Supports 1 STS Traveling Pilot");
1923 PRINT_S1G_CAP(((cap >> 6) & 0x3) == 0x3, "Supports 1 and 2 STS Traveling Pilot");
1924
1925 cap = caps[3];
1926 printf("\t\tByte[3]: 0x%02x\n", cap);
1927 PRINT_S1G_CAP((cap & BIT(0)), "RD Responder");
1928 /* BIT(1) in Byte 3 or BIT(25) in all capabilities is reserved */
1929 PRINT_S1G_CAP(((cap & BIT(2)) == 0x0), "Max MPDU length: 3895 bytes");
1930 PRINT_S1G_CAP((cap & BIT(2)), "Max MPDU length: 7991 bytes");
1931
1932 if (compute_ampdu_length((cap >> 2) & 0x3)) {
1933 printf("\t\t\tMaximum AMPDU length: %d bytes (exponent: 0x0%02x)\n",
1934 compute_ampdu_length((cap >> 2) & 0x3), (cap >> 2) & 0x3);
1935 } else {
1936 printf("\t\t\tMaximum AMPDU length: unrecognized bytes (exponent: %d)\n",
1937 (cap >> 2) & 0x3);
1938 }
1939
1940 printf("\t\t\tMinimum MPDU time spacing: %s (0x%02x)\n",
1941 print_ampdu_space((cap >> 5) & 0x7), (cap >> 5) & 0x7);
1942
1943 cap = caps[4];
1944 printf("\t\tByte[4]: 0x%02x\n", cap);
1945 PRINT_S1G_CAP((cap & BIT(0)), "Uplink sync capable");
1946 PRINT_S1G_CAP((cap & BIT(1)), "Dynamic AID");
1947 PRINT_S1G_CAP((cap & BIT(2)), "BAT");
1948 PRINT_S1G_CAP((cap & BIT(3)), "TIM ADE");
1949 PRINT_S1G_CAP((cap & BIT(4)), "Non-TIM");
1950 PRINT_S1G_CAP((cap & BIT(5)), "Group AID");
1951 PRINT_S1G_CAP(((cap >> 6) & 0x3) == 0x0, "Sensor and non-sensor STAs");
1952 PRINT_S1G_CAP(((cap >> 6) & 0x3) == 0x1, "Only sensor STAs");
1953 PRINT_S1G_CAP(((cap >> 6) & 0x3) == 0x2, "Only non-sensor STAs");
1954
1955 cap = caps[5];
1956 printf("\t\tByte[5]: 0x%02x\n", cap);
1957 PRINT_S1G_CAP((cap & BIT(0)), "Centralized authentication control");
1958 PRINT_S1G_CAP((cap & BIT(1)), "Distributed authentication control");
1959 PRINT_S1G_CAP((cap & BIT(2)), "A-MSDU supported");
1960 PRINT_S1G_CAP((cap & BIT(3)), "A-MPDU supported");
1961 PRINT_S1G_CAP((cap & BIT(4)), "Asymmetric BA supported");
1962 PRINT_S1G_CAP((cap & BIT(5)), "Flow control supported");
1963 PRINT_S1G_CAP(((cap >> 6) & 0x3) == 0x0, "Sectorization operation not supported");
1964 PRINT_S1G_CAP(((cap >> 6) & 0x3) == 0x1, "TXOP-based sectorization operation");
1965 PRINT_S1G_CAP(((cap >> 6) & 0x3) == 0x2, "only group sectorization operation");
1966 PRINT_S1G_CAP(((cap >> 6) & 0x3) == 0x3, "Group and TXOP-based sectorization operations");
1967
1968 cap = caps[6];
1969 if (cap)
1970 printf("\t\tByte[6]: 0x%02x\n", cap);
1971
1972 PRINT_S1G_CAP((cap & BIT(0)), "OBSS mitigation");
1973 PRINT_S1G_CAP((cap & BIT(1)), "Fragment BA");
1974 PRINT_S1G_CAP((cap & BIT(2)), "NDP PS-Poll");
1975 PRINT_S1G_CAP((cap & BIT(3)), "RAW operation");
1976 PRINT_S1G_CAP((cap & BIT(4)), "Page slicing");
1977 PRINT_S1G_CAP((cap & BIT(5)), "TXOP sharing smplicit Ack");
1978
1979 /* Only in case +HTC-VHT Capable is 0x1 */
1980 if (caps[2] & BIT(5)) {
1981 PRINT_S1G_CAP(((cap >> 6) & 0x3) == 0x0, "Not provide VHT MFB (No Feedback)");
1982 PRINT_S1G_CAP(((cap >> 6) & 0x3) == 0x2, "Provides only unsolicited VHT MFB");
1983 PRINT_S1G_CAP(((cap >> 6) & 0x3) == 0x3,
1984 "Provides both feedback and unsolicited VHT MFB");
1985 }
1986
1987 cap = caps[7];
1988 printf("\t\tByte[7]: 0x%02x\n", cap);
1989 PRINT_S1G_CAP((cap & BIT(0)), "TACK support as PS-Poll response");
1990 PRINT_S1G_CAP((cap & BIT(1)), "Duplicate 1 MHz");
1991 PRINT_S1G_CAP((cap & BIT(2)), "MCS negotiation");
1992 PRINT_S1G_CAP((cap & BIT(3)), "1 MHz control response preamble");
1993 PRINT_S1G_CAP((cap & BIT(4)), "NDP beamforming report poll");
1994 PRINT_S1G_CAP((cap & BIT(5)), "Unsolicited dynamic AID");
1995 PRINT_S1G_CAP((cap & BIT(6)), "Sector training operation");
1996 PRINT_S1G_CAP((cap & BIT(7)), "Temporary PS mode switch");
1997
1998 cap = caps[8];
1999 if (cap)
2000 printf("\t\tByte[8]: 0x%02x\n", cap);
2001
2002 PRINT_S1G_CAP((cap & BIT(0)), "TWT grouping");
2003 PRINT_S1G_CAP((cap & BIT(1)), "BDT capable");
2004 printf("\t\t\tColor: %u\n", (cap >> 2) & 0x7);
2005 PRINT_S1G_CAP((cap & BIT(5)), "TWT requester");
2006 PRINT_S1G_CAP((cap & BIT(6)), "TWT responder");
2007 PRINT_S1G_CAP((cap & BIT(7)), "PV1 frame support");
2008
2009 cap = caps[9];
2010 if (cap)
2011 printf("\t\tByte[9]: 0x%02x\n", cap);
2012
2013 PRINT_S1G_CAP((cap & BIT(0)), "Link Adaptation without NDP CMAC PPDU capable");
2014 /* Rest of byte 9 bits are reserved */
2015
2016 /* Supported S1G-MCS and NSS Set subfield */
2017 /* Rx S1G-MCS Map */
2018 cap = caps[10];
2019 printf("\t\tMax Rx S1G MCS Map: 0x%02x\n", cap);
2020 printf("\t\t\tFor 1 SS: %s\n", s1g_ss_max_support(cap & 0x3));
2021 printf("\t\t\tFor 2 SS: %s\n", s1g_ss_max_support((cap >> 2) & 0x3));
2022 printf("\t\t\tFor 3 SS: %s\n", s1g_ss_max_support((cap >> 4) & 0x3));
2023 printf("\t\t\tFor 4 SS: %s\n", s1g_ss_max_support((cap >> 6) & 0x3));
2024
2025 /* Rx Long GI data rate field comprises of 9 bits */
2026 cap = caps[11];
2027 if (cap || caps[12] & 0x1)
2028 printf("\t\t\tRx Highest Long GI Data Rate: %u Mbps\n",
2029 cap + ((caps[12] & 0x1) << 8));
2030
2031 /* Tx S1G-MCS Map */
2032 cap = caps[12];
2033 printf("\t\tMax Tx S1G MCS Map: 0x%02x\n", cap);
2034 printf("\t\t\tFor 1 SS: %s\n", s1g_ss_max_support((cap >> 1) & 0x3));
2035 printf("\t\t\tFor 2 SS: %s\n", s1g_ss_max_support((cap >> 3) & 0x3));
2036 printf("\t\t\tFor 3 SS: %s\n", s1g_ss_max_support((cap >> 5) & 0x3));
2037 printf("\t\t\tFor 4 SS: %s\n", s1g_ss_max_support(((cap >> 7) & 0x1) +
2038 ((caps[13] << 1) & 0x2)));
2039
2040 /* Tx Long GI data rate field comprises of 9 bits */
2041 cap = caps[13];
2042 if (((cap >> 7) & 0x7f) || (caps[14] & 0x3))
2043 printf("\t\t\tTx Highest Long GI Data Rate: %u Mbps\n", ((cap >> 7) & 0x7f) +
2044 ((caps[14] & 0x3) << 7));
2045
2046 /* Rx and Tx single spatial streams and S1G MCS Map for 1 MHz */
2047 cap = (caps[15] >> 2) & 0xf;
2048 PRINT_S1G_CAP((cap & 0x3) == 0x0, "Rx single SS for 1 MHz: as in Rx S1G MCS Map");
2049 PRINT_S1G_CAP((cap & 0x3) == 0x1, "Rx single SS for 1 MHz: single SS and S1G-MCS 2");
2050 PRINT_S1G_CAP((cap & 0x3) == 0x2, "Rx single SS for 1 MHz: single SS and S1G-MCS 7");
2051 PRINT_S1G_CAP((cap & 0x3) == 0x3, "Rx single SS for 1 MHz: single SS and S1G-MCS 9");
2052 cap = (cap >> 2) & 0x3;
2053 PRINT_S1G_CAP((cap & 0x3) == 0x0, "Tx single SS for 1 MHz: as in Tx S1G MCS Map");
2054 PRINT_S1G_CAP((cap & 0x3) == 0x1, "Tx single SS for 1 MHz: single SS and S1G-MCS 2");
2055 PRINT_S1G_CAP((cap & 0x3) == 0x2, "Tx single SS for 1 MHz: single SS and S1G-MCS 7");
2056 PRINT_S1G_CAP((cap & 0x3) == 0x3, "Tx single SS for 1 MHz: single SS and S1G-MCS 9");
2057 /* Last 2 bits are reserved */
2058#undef PRINT_S1G_CAP
2059}