]> git.ipfire.org Git - thirdparty/hostap.git/blame - src/drivers/driver_nl80211_capa.c
wpa_supplicant: Handle port authorized event
[thirdparty/hostap.git] / src / drivers / driver_nl80211_capa.c
CommitLineData
0fafeb54
JM
1/*
2 * Driver interaction with Linux nl80211/cfg80211 - Capabilities
399e6135 3 * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
0fafeb54
JM
4 * Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
5 * Copyright (c) 2009-2010, Atheros Communications
6 *
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
9 */
10
11#include "includes.h"
12#include <netlink/genl/genl.h>
13
14#include "utils/common.h"
0fafeb54 15#include "common/ieee802_11_common.h"
a042e39a 16#include "common/wpa_common.h"
0fafeb54
JM
17#include "common/qca-vendor.h"
18#include "common/qca-vendor-attr.h"
19#include "driver_nl80211.h"
20
21
22static int protocol_feature_handler(struct nl_msg *msg, void *arg)
23{
24 u32 *feat = arg;
25 struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
26 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
27
28 nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
29 genlmsg_attrlen(gnlh, 0), NULL);
30
31 if (tb_msg[NL80211_ATTR_PROTOCOL_FEATURES])
32 *feat = nla_get_u32(tb_msg[NL80211_ATTR_PROTOCOL_FEATURES]);
33
34 return NL_SKIP;
35}
36
37
38static u32 get_nl80211_protocol_features(struct wpa_driver_nl80211_data *drv)
39{
40 u32 feat = 0;
41 struct nl_msg *msg;
42
43 msg = nlmsg_alloc();
44 if (!msg)
9589a91e
JM
45 return 0;
46
47 if (!nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_PROTOCOL_FEATURES)) {
48 nlmsg_free(msg);
49 return 0;
50 }
0fafeb54 51
0fafeb54
JM
52 if (send_and_recv_msgs(drv, msg, protocol_feature_handler, &feat) == 0)
53 return feat;
54
0fafeb54
JM
55 return 0;
56}
57
58
59struct wiphy_info_data {
60 struct wpa_driver_nl80211_data *drv;
61 struct wpa_driver_capa *capa;
62
63 unsigned int num_multichan_concurrent;
64
65 unsigned int error:1;
66 unsigned int device_ap_sme:1;
67 unsigned int poll_command_supported:1;
68 unsigned int data_tx_status:1;
0fafeb54
JM
69 unsigned int auth_supported:1;
70 unsigned int connect_supported:1;
71 unsigned int p2p_go_supported:1;
72 unsigned int p2p_client_supported:1;
abb8d08b 73 unsigned int p2p_go_ctwindow_supported:1;
0fafeb54
JM
74 unsigned int p2p_concurrent:1;
75 unsigned int channel_switch_supported:1;
76 unsigned int set_qos_map_supported:1;
77 unsigned int have_low_prio_scan:1;
dfa87878 78 unsigned int wmm_ac_supported:1;
86056fea
IP
79 unsigned int mac_addr_rand_scan_supported:1;
80 unsigned int mac_addr_rand_sched_scan_supported:1;
0fafeb54
JM
81};
82
83
84static unsigned int probe_resp_offload_support(int supp_protocols)
85{
86 unsigned int prot = 0;
87
88 if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS)
89 prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS;
90 if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2)
91 prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2;
92 if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P)
93 prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P;
94 if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U)
95 prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING;
96
97 return prot;
98}
99
100
101static void wiphy_info_supported_iftypes(struct wiphy_info_data *info,
102 struct nlattr *tb)
103{
104 struct nlattr *nl_mode;
105 int i;
106
107 if (tb == NULL)
108 return;
109
110 nla_for_each_nested(nl_mode, tb, i) {
111 switch (nla_type(nl_mode)) {
112 case NL80211_IFTYPE_AP:
113 info->capa->flags |= WPA_DRIVER_FLAGS_AP;
114 break;
115 case NL80211_IFTYPE_MESH_POINT:
116 info->capa->flags |= WPA_DRIVER_FLAGS_MESH;
117 break;
118 case NL80211_IFTYPE_ADHOC:
119 info->capa->flags |= WPA_DRIVER_FLAGS_IBSS;
120 break;
121 case NL80211_IFTYPE_P2P_DEVICE:
122 info->capa->flags |=
123 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE;
124 break;
125 case NL80211_IFTYPE_P2P_GO:
126 info->p2p_go_supported = 1;
127 break;
128 case NL80211_IFTYPE_P2P_CLIENT:
129 info->p2p_client_supported = 1;
130 break;
0fafeb54
JM
131 }
132 }
133}
134
135
136static int wiphy_info_iface_comb_process(struct wiphy_info_data *info,
137 struct nlattr *nl_combi)
138{
139 struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB];
140 struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT];
141 struct nlattr *nl_limit, *nl_mode;
142 int err, rem_limit, rem_mode;
143 int combination_has_p2p = 0, combination_has_mgd = 0;
144 static struct nla_policy
145 iface_combination_policy[NUM_NL80211_IFACE_COMB] = {
146 [NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED },
147 [NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },
148 [NL80211_IFACE_COMB_STA_AP_BI_MATCH] = { .type = NLA_FLAG },
149 [NL80211_IFACE_COMB_NUM_CHANNELS] = { .type = NLA_U32 },
150 [NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS] = { .type = NLA_U32 },
151 },
152 iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {
153 [NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED },
154 [NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 },
155 };
156
157 err = nla_parse_nested(tb_comb, MAX_NL80211_IFACE_COMB,
158 nl_combi, iface_combination_policy);
159 if (err || !tb_comb[NL80211_IFACE_COMB_LIMITS] ||
160 !tb_comb[NL80211_IFACE_COMB_MAXNUM] ||
161 !tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS])
162 return 0; /* broken combination */
163
164 if (tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS])
165 info->capa->flags |= WPA_DRIVER_FLAGS_RADAR;
166
167 nla_for_each_nested(nl_limit, tb_comb[NL80211_IFACE_COMB_LIMITS],
168 rem_limit) {
169 err = nla_parse_nested(tb_limit, MAX_NL80211_IFACE_LIMIT,
170 nl_limit, iface_limit_policy);
171 if (err || !tb_limit[NL80211_IFACE_LIMIT_TYPES])
172 return 0; /* broken combination */
173
174 nla_for_each_nested(nl_mode,
175 tb_limit[NL80211_IFACE_LIMIT_TYPES],
176 rem_mode) {
177 int ift = nla_type(nl_mode);
178 if (ift == NL80211_IFTYPE_P2P_GO ||
179 ift == NL80211_IFTYPE_P2P_CLIENT)
180 combination_has_p2p = 1;
181 if (ift == NL80211_IFTYPE_STATION)
182 combination_has_mgd = 1;
183 }
184 if (combination_has_p2p && combination_has_mgd)
185 break;
186 }
187
188 if (combination_has_p2p && combination_has_mgd) {
189 unsigned int num_channels =
190 nla_get_u32(tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]);
191
192 info->p2p_concurrent = 1;
193 if (info->num_multichan_concurrent < num_channels)
194 info->num_multichan_concurrent = num_channels;
195 }
196
197 return 0;
198}
199
200
201static void wiphy_info_iface_comb(struct wiphy_info_data *info,
202 struct nlattr *tb)
203{
204 struct nlattr *nl_combi;
205 int rem_combi;
206
207 if (tb == NULL)
208 return;
209
210 nla_for_each_nested(nl_combi, tb, rem_combi) {
211 if (wiphy_info_iface_comb_process(info, nl_combi) > 0)
212 break;
213 }
214}
215
216
217static void wiphy_info_supp_cmds(struct wiphy_info_data *info,
218 struct nlattr *tb)
219{
220 struct nlattr *nl_cmd;
221 int i;
222
223 if (tb == NULL)
224 return;
225
226 nla_for_each_nested(nl_cmd, tb, i) {
227 switch (nla_get_u32(nl_cmd)) {
228 case NL80211_CMD_AUTHENTICATE:
229 info->auth_supported = 1;
230 break;
231 case NL80211_CMD_CONNECT:
232 info->connect_supported = 1;
233 break;
234 case NL80211_CMD_START_SCHED_SCAN:
235 info->capa->sched_scan_supported = 1;
236 break;
237 case NL80211_CMD_PROBE_CLIENT:
238 info->poll_command_supported = 1;
239 break;
240 case NL80211_CMD_CHANNEL_SWITCH:
241 info->channel_switch_supported = 1;
242 break;
243 case NL80211_CMD_SET_QOS_MAP:
244 info->set_qos_map_supported = 1;
245 break;
246 }
247 }
248}
249
250
251static void wiphy_info_cipher_suites(struct wiphy_info_data *info,
252 struct nlattr *tb)
253{
254 int i, num;
255 u32 *ciphers;
256
257 if (tb == NULL)
258 return;
259
260 num = nla_len(tb) / sizeof(u32);
261 ciphers = nla_data(tb);
262 for (i = 0; i < num; i++) {
263 u32 c = ciphers[i];
264
265 wpa_printf(MSG_DEBUG, "nl80211: Supported cipher %02x-%02x-%02x:%d",
266 c >> 24, (c >> 16) & 0xff,
267 (c >> 8) & 0xff, c & 0xff);
268 switch (c) {
a042e39a 269 case RSN_CIPHER_SUITE_CCMP_256:
0fafeb54
JM
270 info->capa->enc |= WPA_DRIVER_CAPA_ENC_CCMP_256;
271 break;
a042e39a 272 case RSN_CIPHER_SUITE_GCMP_256:
0fafeb54
JM
273 info->capa->enc |= WPA_DRIVER_CAPA_ENC_GCMP_256;
274 break;
a042e39a 275 case RSN_CIPHER_SUITE_CCMP:
0fafeb54
JM
276 info->capa->enc |= WPA_DRIVER_CAPA_ENC_CCMP;
277 break;
a042e39a 278 case RSN_CIPHER_SUITE_GCMP:
0fafeb54
JM
279 info->capa->enc |= WPA_DRIVER_CAPA_ENC_GCMP;
280 break;
a042e39a 281 case RSN_CIPHER_SUITE_TKIP:
0fafeb54
JM
282 info->capa->enc |= WPA_DRIVER_CAPA_ENC_TKIP;
283 break;
a042e39a 284 case RSN_CIPHER_SUITE_WEP104:
0fafeb54
JM
285 info->capa->enc |= WPA_DRIVER_CAPA_ENC_WEP104;
286 break;
a042e39a 287 case RSN_CIPHER_SUITE_WEP40:
0fafeb54
JM
288 info->capa->enc |= WPA_DRIVER_CAPA_ENC_WEP40;
289 break;
a042e39a 290 case RSN_CIPHER_SUITE_AES_128_CMAC:
0fafeb54
JM
291 info->capa->enc |= WPA_DRIVER_CAPA_ENC_BIP;
292 break;
a042e39a 293 case RSN_CIPHER_SUITE_BIP_GMAC_128:
0fafeb54
JM
294 info->capa->enc |= WPA_DRIVER_CAPA_ENC_BIP_GMAC_128;
295 break;
a042e39a 296 case RSN_CIPHER_SUITE_BIP_GMAC_256:
0fafeb54
JM
297 info->capa->enc |= WPA_DRIVER_CAPA_ENC_BIP_GMAC_256;
298 break;
a042e39a 299 case RSN_CIPHER_SUITE_BIP_CMAC_256:
0fafeb54
JM
300 info->capa->enc |= WPA_DRIVER_CAPA_ENC_BIP_CMAC_256;
301 break;
a042e39a 302 case RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED:
0fafeb54
JM
303 info->capa->enc |= WPA_DRIVER_CAPA_ENC_GTK_NOT_USED;
304 break;
305 }
306 }
307}
308
309
310static void wiphy_info_max_roc(struct wpa_driver_capa *capa,
311 struct nlattr *tb)
312{
313 if (tb)
314 capa->max_remain_on_chan = nla_get_u32(tb);
315}
316
317
318static void wiphy_info_tdls(struct wpa_driver_capa *capa, struct nlattr *tdls,
319 struct nlattr *ext_setup)
320{
321 if (tdls == NULL)
322 return;
323
324 wpa_printf(MSG_DEBUG, "nl80211: TDLS supported");
325 capa->flags |= WPA_DRIVER_FLAGS_TDLS_SUPPORT;
326
327 if (ext_setup) {
328 wpa_printf(MSG_DEBUG, "nl80211: TDLS external setup");
329 capa->flags |= WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP;
330 }
331}
332
333
4acdc48a
JD
334static int ext_feature_isset(const u8 *ext_features, int ext_features_len,
335 enum nl80211_ext_feature_index ftidx)
336{
337 u8 ft_byte;
338
339 if ((int) ftidx / 8 >= ext_features_len)
340 return 0;
341
342 ft_byte = ext_features[ftidx / 8];
343 return (ft_byte & BIT(ftidx % 8)) != 0;
344}
345
346
347static void wiphy_info_ext_feature_flags(struct wiphy_info_data *info,
348 struct nlattr *tb)
349{
350 struct wpa_driver_capa *capa = info->capa;
b5d172e5
BL
351 u8 *ext_features;
352 int len;
4acdc48a
JD
353
354 if (tb == NULL)
355 return;
356
b5d172e5
BL
357 ext_features = nla_data(tb);
358 len = nla_len(tb);
359
360 if (ext_feature_isset(ext_features, len, NL80211_EXT_FEATURE_VHT_IBSS))
4acdc48a 361 capa->flags |= WPA_DRIVER_FLAGS_VHT_IBSS;
b5d172e5
BL
362
363 if (ext_feature_isset(ext_features, len, NL80211_EXT_FEATURE_RRM))
364 capa->rrm_flags |= WPA_DRIVER_FLAGS_SUPPORT_RRM;
befdb2dc
JM
365
366 if (ext_feature_isset(ext_features, len, NL80211_EXT_FEATURE_FILS_STA))
367 capa->flags |= WPA_DRIVER_FLAGS_SUPPORT_FILS;
d4f3003c
PK
368
369 if (ext_feature_isset(ext_features, len,
370 NL80211_EXT_FEATURE_BEACON_RATE_LEGACY))
371 capa->flags |= WPA_DRIVER_FLAGS_BEACON_RATE_LEGACY;
372
373 if (ext_feature_isset(ext_features, len,
374 NL80211_EXT_FEATURE_BEACON_RATE_HT))
375 capa->flags |= WPA_DRIVER_FLAGS_BEACON_RATE_HT;
376
377 if (ext_feature_isset(ext_features, len,
378 NL80211_EXT_FEATURE_BEACON_RATE_VHT))
379 capa->flags |= WPA_DRIVER_FLAGS_BEACON_RATE_VHT;
96a5f14e
AS
380
381 if (ext_feature_isset(ext_features, len,
382 NL80211_EXT_FEATURE_SET_SCAN_DWELL))
383 capa->rrm_flags |= WPA_DRIVER_FLAGS_SUPPORT_SET_SCAN_DWELL;
384
385 if (ext_feature_isset(ext_features, len,
386 NL80211_EXT_FEATURE_SCAN_START_TIME) &&
387 ext_feature_isset(ext_features, len,
388 NL80211_EXT_FEATURE_BSS_PARENT_TSF) &&
389 ext_feature_isset(ext_features, len,
390 NL80211_EXT_FEATURE_SET_SCAN_DWELL))
391 capa->rrm_flags |= WPA_DRIVER_FLAGS_SUPPORT_BEACON_REPORT;
8331c9b3
VK
392 if (ext_feature_isset(ext_features, len,
393 NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA))
394 capa->flags |= WPA_DRIVER_FLAGS_MGMT_TX_RANDOM_TA;
395 if (ext_feature_isset(ext_features, len,
396 NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA_CONNECTED))
397 capa->flags |= WPA_DRIVER_FLAGS_MGMT_TX_RANDOM_TA_CONNECTED;
20c846d9 398 if (ext_feature_isset(ext_features, len,
399 NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI))
400 capa->flags |= WPA_DRIVER_FLAGS_SCHED_SCAN_RELATIVE_RSSI;
ad295f3b
VK
401 if (ext_feature_isset(ext_features, len,
402 NL80211_EXT_FEATURE_FILS_SK_OFFLOAD))
403 capa->flags |= WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD;
0ff08f96
EP
404
405 if (ext_feature_isset(ext_features, len,
406 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK) &&
407 ext_feature_isset(ext_features, len,
408 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
409 capa->flags |= WPA_DRIVER_FLAGS_4WAY_HANDSHAKE;
4acdc48a
JD
410}
411
412
0fafeb54
JM
413static void wiphy_info_feature_flags(struct wiphy_info_data *info,
414 struct nlattr *tb)
415{
416 u32 flags;
417 struct wpa_driver_capa *capa = info->capa;
418
419 if (tb == NULL)
420 return;
421
422 flags = nla_get_u32(tb);
423
424 if (flags & NL80211_FEATURE_SK_TX_STATUS)
425 info->data_tx_status = 1;
426
427 if (flags & NL80211_FEATURE_INACTIVITY_TIMER)
428 capa->flags |= WPA_DRIVER_FLAGS_INACTIVITY_TIMER;
429
430 if (flags & NL80211_FEATURE_SAE)
431 capa->flags |= WPA_DRIVER_FLAGS_SAE;
432
433 if (flags & NL80211_FEATURE_NEED_OBSS_SCAN)
434 capa->flags |= WPA_DRIVER_FLAGS_OBSS_SCAN;
435
436 if (flags & NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE)
437 capa->flags |= WPA_DRIVER_FLAGS_HT_2040_COEX;
438
4daa5729
AN
439 if (flags & NL80211_FEATURE_TDLS_CHANNEL_SWITCH) {
440 wpa_printf(MSG_DEBUG, "nl80211: TDLS channel switch");
441 capa->flags |= WPA_DRIVER_FLAGS_TDLS_CHANNEL_SWITCH;
442 }
443
abb8d08b
EP
444 if (flags & NL80211_FEATURE_P2P_GO_CTWIN)
445 info->p2p_go_ctwindow_supported = 1;
446
0fafeb54
JM
447 if (flags & NL80211_FEATURE_LOW_PRIORITY_SCAN)
448 info->have_low_prio_scan = 1;
449
86056fea
IP
450 if (flags & NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR)
451 info->mac_addr_rand_scan_supported = 1;
452
453 if (flags & NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR)
454 info->mac_addr_rand_sched_scan_supported = 1;
455
0fafeb54
JM
456 if (flags & NL80211_FEATURE_STATIC_SMPS)
457 capa->smps_modes |= WPA_DRIVER_SMPS_MODE_STATIC;
458
459 if (flags & NL80211_FEATURE_DYNAMIC_SMPS)
460 capa->smps_modes |= WPA_DRIVER_SMPS_MODE_DYNAMIC;
dfa87878
MB
461
462 if (flags & NL80211_FEATURE_SUPPORTS_WMM_ADMISSION)
463 info->wmm_ac_supported = 1;
58162adf
AK
464
465 if (flags & NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES)
466 capa->rrm_flags |= WPA_DRIVER_FLAGS_DS_PARAM_SET_IE_IN_PROBES;
467
468 if (flags & NL80211_FEATURE_WFA_TPC_IE_IN_PROBES)
469 capa->rrm_flags |= WPA_DRIVER_FLAGS_WFA_TPC_IE_IN_PROBES;
470
471 if (flags & NL80211_FEATURE_QUIET)
472 capa->rrm_flags |= WPA_DRIVER_FLAGS_QUIET;
473
474 if (flags & NL80211_FEATURE_TX_POWER_INSERTION)
475 capa->rrm_flags |= WPA_DRIVER_FLAGS_TX_POWER_INSERTION;
1830817e
JD
476
477 if (flags & NL80211_FEATURE_HT_IBSS)
478 capa->flags |= WPA_DRIVER_FLAGS_HT_IBSS;
dc55b6b6
AB
479
480 if (flags & NL80211_FEATURE_FULL_AP_CLIENT_STATE)
481 capa->flags |= WPA_DRIVER_FLAGS_FULL_AP_CLIENT_STATE;
0fafeb54
JM
482}
483
484
485static void wiphy_info_probe_resp_offload(struct wpa_driver_capa *capa,
486 struct nlattr *tb)
487{
488 u32 protocols;
489
490 if (tb == NULL)
491 return;
492
493 protocols = nla_get_u32(tb);
494 wpa_printf(MSG_DEBUG, "nl80211: Supports Probe Response offload in AP "
495 "mode");
496 capa->flags |= WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD;
497 capa->probe_resp_offloads = probe_resp_offload_support(protocols);
498}
499
500
501static void wiphy_info_wowlan_triggers(struct wpa_driver_capa *capa,
502 struct nlattr *tb)
503{
504 struct nlattr *triggers[MAX_NL80211_WOWLAN_TRIG + 1];
505
506 if (tb == NULL)
507 return;
508
509 if (nla_parse_nested(triggers, MAX_NL80211_WOWLAN_TRIG,
510 tb, NULL))
511 return;
512
513 if (triggers[NL80211_WOWLAN_TRIG_ANY])
514 capa->wowlan_triggers.any = 1;
515 if (triggers[NL80211_WOWLAN_TRIG_DISCONNECT])
516 capa->wowlan_triggers.disconnect = 1;
517 if (triggers[NL80211_WOWLAN_TRIG_MAGIC_PKT])
518 capa->wowlan_triggers.magic_pkt = 1;
519 if (triggers[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE])
520 capa->wowlan_triggers.gtk_rekey_failure = 1;
521 if (triggers[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST])
522 capa->wowlan_triggers.eap_identity_req = 1;
523 if (triggers[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE])
524 capa->wowlan_triggers.four_way_handshake = 1;
525 if (triggers[NL80211_WOWLAN_TRIG_RFKILL_RELEASE])
526 capa->wowlan_triggers.rfkill_release = 1;
527}
528
529
cc9a2575
KV
530static void wiphy_info_extended_capab(struct wpa_driver_nl80211_data *drv,
531 struct nlattr *tb)
532{
533 int rem = 0, i;
534 struct nlattr *tb1[NL80211_ATTR_MAX + 1], *attr;
535
536 if (!tb || drv->num_iface_ext_capa == NL80211_IFTYPE_MAX)
537 return;
538
539 nla_for_each_nested(attr, tb, rem) {
540 unsigned int len;
541 struct drv_nl80211_ext_capa *capa;
542
543 nla_parse(tb1, NL80211_ATTR_MAX, nla_data(attr),
544 nla_len(attr), NULL);
545
546 if (!tb1[NL80211_ATTR_IFTYPE] ||
547 !tb1[NL80211_ATTR_EXT_CAPA] ||
548 !tb1[NL80211_ATTR_EXT_CAPA_MASK])
549 continue;
550
551 capa = &drv->iface_ext_capa[drv->num_iface_ext_capa];
552 capa->iftype = nla_get_u32(tb1[NL80211_ATTR_IFTYPE]);
553 wpa_printf(MSG_DEBUG,
554 "nl80211: Driver-advertised extended capabilities for interface type %s",
555 nl80211_iftype_str(capa->iftype));
556
557 len = nla_len(tb1[NL80211_ATTR_EXT_CAPA]);
a1f11e34
JB
558 capa->ext_capa = os_memdup(nla_data(tb1[NL80211_ATTR_EXT_CAPA]),
559 len);
cc9a2575
KV
560 if (!capa->ext_capa)
561 goto err;
562
cc9a2575
KV
563 capa->ext_capa_len = len;
564 wpa_hexdump(MSG_DEBUG, "nl80211: Extended capabilities",
565 capa->ext_capa, capa->ext_capa_len);
566
567 len = nla_len(tb1[NL80211_ATTR_EXT_CAPA_MASK]);
a1f11e34
JB
568 capa->ext_capa_mask =
569 os_memdup(nla_data(tb1[NL80211_ATTR_EXT_CAPA_MASK]),
570 len);
cc9a2575
KV
571 if (!capa->ext_capa_mask)
572 goto err;
573
cc9a2575
KV
574 wpa_hexdump(MSG_DEBUG, "nl80211: Extended capabilities mask",
575 capa->ext_capa_mask, capa->ext_capa_len);
576
577 drv->num_iface_ext_capa++;
578 if (drv->num_iface_ext_capa == NL80211_IFTYPE_MAX)
579 break;
580 }
581
582 return;
583
584err:
585 /* Cleanup allocated memory on error */
586 for (i = 0; i < NL80211_IFTYPE_MAX; i++) {
587 os_free(drv->iface_ext_capa[i].ext_capa);
588 drv->iface_ext_capa[i].ext_capa = NULL;
589 os_free(drv->iface_ext_capa[i].ext_capa_mask);
590 drv->iface_ext_capa[i].ext_capa_mask = NULL;
591 drv->iface_ext_capa[i].ext_capa_len = 0;
592 }
593 drv->num_iface_ext_capa = 0;
594}
595
596
0fafeb54
JM
597static int wiphy_info_handler(struct nl_msg *msg, void *arg)
598{
599 struct nlattr *tb[NL80211_ATTR_MAX + 1];
600 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
601 struct wiphy_info_data *info = arg;
602 struct wpa_driver_capa *capa = info->capa;
603 struct wpa_driver_nl80211_data *drv = info->drv;
604
605 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
606 genlmsg_attrlen(gnlh, 0), NULL);
607
0e92fb8f
JB
608 if (tb[NL80211_ATTR_WIPHY])
609 drv->wiphy_idx = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
610
0fafeb54
JM
611 if (tb[NL80211_ATTR_WIPHY_NAME])
612 os_strlcpy(drv->phyname,
613 nla_get_string(tb[NL80211_ATTR_WIPHY_NAME]),
614 sizeof(drv->phyname));
615 if (tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS])
616 capa->max_scan_ssids =
617 nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]);
618
619 if (tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS])
620 capa->max_sched_scan_ssids =
621 nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS]);
622
09ea4309
AS
623 if (tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS] &&
624 tb[NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL] &&
625 tb[NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS]) {
626 capa->max_sched_scan_plans =
627 nla_get_u32(tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS]);
628
629 capa->max_sched_scan_plan_interval =
630 nla_get_u32(tb[NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL]);
631
632 capa->max_sched_scan_plan_iterations =
633 nla_get_u32(tb[NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS]);
634 }
635
0fafeb54
JM
636 if (tb[NL80211_ATTR_MAX_MATCH_SETS])
637 capa->max_match_sets =
638 nla_get_u8(tb[NL80211_ATTR_MAX_MATCH_SETS]);
639
640 if (tb[NL80211_ATTR_MAC_ACL_MAX])
641 capa->max_acl_mac_addrs =
642 nla_get_u8(tb[NL80211_ATTR_MAC_ACL_MAX]);
643
644 wiphy_info_supported_iftypes(info, tb[NL80211_ATTR_SUPPORTED_IFTYPES]);
645 wiphy_info_iface_comb(info, tb[NL80211_ATTR_INTERFACE_COMBINATIONS]);
646 wiphy_info_supp_cmds(info, tb[NL80211_ATTR_SUPPORTED_COMMANDS]);
647 wiphy_info_cipher_suites(info, tb[NL80211_ATTR_CIPHER_SUITES]);
648
649 if (tb[NL80211_ATTR_OFFCHANNEL_TX_OK]) {
650 wpa_printf(MSG_DEBUG, "nl80211: Using driver-based "
651 "off-channel TX");
652 capa->flags |= WPA_DRIVER_FLAGS_OFFCHANNEL_TX;
653 }
654
655 if (tb[NL80211_ATTR_ROAM_SUPPORT]) {
656 wpa_printf(MSG_DEBUG, "nl80211: Using driver-based roaming");
657 capa->flags |= WPA_DRIVER_FLAGS_BSS_SELECTION;
658 }
659
660 wiphy_info_max_roc(capa,
661 tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION]);
662
663 if (tb[NL80211_ATTR_SUPPORT_AP_UAPSD])
664 capa->flags |= WPA_DRIVER_FLAGS_AP_UAPSD;
665
666 wiphy_info_tdls(capa, tb[NL80211_ATTR_TDLS_SUPPORT],
667 tb[NL80211_ATTR_TDLS_EXTERNAL_SETUP]);
668
669 if (tb[NL80211_ATTR_DEVICE_AP_SME])
670 info->device_ap_sme = 1;
671
672 wiphy_info_feature_flags(info, tb[NL80211_ATTR_FEATURE_FLAGS]);
4acdc48a 673 wiphy_info_ext_feature_flags(info, tb[NL80211_ATTR_EXT_FEATURES]);
0fafeb54
JM
674 wiphy_info_probe_resp_offload(capa,
675 tb[NL80211_ATTR_PROBE_RESP_OFFLOAD]);
676
677 if (tb[NL80211_ATTR_EXT_CAPA] && tb[NL80211_ATTR_EXT_CAPA_MASK] &&
678 drv->extended_capa == NULL) {
679 drv->extended_capa =
680 os_malloc(nla_len(tb[NL80211_ATTR_EXT_CAPA]));
681 if (drv->extended_capa) {
682 os_memcpy(drv->extended_capa,
683 nla_data(tb[NL80211_ATTR_EXT_CAPA]),
684 nla_len(tb[NL80211_ATTR_EXT_CAPA]));
685 drv->extended_capa_len =
686 nla_len(tb[NL80211_ATTR_EXT_CAPA]);
cc9a2575
KV
687 wpa_hexdump(MSG_DEBUG,
688 "nl80211: Driver-advertised extended capabilities (default)",
689 drv->extended_capa, drv->extended_capa_len);
0fafeb54
JM
690 }
691 drv->extended_capa_mask =
7b7b4449 692 os_malloc(nla_len(tb[NL80211_ATTR_EXT_CAPA_MASK]));
0fafeb54
JM
693 if (drv->extended_capa_mask) {
694 os_memcpy(drv->extended_capa_mask,
7b7b4449
LC
695 nla_data(tb[NL80211_ATTR_EXT_CAPA_MASK]),
696 nla_len(tb[NL80211_ATTR_EXT_CAPA_MASK]));
cc9a2575
KV
697 wpa_hexdump(MSG_DEBUG,
698 "nl80211: Driver-advertised extended capabilities mask (default)",
699 drv->extended_capa_mask,
700 drv->extended_capa_len);
0fafeb54
JM
701 } else {
702 os_free(drv->extended_capa);
703 drv->extended_capa = NULL;
704 drv->extended_capa_len = 0;
705 }
706 }
707
cc9a2575
KV
708 wiphy_info_extended_capab(drv, tb[NL80211_ATTR_IFTYPE_EXT_CAPA]);
709
0fafeb54
JM
710 if (tb[NL80211_ATTR_VENDOR_DATA]) {
711 struct nlattr *nl;
712 int rem;
713
714 nla_for_each_nested(nl, tb[NL80211_ATTR_VENDOR_DATA], rem) {
715 struct nl80211_vendor_cmd_info *vinfo;
716 if (nla_len(nl) != sizeof(*vinfo)) {
717 wpa_printf(MSG_DEBUG, "nl80211: Unexpected vendor data info");
718 continue;
719 }
720 vinfo = nla_data(nl);
5f9c92f8
ZK
721 if (vinfo->vendor_id == OUI_QCA) {
722 switch (vinfo->subcmd) {
723 case QCA_NL80211_VENDOR_SUBCMD_TEST:
724 drv->vendor_cmd_test_avail = 1;
725 break;
b658547d 726#ifdef CONFIG_DRIVER_NL80211_QCA
5f9c92f8
ZK
727 case QCA_NL80211_VENDOR_SUBCMD_ROAMING:
728 drv->roaming_vendor_cmd_avail = 1;
729 break;
730 case QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY:
731 drv->dfs_vendor_cmd_avail = 1;
732 break;
733 case QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES:
734 drv->get_features_vendor_cmd_avail = 1;
735 break;
98342208
AK
736 case QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST:
737 drv->get_pref_freq_list = 1;
738 break;
7c813acf
AK
739 case QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL:
740 drv->set_prob_oper_freq = 1;
741 break;
5f9c92f8
ZK
742 case QCA_NL80211_VENDOR_SUBCMD_DO_ACS:
743 drv->capa.flags |=
744 WPA_DRIVER_FLAGS_ACS_OFFLOAD;
745 break;
844dfeb8
SD
746 case QCA_NL80211_VENDOR_SUBCMD_SETBAND:
747 drv->setband_vendor_cmd_avail = 1;
748 break;
f22a080c
KV
749 case QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN:
750 drv->scan_vendor_cmd_avail = 1;
751 break;
cc9985d1 752 case QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION:
753 drv->set_wifi_conf_vendor_cmd_avail = 1;
754 break;
ca1ab9db
PX
755 case QCA_NL80211_VENDOR_SUBCMD_GET_HE_CAPABILITIES:
756 drv->he_capab_vendor_cmd_avail = 1;
757 break;
3ab48492
KV
758 case QCA_NL80211_VENDOR_SUBCMD_FETCH_BSS_TRANSITION_STATUS:
759 drv->fetch_bss_trans_status = 1;
760 break;
b04854ce
AP
761 case QCA_NL80211_VENDOR_SUBCMD_ROAM:
762 drv->roam_vendor_cmd_avail = 1;
763 break;
b658547d 764#endif /* CONFIG_DRIVER_NL80211_QCA */
5f9c92f8 765 }
0fafeb54
JM
766 }
767
768 wpa_printf(MSG_DEBUG, "nl80211: Supported vendor command: vendor_id=0x%x subcmd=%u",
769 vinfo->vendor_id, vinfo->subcmd);
770 }
771 }
772
773 if (tb[NL80211_ATTR_VENDOR_EVENTS]) {
774 struct nlattr *nl;
775 int rem;
776
777 nla_for_each_nested(nl, tb[NL80211_ATTR_VENDOR_EVENTS], rem) {
778 struct nl80211_vendor_cmd_info *vinfo;
779 if (nla_len(nl) != sizeof(*vinfo)) {
780 wpa_printf(MSG_DEBUG, "nl80211: Unexpected vendor data info");
781 continue;
782 }
783 vinfo = nla_data(nl);
0fafeb54
JM
784 wpa_printf(MSG_DEBUG, "nl80211: Supported vendor event: vendor_id=0x%x subcmd=%u",
785 vinfo->vendor_id, vinfo->subcmd);
786 }
787 }
788
789 wiphy_info_wowlan_triggers(capa,
790 tb[NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED]);
791
792 if (tb[NL80211_ATTR_MAX_AP_ASSOC_STA])
793 capa->max_stations =
794 nla_get_u32(tb[NL80211_ATTR_MAX_AP_ASSOC_STA]);
795
366179d2
AO
796 if (tb[NL80211_ATTR_MAX_CSA_COUNTERS])
797 capa->max_csa_counters =
798 nla_get_u8(tb[NL80211_ATTR_MAX_CSA_COUNTERS]);
799
0fafeb54
JM
800 return NL_SKIP;
801}
802
803
804static int wpa_driver_nl80211_get_info(struct wpa_driver_nl80211_data *drv,
805 struct wiphy_info_data *info)
806{
807 u32 feat;
808 struct nl_msg *msg;
9589a91e 809 int flags = 0;
0fafeb54
JM
810
811 os_memset(info, 0, sizeof(*info));
812 info->capa = &drv->capa;
813 info->drv = drv;
814
0fafeb54
JM
815 feat = get_nl80211_protocol_features(drv);
816 if (feat & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP)
9589a91e 817 flags = NLM_F_DUMP;
56f77852
JM
818 msg = nl80211_cmd_msg(drv->first_bss, flags, NL80211_CMD_GET_WIPHY);
819 if (!msg || nla_put_flag(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP)) {
9589a91e
JM
820 nlmsg_free(msg);
821 return -1;
822 }
0fafeb54
JM
823
824 if (send_and_recv_msgs(drv, msg, wiphy_info_handler, info))
825 return -1;
826
827 if (info->auth_supported)
828 drv->capa.flags |= WPA_DRIVER_FLAGS_SME;
829 else if (!info->connect_supported) {
830 wpa_printf(MSG_INFO, "nl80211: Driver does not support "
831 "authentication/association or connect commands");
832 info->error = 1;
833 }
834
835 if (info->p2p_go_supported && info->p2p_client_supported)
836 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CAPABLE;
837 if (info->p2p_concurrent) {
838 wpa_printf(MSG_DEBUG, "nl80211: Use separate P2P group "
839 "interface (driver advertised support)");
840 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
841 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;
842 }
843 if (info->num_multichan_concurrent > 1) {
844 wpa_printf(MSG_DEBUG, "nl80211: Enable multi-channel "
845 "concurrent (driver advertised support)");
846 drv->capa.num_multichan_concurrent =
847 info->num_multichan_concurrent;
848 }
849 if (drv->capa.flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
850 wpa_printf(MSG_DEBUG, "nl80211: use P2P_DEVICE support");
851
852 /* default to 5000 since early versions of mac80211 don't set it */
853 if (!drv->capa.max_remain_on_chan)
854 drv->capa.max_remain_on_chan = 5000;
855
dfa87878 856 drv->capa.wmm_ac_supported = info->wmm_ac_supported;
0fafeb54 857
86056fea
IP
858 drv->capa.mac_addr_rand_sched_scan_supported =
859 info->mac_addr_rand_sched_scan_supported;
860 drv->capa.mac_addr_rand_scan_supported =
861 info->mac_addr_rand_scan_supported;
862
366179d2
AO
863 if (info->channel_switch_supported) {
864 drv->capa.flags |= WPA_DRIVER_FLAGS_AP_CSA;
865 if (!drv->capa.max_csa_counters)
866 drv->capa.max_csa_counters = 1;
867 }
868
09ea4309
AS
869 if (!drv->capa.max_sched_scan_plans) {
870 drv->capa.max_sched_scan_plans = 1;
871 drv->capa.max_sched_scan_plan_interval = UINT32_MAX;
872 drv->capa.max_sched_scan_plan_iterations = 0;
873 }
874
0fafeb54 875 return 0;
0fafeb54
JM
876}
877
878
b658547d
JM
879#ifdef CONFIG_DRIVER_NL80211_QCA
880
0fafeb54
JM
881static int dfs_info_handler(struct nl_msg *msg, void *arg)
882{
883 struct nlattr *tb[NL80211_ATTR_MAX + 1];
884 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
885 int *dfs_capability_ptr = arg;
886
887 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
888 genlmsg_attrlen(gnlh, 0), NULL);
889
890 if (tb[NL80211_ATTR_VENDOR_DATA]) {
891 struct nlattr *nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
892 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_MAX + 1];
893
894 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_MAX,
895 nla_data(nl_vend), nla_len(nl_vend), NULL);
896
897 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_DFS]) {
898 u32 val;
899 val = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_DFS]);
900 wpa_printf(MSG_DEBUG, "nl80211: DFS offload capability: %u",
901 val);
902 *dfs_capability_ptr = val;
903 }
904 }
905
906 return NL_SKIP;
907}
908
909
910static void qca_nl80211_check_dfs_capa(struct wpa_driver_nl80211_data *drv)
911{
912 struct nl_msg *msg;
913 int dfs_capability = 0;
914 int ret;
915
916 if (!drv->dfs_vendor_cmd_avail)
917 return;
918
9725b784 919 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
9589a91e
JM
920 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
921 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
922 QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY)) {
923 nlmsg_free(msg);
924 return;
925 }
0fafeb54
JM
926
927 ret = send_and_recv_msgs(drv, msg, dfs_info_handler, &dfs_capability);
928 if (!ret && dfs_capability)
929 drv->capa.flags |= WPA_DRIVER_FLAGS_DFS_OFFLOAD;
0fafeb54
JM
930}
931
932
ca1ab9db
PX
933static int qca_nl80211_he_capab_handler(struct nl_msg *msg, void *arg)
934{
935 struct nlattr *tb[NL80211_ATTR_MAX + 1];
936 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
937 struct he_capabilities *he_capab = arg;
938 struct nlattr *nl_vend;
939 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_MAX + 1];
940 size_t len;
941
942 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
943 genlmsg_attrlen(gnlh, 0), NULL);
944
945 if (!tb[NL80211_ATTR_VENDOR_DATA])
946 return NL_SKIP;
947
948 nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
949 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_MAX,
950 nla_data(nl_vend), nla_len(nl_vend), NULL);
951
952 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_HE_SUPPORTED]) {
953 u8 he_supported;
954
955 he_supported = nla_get_u8(
956 tb_vendor[QCA_WLAN_VENDOR_ATTR_HE_SUPPORTED]);
957 wpa_printf(MSG_DEBUG, "nl80211: HE capabilities supported: %u",
958 he_supported);
959 he_capab->he_supported = he_supported;
960 if (!he_supported)
961 return NL_SKIP;
962 }
963
964 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_PHY_CAPAB]) {
965 len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_PHY_CAPAB]);
966
967 if (len > sizeof(he_capab->phy_cap))
968 len = sizeof(he_capab->phy_cap);
969 os_memcpy(he_capab->phy_cap,
970 nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_PHY_CAPAB]),
971 len);
972 }
973
974 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_MAC_CAPAB])
975 he_capab->mac_cap =
976 nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_MAC_CAPAB]);
977
978 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_HE_MCS])
979 he_capab->mcs =
980 nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_HE_MCS]);
981
982 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_NUM_SS])
983 he_capab->ppet.numss_m1 =
984 nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_NUM_SS]);
985
986 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_RU_IDX_MASK])
987 he_capab->ppet.ru_count =
988 nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_RU_IDX_MASK]);
989
990 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_PPE_THRESHOLD]) {
991 len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_PPE_THRESHOLD]);
992
993 if (len > sizeof(he_capab->ppet.ppet16_ppet8_ru3_ru0))
994 len = sizeof(he_capab->ppet.ppet16_ppet8_ru3_ru0);
995 os_memcpy(he_capab->ppet.ppet16_ppet8_ru3_ru0,
996 nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_PPE_THRESHOLD]),
997 len);
998 }
999
1000 return NL_SKIP;
1001}
1002
1003
1004static void qca_nl80211_check_he_capab(struct wpa_driver_nl80211_data *drv)
1005{
1006 struct nl_msg *msg;
1007 int ret;
1008
1009 if (!drv->he_capab_vendor_cmd_avail)
1010 return;
1011
1012 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
1013 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
1014 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
1015 QCA_NL80211_VENDOR_SUBCMD_GET_HE_CAPABILITIES)) {
1016 nlmsg_free(msg);
1017 return;
1018 }
1019
1020 ret = send_and_recv_msgs(drv, msg, qca_nl80211_he_capab_handler,
1021 &drv->he_capab);
1022 if (!ret && drv->he_capab.he_supported)
1023 drv->capa.flags |= WPA_DRIVER_FLAGS_HE_CAPABILITIES;
1024}
1025
1026
15badebd
CL
1027struct features_info {
1028 u8 *flags;
1029 size_t flags_len;
079a28f7 1030 struct wpa_driver_capa *capa;
15badebd
CL
1031};
1032
1033
1034static int features_info_handler(struct nl_msg *msg, void *arg)
1035{
1036 struct nlattr *tb[NL80211_ATTR_MAX + 1];
1037 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
1038 struct features_info *info = arg;
1039 struct nlattr *nl_vend, *attr;
1040
1041 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
1042 genlmsg_attrlen(gnlh, 0), NULL);
1043
1044 nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
1045 if (nl_vend) {
1046 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_MAX + 1];
1047
1048 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_MAX,
1049 nla_data(nl_vend), nla_len(nl_vend), NULL);
1050
1051 attr = tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS];
1052 if (attr) {
fdc1188a
PS
1053 int len = nla_len(attr);
1054 info->flags = os_malloc(len);
1055 if (info->flags != NULL) {
1056 os_memcpy(info->flags, nla_data(attr), len);
1057 info->flags_len = len;
1058 }
15badebd 1059 }
079a28f7
AK
1060 attr = tb_vendor[QCA_WLAN_VENDOR_ATTR_CONCURRENCY_CAPA];
1061 if (attr)
1062 info->capa->conc_capab = nla_get_u32(attr);
1063
1064 attr = tb_vendor[
1065 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND];
1066 if (attr)
1067 info->capa->max_conc_chan_2_4 = nla_get_u32(attr);
1068
1069 attr = tb_vendor[
1070 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND];
1071 if (attr)
1072 info->capa->max_conc_chan_5_0 = nla_get_u32(attr);
15badebd
CL
1073 }
1074
1075 return NL_SKIP;
1076}
1077
1078
1079static int check_feature(enum qca_wlan_vendor_features feature,
1080 struct features_info *info)
1081{
49e3eea8 1082 size_t idx = feature / 8;
15badebd 1083
49e3eea8
JM
1084 return (idx < info->flags_len) &&
1085 (info->flags[idx] & BIT(feature % 8));
15badebd
CL
1086}
1087
1088
1089static void qca_nl80211_get_features(struct wpa_driver_nl80211_data *drv)
1090{
1091 struct nl_msg *msg;
1092 struct features_info info;
1093 int ret;
1094
1095 if (!drv->get_features_vendor_cmd_avail)
1096 return;
1097
1098 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
1099 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
1100 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
1101 QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES)) {
1102 nlmsg_free(msg);
1103 return;
1104 }
1105
1106 os_memset(&info, 0, sizeof(info));
079a28f7 1107 info.capa = &drv->capa;
15badebd
CL
1108 ret = send_and_recv_msgs(drv, msg, features_info_handler, &info);
1109 if (ret || !info.flags)
1110 return;
1111
1112 if (check_feature(QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD, &info))
1113 drv->capa.flags |= WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD;
3784c058
PX
1114
1115 if (check_feature(QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY, &info))
1116 drv->capa.flags |= WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY;
8e509745
KV
1117
1118 if (check_feature(QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS,
1119 &info))
1120 drv->capa.flags |= WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS;
a6f5b193
PX
1121 if (check_feature(QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD, &info))
1122 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_LISTEN_OFFLOAD;
fb718f94
AP
1123 if (check_feature(QCA_WLAN_VENDOR_FEATURE_OCE_STA, &info))
1124 drv->capa.flags |= WPA_DRIVER_FLAGS_OCE_STA;
1125 if (check_feature(QCA_WLAN_VENDOR_FEATURE_OCE_AP, &info))
1126 drv->capa.flags |= WPA_DRIVER_FLAGS_OCE_AP;
1127 if (check_feature(QCA_WLAN_VENDOR_FEATURE_OCE_STA_CFON, &info))
1128 drv->capa.flags |= WPA_DRIVER_FLAGS_OCE_STA_CFON;
fdc1188a 1129 os_free(info.flags);
15badebd
CL
1130}
1131
b658547d
JM
1132#endif /* CONFIG_DRIVER_NL80211_QCA */
1133
15badebd 1134
0fafeb54
JM
1135int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
1136{
1137 struct wiphy_info_data info;
1138 if (wpa_driver_nl80211_get_info(drv, &info))
1139 return -1;
1140
1141 if (info.error)
1142 return -1;
1143
1144 drv->has_capability = 1;
1145 drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1146 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
1147 WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
399e6135
JM
1148 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK |
1149 WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B |
f9561868 1150 WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192 |
567da5bb
JM
1151 WPA_DRIVER_CAPA_KEY_MGMT_OWE |
1152 WPA_DRIVER_CAPA_KEY_MGMT_DPP;
fe3e0bac
VK
1153
1154 if (drv->capa.flags & WPA_DRIVER_FLAGS_SME)
1155 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256 |
1156 WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384 |
1157 WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256 |
1158 WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384;
1159 else if (drv->capa.flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)
1160 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256 |
1161 WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384;
1162
0fafeb54
JM
1163 drv->capa.auth = WPA_DRIVER_AUTH_OPEN |
1164 WPA_DRIVER_AUTH_SHARED |
1165 WPA_DRIVER_AUTH_LEAP;
1166
1167 drv->capa.flags |= WPA_DRIVER_FLAGS_SANE_ERROR_CODES;
1168 drv->capa.flags |= WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE;
1169 drv->capa.flags |= WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
1170
1171 /*
1172 * As all cfg80211 drivers must support cases where the AP interface is
1173 * removed without the knowledge of wpa_supplicant/hostapd, e.g., in
1174 * case that the user space daemon has crashed, they must be able to
1175 * cleanup all stations and key entries in the AP tear down flow. Thus,
1176 * this flag can/should always be set for cfg80211 drivers.
1177 */
1178 drv->capa.flags |= WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT;
1179
1180 if (!info.device_ap_sme) {
1181 drv->capa.flags |= WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS;
1182
1183 /*
1184 * No AP SME is currently assumed to also indicate no AP MLME
1185 * in the driver/firmware.
1186 */
1187 drv->capa.flags |= WPA_DRIVER_FLAGS_AP_MLME;
1188 }
1189
1190 drv->device_ap_sme = info.device_ap_sme;
1191 drv->poll_command_supported = info.poll_command_supported;
1192 drv->data_tx_status = info.data_tx_status;
abb8d08b 1193 drv->p2p_go_ctwindow_supported = info.p2p_go_ctwindow_supported;
0fafeb54
JM
1194 if (info.set_qos_map_supported)
1195 drv->capa.flags |= WPA_DRIVER_FLAGS_QOS_MAPPING;
1196 drv->have_low_prio_scan = info.have_low_prio_scan;
1197
1198 /*
1199 * If poll command and tx status are supported, mac80211 is new enough
1200 * to have everything we need to not need monitor interfaces.
1201 */
660103ec
SD
1202 drv->use_monitor = !info.device_ap_sme &&
1203 (!info.poll_command_supported || !info.data_tx_status);
0fafeb54
JM
1204
1205 /*
1206 * If we aren't going to use monitor interfaces, but the
1207 * driver doesn't support data TX status, we won't get TX
1208 * status for EAPOL frames.
1209 */
1210 if (!drv->use_monitor && !info.data_tx_status)
1211 drv->capa.flags &= ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
1212
b658547d 1213#ifdef CONFIG_DRIVER_NL80211_QCA
0fafeb54 1214 qca_nl80211_check_dfs_capa(drv);
15badebd 1215 qca_nl80211_get_features(drv);
ca1ab9db 1216 qca_nl80211_check_he_capab(drv);
0fafeb54 1217
8e509745
KV
1218 /*
1219 * To enable offchannel simultaneous support in wpa_supplicant, the
1220 * underlying driver needs to support the same along with offchannel TX.
1221 * Offchannel TX support is needed since remain_on_channel and
1222 * action_tx use some common data structures and hence cannot be
1223 * scheduled simultaneously.
1224 */
1225 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX))
1226 drv->capa.flags &= ~WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS;
b658547d 1227#endif /* CONFIG_DRIVER_NL80211_QCA */
8e509745 1228
0fafeb54
JM
1229 return 0;
1230}
1231
1232
1233struct phy_info_arg {
1234 u16 *num_modes;
1235 struct hostapd_hw_modes *modes;
1236 int last_mode, last_chan_idx;
747ba106 1237 int failed;
aa56e36d 1238 u8 dfs_domain;
0fafeb54
JM
1239};
1240
1241static void phy_info_ht_capa(struct hostapd_hw_modes *mode, struct nlattr *capa,
1242 struct nlattr *ampdu_factor,
1243 struct nlattr *ampdu_density,
1244 struct nlattr *mcs_set)
1245{
1246 if (capa)
1247 mode->ht_capab = nla_get_u16(capa);
1248
1249 if (ampdu_factor)
1250 mode->a_mpdu_params |= nla_get_u8(ampdu_factor) & 0x03;
1251
1252 if (ampdu_density)
1253 mode->a_mpdu_params |= nla_get_u8(ampdu_density) << 2;
1254
1255 if (mcs_set && nla_len(mcs_set) >= 16) {
1256 u8 *mcs;
1257 mcs = nla_data(mcs_set);
1258 os_memcpy(mode->mcs_set, mcs, 16);
1259 }
1260}
1261
1262
1263static void phy_info_vht_capa(struct hostapd_hw_modes *mode,
1264 struct nlattr *capa,
1265 struct nlattr *mcs_set)
1266{
1267 if (capa)
1268 mode->vht_capab = nla_get_u32(capa);
1269
1270 if (mcs_set && nla_len(mcs_set) >= 8) {
1271 u8 *mcs;
1272 mcs = nla_data(mcs_set);
1273 os_memcpy(mode->vht_mcs_set, mcs, 8);
1274 }
1275}
1276
1277
1278static void phy_info_freq(struct hostapd_hw_modes *mode,
1279 struct hostapd_channel_data *chan,
1280 struct nlattr *tb_freq[])
1281{
1282 u8 channel;
1283 chan->freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
1284 chan->flag = 0;
1285 chan->dfs_cac_ms = 0;
1286 if (ieee80211_freq_to_chan(chan->freq, &channel) != NUM_HOSTAPD_MODES)
1287 chan->chan = channel;
1288
1289 if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
1290 chan->flag |= HOSTAPD_CHAN_DISABLED;
1291 if (tb_freq[NL80211_FREQUENCY_ATTR_NO_IR])
1292 chan->flag |= HOSTAPD_CHAN_NO_IR;
1293 if (tb_freq[NL80211_FREQUENCY_ATTR_RADAR])
1294 chan->flag |= HOSTAPD_CHAN_RADAR;
1295 if (tb_freq[NL80211_FREQUENCY_ATTR_INDOOR_ONLY])
1296 chan->flag |= HOSTAPD_CHAN_INDOOR_ONLY;
1297 if (tb_freq[NL80211_FREQUENCY_ATTR_GO_CONCURRENT])
1298 chan->flag |= HOSTAPD_CHAN_GO_CONCURRENT;
1299
1300 if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]) {
1301 enum nl80211_dfs_state state =
1302 nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]);
1303
1304 switch (state) {
1305 case NL80211_DFS_USABLE:
1306 chan->flag |= HOSTAPD_CHAN_DFS_USABLE;
1307 break;
1308 case NL80211_DFS_AVAILABLE:
1309 chan->flag |= HOSTAPD_CHAN_DFS_AVAILABLE;
1310 break;
1311 case NL80211_DFS_UNAVAILABLE:
1312 chan->flag |= HOSTAPD_CHAN_DFS_UNAVAILABLE;
1313 break;
1314 }
1315 }
1316
1317 if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME]) {
1318 chan->dfs_cac_ms = nla_get_u32(
1319 tb_freq[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME]);
1320 }
1321}
1322
1323
1324static int phy_info_freqs(struct phy_info_arg *phy_info,
1325 struct hostapd_hw_modes *mode, struct nlattr *tb)
1326{
1327 static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
1328 [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 },
1329 [NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG },
1330 [NL80211_FREQUENCY_ATTR_NO_IR] = { .type = NLA_FLAG },
1331 [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG },
1332 [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 },
1333 [NL80211_FREQUENCY_ATTR_DFS_STATE] = { .type = NLA_U32 },
1334 };
1335 int new_channels = 0;
1336 struct hostapd_channel_data *channel;
1337 struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1];
1338 struct nlattr *nl_freq;
1339 int rem_freq, idx;
1340
1341 if (tb == NULL)
1342 return NL_OK;
1343
1344 nla_for_each_nested(nl_freq, tb, rem_freq) {
1345 nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX,
1346 nla_data(nl_freq), nla_len(nl_freq), freq_policy);
1347 if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
1348 continue;
1349 new_channels++;
1350 }
1351
1352 channel = os_realloc_array(mode->channels,
1353 mode->num_channels + new_channels,
1354 sizeof(struct hostapd_channel_data));
1355 if (!channel)
747ba106 1356 return NL_STOP;
0fafeb54
JM
1357
1358 mode->channels = channel;
1359 mode->num_channels += new_channels;
1360
1361 idx = phy_info->last_chan_idx;
1362
1363 nla_for_each_nested(nl_freq, tb, rem_freq) {
1364 nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX,
1365 nla_data(nl_freq), nla_len(nl_freq), freq_policy);
1366 if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
1367 continue;
1368 phy_info_freq(mode, &mode->channels[idx], tb_freq);
1369 idx++;
1370 }
1371 phy_info->last_chan_idx = idx;
1372
1373 return NL_OK;
1374}
1375
1376
1377static int phy_info_rates(struct hostapd_hw_modes *mode, struct nlattr *tb)
1378{
1379 static struct nla_policy rate_policy[NL80211_BITRATE_ATTR_MAX + 1] = {
1380 [NL80211_BITRATE_ATTR_RATE] = { .type = NLA_U32 },
1381 [NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE] =
1382 { .type = NLA_FLAG },
1383 };
1384 struct nlattr *tb_rate[NL80211_BITRATE_ATTR_MAX + 1];
1385 struct nlattr *nl_rate;
1386 int rem_rate, idx;
1387
1388 if (tb == NULL)
1389 return NL_OK;
1390
1391 nla_for_each_nested(nl_rate, tb, rem_rate) {
1392 nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX,
1393 nla_data(nl_rate), nla_len(nl_rate),
1394 rate_policy);
1395 if (!tb_rate[NL80211_BITRATE_ATTR_RATE])
1396 continue;
1397 mode->num_rates++;
1398 }
1399
1400 mode->rates = os_calloc(mode->num_rates, sizeof(int));
1401 if (!mode->rates)
747ba106 1402 return NL_STOP;
0fafeb54
JM
1403
1404 idx = 0;
1405
1406 nla_for_each_nested(nl_rate, tb, rem_rate) {
1407 nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX,
1408 nla_data(nl_rate), nla_len(nl_rate),
1409 rate_policy);
1410 if (!tb_rate[NL80211_BITRATE_ATTR_RATE])
1411 continue;
1412 mode->rates[idx] = nla_get_u32(
1413 tb_rate[NL80211_BITRATE_ATTR_RATE]);
1414 idx++;
1415 }
1416
1417 return NL_OK;
1418}
1419
1420
1421static int phy_info_band(struct phy_info_arg *phy_info, struct nlattr *nl_band)
1422{
1423 struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1];
1424 struct hostapd_hw_modes *mode;
1425 int ret;
1426
1427 if (phy_info->last_mode != nl_band->nla_type) {
1428 mode = os_realloc_array(phy_info->modes,
1429 *phy_info->num_modes + 1,
1430 sizeof(*mode));
747ba106
JM
1431 if (!mode) {
1432 phy_info->failed = 1;
1433 return NL_STOP;
1434 }
0fafeb54
JM
1435 phy_info->modes = mode;
1436
1437 mode = &phy_info->modes[*(phy_info->num_modes)];
1438 os_memset(mode, 0, sizeof(*mode));
1439 mode->mode = NUM_HOSTAPD_MODES;
1440 mode->flags = HOSTAPD_MODE_FLAG_HT_INFO_KNOWN |
1441 HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN;
1442
1443 /*
1444 * Unsupported VHT MCS stream is defined as value 3, so the VHT
1445 * MCS RX/TX map must be initialized with 0xffff to mark all 8
1446 * possible streams as unsupported. This will be overridden if
1447 * driver advertises VHT support.
1448 */
1449 mode->vht_mcs_set[0] = 0xff;
1450 mode->vht_mcs_set[1] = 0xff;
1451 mode->vht_mcs_set[4] = 0xff;
1452 mode->vht_mcs_set[5] = 0xff;
1453
1454 *(phy_info->num_modes) += 1;
1455 phy_info->last_mode = nl_band->nla_type;
1456 phy_info->last_chan_idx = 0;
1457 } else
1458 mode = &phy_info->modes[*(phy_info->num_modes) - 1];
1459
1460 nla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band),
1461 nla_len(nl_band), NULL);
1462
1463 phy_info_ht_capa(mode, tb_band[NL80211_BAND_ATTR_HT_CAPA],
1464 tb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR],
1465 tb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY],
1466 tb_band[NL80211_BAND_ATTR_HT_MCS_SET]);
1467 phy_info_vht_capa(mode, tb_band[NL80211_BAND_ATTR_VHT_CAPA],
1468 tb_band[NL80211_BAND_ATTR_VHT_MCS_SET]);
1469 ret = phy_info_freqs(phy_info, mode, tb_band[NL80211_BAND_ATTR_FREQS]);
747ba106
JM
1470 if (ret == NL_OK)
1471 ret = phy_info_rates(mode, tb_band[NL80211_BAND_ATTR_RATES]);
1472 if (ret != NL_OK) {
1473 phy_info->failed = 1;
0fafeb54 1474 return ret;
747ba106 1475 }
0fafeb54
JM
1476
1477 return NL_OK;
1478}
1479
1480
1481static int phy_info_handler(struct nl_msg *msg, void *arg)
1482{
1483 struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
1484 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
1485 struct phy_info_arg *phy_info = arg;
1486 struct nlattr *nl_band;
1487 int rem_band;
1488
1489 nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
1490 genlmsg_attrlen(gnlh, 0), NULL);
1491
1492 if (!tb_msg[NL80211_ATTR_WIPHY_BANDS])
1493 return NL_SKIP;
1494
1495 nla_for_each_nested(nl_band, tb_msg[NL80211_ATTR_WIPHY_BANDS], rem_band)
1496 {
1497 int res = phy_info_band(phy_info, nl_band);
1498 if (res != NL_OK)
1499 return res;
1500 }
1501
1502 return NL_SKIP;
1503}
1504
1505
1506static struct hostapd_hw_modes *
1507wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes *modes,
1508 u16 *num_modes)
1509{
1510 u16 m;
1511 struct hostapd_hw_modes *mode11g = NULL, *nmodes, *mode;
1512 int i, mode11g_idx = -1;
1513
1514 /* heuristic to set up modes */
1515 for (m = 0; m < *num_modes; m++) {
1516 if (!modes[m].num_channels)
1517 continue;
1518 if (modes[m].channels[0].freq < 4000) {
1519 modes[m].mode = HOSTAPD_MODE_IEEE80211B;
1520 for (i = 0; i < modes[m].num_rates; i++) {
1521 if (modes[m].rates[i] > 200) {
1522 modes[m].mode = HOSTAPD_MODE_IEEE80211G;
1523 break;
1524 }
1525 }
1526 } else if (modes[m].channels[0].freq > 50000)
1527 modes[m].mode = HOSTAPD_MODE_IEEE80211AD;
1528 else
1529 modes[m].mode = HOSTAPD_MODE_IEEE80211A;
1530 }
1531
1532 /* If only 802.11g mode is included, use it to construct matching
1533 * 802.11b mode data. */
1534
1535 for (m = 0; m < *num_modes; m++) {
1536 if (modes[m].mode == HOSTAPD_MODE_IEEE80211B)
1537 return modes; /* 802.11b already included */
1538 if (modes[m].mode == HOSTAPD_MODE_IEEE80211G)
1539 mode11g_idx = m;
1540 }
1541
1542 if (mode11g_idx < 0)
1543 return modes; /* 2.4 GHz band not supported at all */
1544
1545 nmodes = os_realloc_array(modes, *num_modes + 1, sizeof(*nmodes));
1546 if (nmodes == NULL)
1547 return modes; /* Could not add 802.11b mode */
1548
1549 mode = &nmodes[*num_modes];
1550 os_memset(mode, 0, sizeof(*mode));
1551 (*num_modes)++;
1552 modes = nmodes;
1553
1554 mode->mode = HOSTAPD_MODE_IEEE80211B;
1555
1556 mode11g = &modes[mode11g_idx];
1557 mode->num_channels = mode11g->num_channels;
a1f11e34
JB
1558 mode->channels = os_memdup(mode11g->channels,
1559 mode11g->num_channels *
0fafeb54
JM
1560 sizeof(struct hostapd_channel_data));
1561 if (mode->channels == NULL) {
1562 (*num_modes)--;
1563 return modes; /* Could not add 802.11b mode */
1564 }
0fafeb54
JM
1565
1566 mode->num_rates = 0;
1567 mode->rates = os_malloc(4 * sizeof(int));
1568 if (mode->rates == NULL) {
1569 os_free(mode->channels);
1570 (*num_modes)--;
1571 return modes; /* Could not add 802.11b mode */
1572 }
1573
1574 for (i = 0; i < mode11g->num_rates; i++) {
1575 if (mode11g->rates[i] != 10 && mode11g->rates[i] != 20 &&
1576 mode11g->rates[i] != 55 && mode11g->rates[i] != 110)
1577 continue;
1578 mode->rates[mode->num_rates] = mode11g->rates[i];
1579 mode->num_rates++;
1580 if (mode->num_rates == 4)
1581 break;
1582 }
1583
1584 if (mode->num_rates == 0) {
1585 os_free(mode->channels);
1586 os_free(mode->rates);
1587 (*num_modes)--;
1588 return modes; /* No 802.11b rates */
1589 }
1590
1591 wpa_printf(MSG_DEBUG, "nl80211: Added 802.11b mode based on 802.11g "
1592 "information");
1593
1594 return modes;
1595}
1596
1597
1598static void nl80211_set_ht40_mode(struct hostapd_hw_modes *mode, int start,
1599 int end)
1600{
1601 int c;
1602
1603 for (c = 0; c < mode->num_channels; c++) {
1604 struct hostapd_channel_data *chan = &mode->channels[c];
1605 if (chan->freq - 10 >= start && chan->freq + 10 <= end)
1606 chan->flag |= HOSTAPD_CHAN_HT40;
1607 }
1608}
1609
1610
1611static void nl80211_set_ht40_mode_sec(struct hostapd_hw_modes *mode, int start,
1612 int end)
1613{
1614 int c;
1615
1616 for (c = 0; c < mode->num_channels; c++) {
1617 struct hostapd_channel_data *chan = &mode->channels[c];
1618 if (!(chan->flag & HOSTAPD_CHAN_HT40))
1619 continue;
1620 if (chan->freq - 30 >= start && chan->freq - 10 <= end)
1621 chan->flag |= HOSTAPD_CHAN_HT40MINUS;
1622 if (chan->freq + 10 >= start && chan->freq + 30 <= end)
1623 chan->flag |= HOSTAPD_CHAN_HT40PLUS;
1624 }
1625}
1626
1627
1628static void nl80211_reg_rule_max_eirp(u32 start, u32 end, u32 max_eirp,
1629 struct phy_info_arg *results)
1630{
1631 u16 m;
1632
1633 for (m = 0; m < *results->num_modes; m++) {
1634 int c;
1635 struct hostapd_hw_modes *mode = &results->modes[m];
1636
1637 for (c = 0; c < mode->num_channels; c++) {
1638 struct hostapd_channel_data *chan = &mode->channels[c];
1639 if ((u32) chan->freq - 10 >= start &&
1640 (u32) chan->freq + 10 <= end)
1641 chan->max_tx_power = max_eirp;
1642 }
1643 }
1644}
1645
1646
1647static void nl80211_reg_rule_ht40(u32 start, u32 end,
1648 struct phy_info_arg *results)
1649{
1650 u16 m;
1651
1652 for (m = 0; m < *results->num_modes; m++) {
1653 if (!(results->modes[m].ht_capab &
1654 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
1655 continue;
1656 nl80211_set_ht40_mode(&results->modes[m], start, end);
1657 }
1658}
1659
1660
1661static void nl80211_reg_rule_sec(struct nlattr *tb[],
1662 struct phy_info_arg *results)
1663{
1664 u32 start, end, max_bw;
1665 u16 m;
1666
1667 if (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL ||
1668 tb[NL80211_ATTR_FREQ_RANGE_END] == NULL ||
1669 tb[NL80211_ATTR_FREQ_RANGE_MAX_BW] == NULL)
1670 return;
1671
1672 start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
1673 end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
1674 max_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
1675
1676 if (max_bw < 20)
1677 return;
1678
1679 for (m = 0; m < *results->num_modes; m++) {
1680 if (!(results->modes[m].ht_capab &
1681 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
1682 continue;
1683 nl80211_set_ht40_mode_sec(&results->modes[m], start, end);
1684 }
1685}
1686
1687
1688static void nl80211_set_vht_mode(struct hostapd_hw_modes *mode, int start,
bee5d8e0 1689 int end, int max_bw)
0fafeb54
JM
1690{
1691 int c;
1692
1693 for (c = 0; c < mode->num_channels; c++) {
1694 struct hostapd_channel_data *chan = &mode->channels[c];
1695 if (chan->freq - 10 >= start && chan->freq + 70 <= end)
1696 chan->flag |= HOSTAPD_CHAN_VHT_10_70;
1697
1698 if (chan->freq - 30 >= start && chan->freq + 50 <= end)
1699 chan->flag |= HOSTAPD_CHAN_VHT_30_50;
1700
1701 if (chan->freq - 50 >= start && chan->freq + 30 <= end)
1702 chan->flag |= HOSTAPD_CHAN_VHT_50_30;
1703
1704 if (chan->freq - 70 >= start && chan->freq + 10 <= end)
1705 chan->flag |= HOSTAPD_CHAN_VHT_70_10;
bee5d8e0
AK
1706
1707 if (max_bw >= 160) {
1708 if (chan->freq - 10 >= start && chan->freq + 150 <= end)
1709 chan->flag |= HOSTAPD_CHAN_VHT_10_150;
1710
1711 if (chan->freq - 30 >= start && chan->freq + 130 <= end)
1712 chan->flag |= HOSTAPD_CHAN_VHT_30_130;
1713
1714 if (chan->freq - 50 >= start && chan->freq + 110 <= end)
1715 chan->flag |= HOSTAPD_CHAN_VHT_50_110;
1716
1717 if (chan->freq - 70 >= start && chan->freq + 90 <= end)
1718 chan->flag |= HOSTAPD_CHAN_VHT_70_90;
1719
1720 if (chan->freq - 90 >= start && chan->freq + 70 <= end)
1721 chan->flag |= HOSTAPD_CHAN_VHT_90_70;
1722
1723 if (chan->freq - 110 >= start && chan->freq + 50 <= end)
1724 chan->flag |= HOSTAPD_CHAN_VHT_110_50;
1725
1726 if (chan->freq - 130 >= start && chan->freq + 30 <= end)
1727 chan->flag |= HOSTAPD_CHAN_VHT_130_30;
1728
1729 if (chan->freq - 150 >= start && chan->freq + 10 <= end)
1730 chan->flag |= HOSTAPD_CHAN_VHT_150_10;
1731 }
0fafeb54
JM
1732 }
1733}
1734
1735
1736static void nl80211_reg_rule_vht(struct nlattr *tb[],
1737 struct phy_info_arg *results)
1738{
1739 u32 start, end, max_bw;
1740 u16 m;
1741
1742 if (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL ||
1743 tb[NL80211_ATTR_FREQ_RANGE_END] == NULL ||
1744 tb[NL80211_ATTR_FREQ_RANGE_MAX_BW] == NULL)
1745 return;
1746
1747 start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
1748 end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
1749 max_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
1750
1751 if (max_bw < 80)
1752 return;
1753
1754 for (m = 0; m < *results->num_modes; m++) {
1755 if (!(results->modes[m].ht_capab &
1756 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
1757 continue;
1758 /* TODO: use a real VHT support indication */
1759 if (!results->modes[m].vht_capab)
1760 continue;
1761
bee5d8e0 1762 nl80211_set_vht_mode(&results->modes[m], start, end, max_bw);
0fafeb54
JM
1763 }
1764}
1765
1766
aa56e36d
VT
1767static void nl80211_set_dfs_domain(enum nl80211_dfs_regions region,
1768 u8 *dfs_domain)
1769{
1770 if (region == NL80211_DFS_FCC)
1771 *dfs_domain = HOSTAPD_DFS_REGION_FCC;
1772 else if (region == NL80211_DFS_ETSI)
1773 *dfs_domain = HOSTAPD_DFS_REGION_ETSI;
1774 else if (region == NL80211_DFS_JP)
1775 *dfs_domain = HOSTAPD_DFS_REGION_JP;
1776 else
1777 *dfs_domain = 0;
1778}
1779
1780
0fafeb54
JM
1781static const char * dfs_domain_name(enum nl80211_dfs_regions region)
1782{
1783 switch (region) {
1784 case NL80211_DFS_UNSET:
1785 return "DFS-UNSET";
1786 case NL80211_DFS_FCC:
1787 return "DFS-FCC";
1788 case NL80211_DFS_ETSI:
1789 return "DFS-ETSI";
1790 case NL80211_DFS_JP:
1791 return "DFS-JP";
1792 default:
1793 return "DFS-invalid";
1794 }
1795}
1796
1797
1798static int nl80211_get_reg(struct nl_msg *msg, void *arg)
1799{
1800 struct phy_info_arg *results = arg;
1801 struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
1802 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
1803 struct nlattr *nl_rule;
1804 struct nlattr *tb_rule[NL80211_FREQUENCY_ATTR_MAX + 1];
1805 int rem_rule;
1806 static struct nla_policy reg_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
1807 [NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 },
1808 [NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 },
1809 [NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 },
1810 [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 },
1811 [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 },
1812 [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },
1813 };
1814
1815 nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
1816 genlmsg_attrlen(gnlh, 0), NULL);
1817 if (!tb_msg[NL80211_ATTR_REG_ALPHA2] ||
1818 !tb_msg[NL80211_ATTR_REG_RULES]) {
1819 wpa_printf(MSG_DEBUG, "nl80211: No regulatory information "
1820 "available");
1821 return NL_SKIP;
1822 }
1823
1824 if (tb_msg[NL80211_ATTR_DFS_REGION]) {
1825 enum nl80211_dfs_regions dfs_domain;
1826 dfs_domain = nla_get_u8(tb_msg[NL80211_ATTR_DFS_REGION]);
aa56e36d 1827 nl80211_set_dfs_domain(dfs_domain, &results->dfs_domain);
0fafeb54
JM
1828 wpa_printf(MSG_DEBUG, "nl80211: Regulatory information - country=%s (%s)",
1829 (char *) nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]),
1830 dfs_domain_name(dfs_domain));
1831 } else {
1832 wpa_printf(MSG_DEBUG, "nl80211: Regulatory information - country=%s",
1833 (char *) nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]));
1834 }
1835
1836 nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
1837 {
1838 u32 start, end, max_eirp = 0, max_bw = 0, flags = 0;
1839 nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,
1840 nla_data(nl_rule), nla_len(nl_rule), reg_policy);
1841 if (tb_rule[NL80211_ATTR_FREQ_RANGE_START] == NULL ||
1842 tb_rule[NL80211_ATTR_FREQ_RANGE_END] == NULL)
1843 continue;
1844 start = nla_get_u32(tb_rule[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
1845 end = nla_get_u32(tb_rule[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
1846 if (tb_rule[NL80211_ATTR_POWER_RULE_MAX_EIRP])
1847 max_eirp = nla_get_u32(tb_rule[NL80211_ATTR_POWER_RULE_MAX_EIRP]) / 100;
1848 if (tb_rule[NL80211_ATTR_FREQ_RANGE_MAX_BW])
1849 max_bw = nla_get_u32(tb_rule[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
1850 if (tb_rule[NL80211_ATTR_REG_RULE_FLAGS])
1851 flags = nla_get_u32(tb_rule[NL80211_ATTR_REG_RULE_FLAGS]);
1852
1853 wpa_printf(MSG_DEBUG, "nl80211: %u-%u @ %u MHz %u mBm%s%s%s%s%s%s%s%s",
1854 start, end, max_bw, max_eirp,
1855 flags & NL80211_RRF_NO_OFDM ? " (no OFDM)" : "",
1856 flags & NL80211_RRF_NO_CCK ? " (no CCK)" : "",
1857 flags & NL80211_RRF_NO_INDOOR ? " (no indoor)" : "",
1858 flags & NL80211_RRF_NO_OUTDOOR ? " (no outdoor)" :
1859 "",
1860 flags & NL80211_RRF_DFS ? " (DFS)" : "",
1861 flags & NL80211_RRF_PTP_ONLY ? " (PTP only)" : "",
1862 flags & NL80211_RRF_PTMP_ONLY ? " (PTMP only)" : "",
1863 flags & NL80211_RRF_NO_IR ? " (no IR)" : "");
1864 if (max_bw >= 40)
1865 nl80211_reg_rule_ht40(start, end, results);
1866 if (tb_rule[NL80211_ATTR_POWER_RULE_MAX_EIRP])
1867 nl80211_reg_rule_max_eirp(start, end, max_eirp,
1868 results);
1869 }
1870
1871 nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
1872 {
1873 nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,
1874 nla_data(nl_rule), nla_len(nl_rule), reg_policy);
1875 nl80211_reg_rule_sec(tb_rule, results);
1876 }
1877
1878 nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
1879 {
1880 nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,
1881 nla_data(nl_rule), nla_len(nl_rule), reg_policy);
1882 nl80211_reg_rule_vht(tb_rule, results);
1883 }
1884
1885 return NL_SKIP;
1886}
1887
1888
1889static int nl80211_set_regulatory_flags(struct wpa_driver_nl80211_data *drv,
1890 struct phy_info_arg *results)
1891{
1892 struct nl_msg *msg;
1893
1894 msg = nlmsg_alloc();
1895 if (!msg)
1896 return -ENOMEM;
1897
1898 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_REG);
1899 return send_and_recv_msgs(drv, msg, nl80211_get_reg, results);
1900}
1901
1902
1903struct hostapd_hw_modes *
aa56e36d
VT
1904nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags,
1905 u8 *dfs_domain)
0fafeb54
JM
1906{
1907 u32 feat;
1908 struct i802_bss *bss = priv;
1909 struct wpa_driver_nl80211_data *drv = bss->drv;
9589a91e 1910 int nl_flags = 0;
0fafeb54
JM
1911 struct nl_msg *msg;
1912 struct phy_info_arg result = {
1913 .num_modes = num_modes,
1914 .modes = NULL,
1915 .last_mode = -1,
747ba106 1916 .failed = 0,
aa56e36d 1917 .dfs_domain = 0,
0fafeb54
JM
1918 };
1919
1920 *num_modes = 0;
1921 *flags = 0;
aa56e36d 1922 *dfs_domain = 0;
0fafeb54 1923
0fafeb54
JM
1924 feat = get_nl80211_protocol_features(drv);
1925 if (feat & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP)
9589a91e 1926 nl_flags = NLM_F_DUMP;
56f77852
JM
1927 if (!(msg = nl80211_cmd_msg(bss, nl_flags, NL80211_CMD_GET_WIPHY)) ||
1928 nla_put_flag(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP)) {
9589a91e
JM
1929 nlmsg_free(msg);
1930 return NULL;
1931 }
0fafeb54
JM
1932
1933 if (send_and_recv_msgs(drv, msg, phy_info_handler, &result) == 0) {
1934 nl80211_set_regulatory_flags(drv, &result);
747ba106
JM
1935 if (result.failed) {
1936 int i;
1937
1938 for (i = 0; result.modes && i < *num_modes; i++) {
1939 os_free(result.modes[i].channels);
1940 os_free(result.modes[i].rates);
1941 }
1942 os_free(result.modes);
517b5f92 1943 *num_modes = 0;
747ba106
JM
1944 return NULL;
1945 }
aa56e36d
VT
1946
1947 *dfs_domain = result.dfs_domain;
1948
0fafeb54
JM
1949 return wpa_driver_nl80211_postprocess_modes(result.modes,
1950 num_modes);
1951 }
9589a91e 1952
0fafeb54
JM
1953 return NULL;
1954}