2 * Driver interaction with Linux nl80211/cfg80211 - Capabilities
3 * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
4 * Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
5 * Copyright (c) 2009-2010, Atheros Communications
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
12 #include <netlink/genl/genl.h>
14 #include "utils/common.h"
15 #include "common/ieee802_11_common.h"
16 #include "common/wpa_common.h"
17 #include "common/qca-vendor.h"
18 #include "common/qca-vendor-attr.h"
19 #include "driver_nl80211.h"
22 static int protocol_feature_handler(struct nl_msg
*msg
, void *arg
)
25 struct nlattr
*tb_msg
[NL80211_ATTR_MAX
+ 1];
26 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
28 nla_parse(tb_msg
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
29 genlmsg_attrlen(gnlh
, 0), NULL
);
31 if (tb_msg
[NL80211_ATTR_PROTOCOL_FEATURES
])
32 *feat
= nla_get_u32(tb_msg
[NL80211_ATTR_PROTOCOL_FEATURES
]);
38 static u32
get_nl80211_protocol_features(struct wpa_driver_nl80211_data
*drv
)
47 if (!nl80211_cmd(drv
, msg
, 0, NL80211_CMD_GET_PROTOCOL_FEATURES
)) {
52 if (send_and_recv_msgs(drv
, msg
, protocol_feature_handler
, &feat
) == 0)
59 struct wiphy_info_data
{
60 struct wpa_driver_nl80211_data
*drv
;
61 struct wpa_driver_capa
*capa
;
63 unsigned int num_multichan_concurrent
;
66 unsigned int device_ap_sme
:1;
67 unsigned int poll_command_supported
:1;
68 unsigned int data_tx_status
:1;
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;
73 unsigned int p2p_go_ctwindow_supported
:1;
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;
78 unsigned int wmm_ac_supported
:1;
79 unsigned int mac_addr_rand_scan_supported
:1;
80 unsigned int mac_addr_rand_sched_scan_supported
:1;
84 static unsigned int probe_resp_offload_support(int supp_protocols
)
86 unsigned int prot
= 0;
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
;
101 static void wiphy_info_supported_iftypes(struct wiphy_info_data
*info
,
104 struct nlattr
*nl_mode
;
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
;
115 case NL80211_IFTYPE_MESH_POINT
:
116 info
->capa
->flags
|= WPA_DRIVER_FLAGS_MESH
;
118 case NL80211_IFTYPE_ADHOC
:
119 info
->capa
->flags
|= WPA_DRIVER_FLAGS_IBSS
;
121 case NL80211_IFTYPE_P2P_DEVICE
:
123 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE
;
125 case NL80211_IFTYPE_P2P_GO
:
126 info
->p2p_go_supported
= 1;
128 case NL80211_IFTYPE_P2P_CLIENT
:
129 info
->p2p_client_supported
= 1;
136 static int wiphy_info_iface_comb_process(struct wiphy_info_data
*info
,
137 struct nlattr
*nl_combi
)
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
},
152 iface_limit_policy
[NUM_NL80211_IFACE_LIMIT
] = {
153 [NL80211_IFACE_LIMIT_TYPES
] = { .type
= NLA_NESTED
},
154 [NL80211_IFACE_LIMIT_MAX
] = { .type
= NLA_U32
},
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 */
164 if (tb_comb
[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS
])
165 info
->capa
->flags
|= WPA_DRIVER_FLAGS_RADAR
;
167 nla_for_each_nested(nl_limit
, tb_comb
[NL80211_IFACE_COMB_LIMITS
],
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 */
174 nla_for_each_nested(nl_mode
,
175 tb_limit
[NL80211_IFACE_LIMIT_TYPES
],
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;
184 if (combination_has_p2p
&& combination_has_mgd
)
188 if (combination_has_p2p
&& combination_has_mgd
) {
189 unsigned int num_channels
=
190 nla_get_u32(tb_comb
[NL80211_IFACE_COMB_NUM_CHANNELS
]);
192 info
->p2p_concurrent
= 1;
193 if (info
->num_multichan_concurrent
< num_channels
)
194 info
->num_multichan_concurrent
= num_channels
;
201 static void wiphy_info_iface_comb(struct wiphy_info_data
*info
,
204 struct nlattr
*nl_combi
;
210 nla_for_each_nested(nl_combi
, tb
, rem_combi
) {
211 if (wiphy_info_iface_comb_process(info
, nl_combi
) > 0)
217 static void wiphy_info_supp_cmds(struct wiphy_info_data
*info
,
220 struct nlattr
*nl_cmd
;
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;
231 case NL80211_CMD_CONNECT
:
232 info
->connect_supported
= 1;
234 case NL80211_CMD_START_SCHED_SCAN
:
235 info
->capa
->sched_scan_supported
= 1;
237 case NL80211_CMD_PROBE_CLIENT
:
238 info
->poll_command_supported
= 1;
240 case NL80211_CMD_CHANNEL_SWITCH
:
241 info
->channel_switch_supported
= 1;
243 case NL80211_CMD_SET_QOS_MAP
:
244 info
->set_qos_map_supported
= 1;
251 static void wiphy_info_cipher_suites(struct wiphy_info_data
*info
,
260 num
= nla_len(tb
) / sizeof(u32
);
261 ciphers
= nla_data(tb
);
262 for (i
= 0; i
< num
; i
++) {
265 wpa_printf(MSG_DEBUG
, "nl80211: Supported cipher %02x-%02x-%02x:%d",
266 c
>> 24, (c
>> 16) & 0xff,
267 (c
>> 8) & 0xff, c
& 0xff);
269 case RSN_CIPHER_SUITE_CCMP_256
:
270 info
->capa
->enc
|= WPA_DRIVER_CAPA_ENC_CCMP_256
;
272 case RSN_CIPHER_SUITE_GCMP_256
:
273 info
->capa
->enc
|= WPA_DRIVER_CAPA_ENC_GCMP_256
;
275 case RSN_CIPHER_SUITE_CCMP
:
276 info
->capa
->enc
|= WPA_DRIVER_CAPA_ENC_CCMP
;
278 case RSN_CIPHER_SUITE_GCMP
:
279 info
->capa
->enc
|= WPA_DRIVER_CAPA_ENC_GCMP
;
281 case RSN_CIPHER_SUITE_TKIP
:
282 info
->capa
->enc
|= WPA_DRIVER_CAPA_ENC_TKIP
;
284 case RSN_CIPHER_SUITE_WEP104
:
285 info
->capa
->enc
|= WPA_DRIVER_CAPA_ENC_WEP104
;
287 case RSN_CIPHER_SUITE_WEP40
:
288 info
->capa
->enc
|= WPA_DRIVER_CAPA_ENC_WEP40
;
290 case RSN_CIPHER_SUITE_AES_128_CMAC
:
291 info
->capa
->enc
|= WPA_DRIVER_CAPA_ENC_BIP
;
293 case RSN_CIPHER_SUITE_BIP_GMAC_128
:
294 info
->capa
->enc
|= WPA_DRIVER_CAPA_ENC_BIP_GMAC_128
;
296 case RSN_CIPHER_SUITE_BIP_GMAC_256
:
297 info
->capa
->enc
|= WPA_DRIVER_CAPA_ENC_BIP_GMAC_256
;
299 case RSN_CIPHER_SUITE_BIP_CMAC_256
:
300 info
->capa
->enc
|= WPA_DRIVER_CAPA_ENC_BIP_CMAC_256
;
302 case RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED
:
303 info
->capa
->enc
|= WPA_DRIVER_CAPA_ENC_GTK_NOT_USED
;
310 static void wiphy_info_max_roc(struct wpa_driver_capa
*capa
,
314 capa
->max_remain_on_chan
= nla_get_u32(tb
);
318 static void wiphy_info_tdls(struct wpa_driver_capa
*capa
, struct nlattr
*tdls
,
319 struct nlattr
*ext_setup
)
324 wpa_printf(MSG_DEBUG
, "nl80211: TDLS supported");
325 capa
->flags
|= WPA_DRIVER_FLAGS_TDLS_SUPPORT
;
328 wpa_printf(MSG_DEBUG
, "nl80211: TDLS external setup");
329 capa
->flags
|= WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP
;
334 static int ext_feature_isset(const u8
*ext_features
, int ext_features_len
,
335 enum nl80211_ext_feature_index ftidx
)
339 if ((int) ftidx
/ 8 >= ext_features_len
)
342 ft_byte
= ext_features
[ftidx
/ 8];
343 return (ft_byte
& BIT(ftidx
% 8)) != 0;
347 static void wiphy_info_ext_feature_flags(struct wiphy_info_data
*info
,
350 struct wpa_driver_capa
*capa
= info
->capa
;
357 ext_features
= nla_data(tb
);
360 if (ext_feature_isset(ext_features
, len
, NL80211_EXT_FEATURE_VHT_IBSS
))
361 capa
->flags
|= WPA_DRIVER_FLAGS_VHT_IBSS
;
363 if (ext_feature_isset(ext_features
, len
, NL80211_EXT_FEATURE_RRM
))
364 capa
->rrm_flags
|= WPA_DRIVER_FLAGS_SUPPORT_RRM
;
366 if (ext_feature_isset(ext_features
, len
, NL80211_EXT_FEATURE_FILS_STA
))
367 capa
->flags
|= WPA_DRIVER_FLAGS_SUPPORT_FILS
;
369 if (ext_feature_isset(ext_features
, len
,
370 NL80211_EXT_FEATURE_BEACON_RATE_LEGACY
))
371 capa
->flags
|= WPA_DRIVER_FLAGS_BEACON_RATE_LEGACY
;
373 if (ext_feature_isset(ext_features
, len
,
374 NL80211_EXT_FEATURE_BEACON_RATE_HT
))
375 capa
->flags
|= WPA_DRIVER_FLAGS_BEACON_RATE_HT
;
377 if (ext_feature_isset(ext_features
, len
,
378 NL80211_EXT_FEATURE_BEACON_RATE_VHT
))
379 capa
->flags
|= WPA_DRIVER_FLAGS_BEACON_RATE_VHT
;
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
;
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
;
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
;
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
;
401 if (ext_feature_isset(ext_features
, len
,
402 NL80211_EXT_FEATURE_FILS_SK_OFFLOAD
))
403 capa
->flags
|= WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD
;
407 static void wiphy_info_feature_flags(struct wiphy_info_data
*info
,
411 struct wpa_driver_capa
*capa
= info
->capa
;
416 flags
= nla_get_u32(tb
);
418 if (flags
& NL80211_FEATURE_SK_TX_STATUS
)
419 info
->data_tx_status
= 1;
421 if (flags
& NL80211_FEATURE_INACTIVITY_TIMER
)
422 capa
->flags
|= WPA_DRIVER_FLAGS_INACTIVITY_TIMER
;
424 if (flags
& NL80211_FEATURE_SAE
)
425 capa
->flags
|= WPA_DRIVER_FLAGS_SAE
;
427 if (flags
& NL80211_FEATURE_NEED_OBSS_SCAN
)
428 capa
->flags
|= WPA_DRIVER_FLAGS_OBSS_SCAN
;
430 if (flags
& NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE
)
431 capa
->flags
|= WPA_DRIVER_FLAGS_HT_2040_COEX
;
433 if (flags
& NL80211_FEATURE_TDLS_CHANNEL_SWITCH
) {
434 wpa_printf(MSG_DEBUG
, "nl80211: TDLS channel switch");
435 capa
->flags
|= WPA_DRIVER_FLAGS_TDLS_CHANNEL_SWITCH
;
438 if (flags
& NL80211_FEATURE_P2P_GO_CTWIN
)
439 info
->p2p_go_ctwindow_supported
= 1;
441 if (flags
& NL80211_FEATURE_LOW_PRIORITY_SCAN
)
442 info
->have_low_prio_scan
= 1;
444 if (flags
& NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR
)
445 info
->mac_addr_rand_scan_supported
= 1;
447 if (flags
& NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR
)
448 info
->mac_addr_rand_sched_scan_supported
= 1;
450 if (flags
& NL80211_FEATURE_STATIC_SMPS
)
451 capa
->smps_modes
|= WPA_DRIVER_SMPS_MODE_STATIC
;
453 if (flags
& NL80211_FEATURE_DYNAMIC_SMPS
)
454 capa
->smps_modes
|= WPA_DRIVER_SMPS_MODE_DYNAMIC
;
456 if (flags
& NL80211_FEATURE_SUPPORTS_WMM_ADMISSION
)
457 info
->wmm_ac_supported
= 1;
459 if (flags
& NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES
)
460 capa
->rrm_flags
|= WPA_DRIVER_FLAGS_DS_PARAM_SET_IE_IN_PROBES
;
462 if (flags
& NL80211_FEATURE_WFA_TPC_IE_IN_PROBES
)
463 capa
->rrm_flags
|= WPA_DRIVER_FLAGS_WFA_TPC_IE_IN_PROBES
;
465 if (flags
& NL80211_FEATURE_QUIET
)
466 capa
->rrm_flags
|= WPA_DRIVER_FLAGS_QUIET
;
468 if (flags
& NL80211_FEATURE_TX_POWER_INSERTION
)
469 capa
->rrm_flags
|= WPA_DRIVER_FLAGS_TX_POWER_INSERTION
;
471 if (flags
& NL80211_FEATURE_HT_IBSS
)
472 capa
->flags
|= WPA_DRIVER_FLAGS_HT_IBSS
;
474 if (flags
& NL80211_FEATURE_FULL_AP_CLIENT_STATE
)
475 capa
->flags
|= WPA_DRIVER_FLAGS_FULL_AP_CLIENT_STATE
;
479 static void wiphy_info_probe_resp_offload(struct wpa_driver_capa
*capa
,
487 protocols
= nla_get_u32(tb
);
488 wpa_printf(MSG_DEBUG
, "nl80211: Supports Probe Response offload in AP "
490 capa
->flags
|= WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD
;
491 capa
->probe_resp_offloads
= probe_resp_offload_support(protocols
);
495 static void wiphy_info_wowlan_triggers(struct wpa_driver_capa
*capa
,
498 struct nlattr
*triggers
[MAX_NL80211_WOWLAN_TRIG
+ 1];
503 if (nla_parse_nested(triggers
, MAX_NL80211_WOWLAN_TRIG
,
507 if (triggers
[NL80211_WOWLAN_TRIG_ANY
])
508 capa
->wowlan_triggers
.any
= 1;
509 if (triggers
[NL80211_WOWLAN_TRIG_DISCONNECT
])
510 capa
->wowlan_triggers
.disconnect
= 1;
511 if (triggers
[NL80211_WOWLAN_TRIG_MAGIC_PKT
])
512 capa
->wowlan_triggers
.magic_pkt
= 1;
513 if (triggers
[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE
])
514 capa
->wowlan_triggers
.gtk_rekey_failure
= 1;
515 if (triggers
[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST
])
516 capa
->wowlan_triggers
.eap_identity_req
= 1;
517 if (triggers
[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE
])
518 capa
->wowlan_triggers
.four_way_handshake
= 1;
519 if (triggers
[NL80211_WOWLAN_TRIG_RFKILL_RELEASE
])
520 capa
->wowlan_triggers
.rfkill_release
= 1;
524 static void wiphy_info_extended_capab(struct wpa_driver_nl80211_data
*drv
,
528 struct nlattr
*tb1
[NL80211_ATTR_MAX
+ 1], *attr
;
530 if (!tb
|| drv
->num_iface_ext_capa
== NL80211_IFTYPE_MAX
)
533 nla_for_each_nested(attr
, tb
, rem
) {
535 struct drv_nl80211_ext_capa
*capa
;
537 nla_parse(tb1
, NL80211_ATTR_MAX
, nla_data(attr
),
538 nla_len(attr
), NULL
);
540 if (!tb1
[NL80211_ATTR_IFTYPE
] ||
541 !tb1
[NL80211_ATTR_EXT_CAPA
] ||
542 !tb1
[NL80211_ATTR_EXT_CAPA_MASK
])
545 capa
= &drv
->iface_ext_capa
[drv
->num_iface_ext_capa
];
546 capa
->iftype
= nla_get_u32(tb1
[NL80211_ATTR_IFTYPE
]);
547 wpa_printf(MSG_DEBUG
,
548 "nl80211: Driver-advertised extended capabilities for interface type %s",
549 nl80211_iftype_str(capa
->iftype
));
551 len
= nla_len(tb1
[NL80211_ATTR_EXT_CAPA
]);
552 capa
->ext_capa
= os_memdup(nla_data(tb1
[NL80211_ATTR_EXT_CAPA
]),
557 capa
->ext_capa_len
= len
;
558 wpa_hexdump(MSG_DEBUG
, "nl80211: Extended capabilities",
559 capa
->ext_capa
, capa
->ext_capa_len
);
561 len
= nla_len(tb1
[NL80211_ATTR_EXT_CAPA_MASK
]);
562 capa
->ext_capa_mask
=
563 os_memdup(nla_data(tb1
[NL80211_ATTR_EXT_CAPA_MASK
]),
565 if (!capa
->ext_capa_mask
)
568 wpa_hexdump(MSG_DEBUG
, "nl80211: Extended capabilities mask",
569 capa
->ext_capa_mask
, capa
->ext_capa_len
);
571 drv
->num_iface_ext_capa
++;
572 if (drv
->num_iface_ext_capa
== NL80211_IFTYPE_MAX
)
579 /* Cleanup allocated memory on error */
580 for (i
= 0; i
< NL80211_IFTYPE_MAX
; i
++) {
581 os_free(drv
->iface_ext_capa
[i
].ext_capa
);
582 drv
->iface_ext_capa
[i
].ext_capa
= NULL
;
583 os_free(drv
->iface_ext_capa
[i
].ext_capa_mask
);
584 drv
->iface_ext_capa
[i
].ext_capa_mask
= NULL
;
585 drv
->iface_ext_capa
[i
].ext_capa_len
= 0;
587 drv
->num_iface_ext_capa
= 0;
591 static int wiphy_info_handler(struct nl_msg
*msg
, void *arg
)
593 struct nlattr
*tb
[NL80211_ATTR_MAX
+ 1];
594 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
595 struct wiphy_info_data
*info
= arg
;
596 struct wpa_driver_capa
*capa
= info
->capa
;
597 struct wpa_driver_nl80211_data
*drv
= info
->drv
;
599 nla_parse(tb
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
600 genlmsg_attrlen(gnlh
, 0), NULL
);
602 if (tb
[NL80211_ATTR_WIPHY
])
603 drv
->wiphy_idx
= nla_get_u32(tb
[NL80211_ATTR_WIPHY
]);
605 if (tb
[NL80211_ATTR_WIPHY_NAME
])
606 os_strlcpy(drv
->phyname
,
607 nla_get_string(tb
[NL80211_ATTR_WIPHY_NAME
]),
608 sizeof(drv
->phyname
));
609 if (tb
[NL80211_ATTR_MAX_NUM_SCAN_SSIDS
])
610 capa
->max_scan_ssids
=
611 nla_get_u8(tb
[NL80211_ATTR_MAX_NUM_SCAN_SSIDS
]);
613 if (tb
[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS
])
614 capa
->max_sched_scan_ssids
=
615 nla_get_u8(tb
[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS
]);
617 if (tb
[NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS
] &&
618 tb
[NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL
] &&
619 tb
[NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS
]) {
620 capa
->max_sched_scan_plans
=
621 nla_get_u32(tb
[NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS
]);
623 capa
->max_sched_scan_plan_interval
=
624 nla_get_u32(tb
[NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL
]);
626 capa
->max_sched_scan_plan_iterations
=
627 nla_get_u32(tb
[NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS
]);
630 if (tb
[NL80211_ATTR_MAX_MATCH_SETS
])
631 capa
->max_match_sets
=
632 nla_get_u8(tb
[NL80211_ATTR_MAX_MATCH_SETS
]);
634 if (tb
[NL80211_ATTR_MAC_ACL_MAX
])
635 capa
->max_acl_mac_addrs
=
636 nla_get_u8(tb
[NL80211_ATTR_MAC_ACL_MAX
]);
638 wiphy_info_supported_iftypes(info
, tb
[NL80211_ATTR_SUPPORTED_IFTYPES
]);
639 wiphy_info_iface_comb(info
, tb
[NL80211_ATTR_INTERFACE_COMBINATIONS
]);
640 wiphy_info_supp_cmds(info
, tb
[NL80211_ATTR_SUPPORTED_COMMANDS
]);
641 wiphy_info_cipher_suites(info
, tb
[NL80211_ATTR_CIPHER_SUITES
]);
643 if (tb
[NL80211_ATTR_OFFCHANNEL_TX_OK
]) {
644 wpa_printf(MSG_DEBUG
, "nl80211: Using driver-based "
646 capa
->flags
|= WPA_DRIVER_FLAGS_OFFCHANNEL_TX
;
649 if (tb
[NL80211_ATTR_ROAM_SUPPORT
]) {
650 wpa_printf(MSG_DEBUG
, "nl80211: Using driver-based roaming");
651 capa
->flags
|= WPA_DRIVER_FLAGS_BSS_SELECTION
;
654 wiphy_info_max_roc(capa
,
655 tb
[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION
]);
657 if (tb
[NL80211_ATTR_SUPPORT_AP_UAPSD
])
658 capa
->flags
|= WPA_DRIVER_FLAGS_AP_UAPSD
;
660 wiphy_info_tdls(capa
, tb
[NL80211_ATTR_TDLS_SUPPORT
],
661 tb
[NL80211_ATTR_TDLS_EXTERNAL_SETUP
]);
663 if (tb
[NL80211_ATTR_DEVICE_AP_SME
])
664 info
->device_ap_sme
= 1;
666 wiphy_info_feature_flags(info
, tb
[NL80211_ATTR_FEATURE_FLAGS
]);
667 wiphy_info_ext_feature_flags(info
, tb
[NL80211_ATTR_EXT_FEATURES
]);
668 wiphy_info_probe_resp_offload(capa
,
669 tb
[NL80211_ATTR_PROBE_RESP_OFFLOAD
]);
671 if (tb
[NL80211_ATTR_EXT_CAPA
] && tb
[NL80211_ATTR_EXT_CAPA_MASK
] &&
672 drv
->extended_capa
== NULL
) {
674 os_malloc(nla_len(tb
[NL80211_ATTR_EXT_CAPA
]));
675 if (drv
->extended_capa
) {
676 os_memcpy(drv
->extended_capa
,
677 nla_data(tb
[NL80211_ATTR_EXT_CAPA
]),
678 nla_len(tb
[NL80211_ATTR_EXT_CAPA
]));
679 drv
->extended_capa_len
=
680 nla_len(tb
[NL80211_ATTR_EXT_CAPA
]);
681 wpa_hexdump(MSG_DEBUG
,
682 "nl80211: Driver-advertised extended capabilities (default)",
683 drv
->extended_capa
, drv
->extended_capa_len
);
685 drv
->extended_capa_mask
=
686 os_malloc(nla_len(tb
[NL80211_ATTR_EXT_CAPA_MASK
]));
687 if (drv
->extended_capa_mask
) {
688 os_memcpy(drv
->extended_capa_mask
,
689 nla_data(tb
[NL80211_ATTR_EXT_CAPA_MASK
]),
690 nla_len(tb
[NL80211_ATTR_EXT_CAPA_MASK
]));
691 wpa_hexdump(MSG_DEBUG
,
692 "nl80211: Driver-advertised extended capabilities mask (default)",
693 drv
->extended_capa_mask
,
694 drv
->extended_capa_len
);
696 os_free(drv
->extended_capa
);
697 drv
->extended_capa
= NULL
;
698 drv
->extended_capa_len
= 0;
702 wiphy_info_extended_capab(drv
, tb
[NL80211_ATTR_IFTYPE_EXT_CAPA
]);
704 if (tb
[NL80211_ATTR_VENDOR_DATA
]) {
708 nla_for_each_nested(nl
, tb
[NL80211_ATTR_VENDOR_DATA
], rem
) {
709 struct nl80211_vendor_cmd_info
*vinfo
;
710 if (nla_len(nl
) != sizeof(*vinfo
)) {
711 wpa_printf(MSG_DEBUG
, "nl80211: Unexpected vendor data info");
714 vinfo
= nla_data(nl
);
715 if (vinfo
->vendor_id
== OUI_QCA
) {
716 switch (vinfo
->subcmd
) {
717 case QCA_NL80211_VENDOR_SUBCMD_TEST
:
718 drv
->vendor_cmd_test_avail
= 1;
720 #ifdef CONFIG_DRIVER_NL80211_QCA
721 case QCA_NL80211_VENDOR_SUBCMD_ROAMING
:
722 drv
->roaming_vendor_cmd_avail
= 1;
724 case QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY
:
725 drv
->dfs_vendor_cmd_avail
= 1;
727 case QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES
:
728 drv
->get_features_vendor_cmd_avail
= 1;
730 case QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST
:
731 drv
->get_pref_freq_list
= 1;
733 case QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL
:
734 drv
->set_prob_oper_freq
= 1;
736 case QCA_NL80211_VENDOR_SUBCMD_DO_ACS
:
738 WPA_DRIVER_FLAGS_ACS_OFFLOAD
;
740 case QCA_NL80211_VENDOR_SUBCMD_SETBAND
:
741 drv
->setband_vendor_cmd_avail
= 1;
743 case QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
:
744 drv
->scan_vendor_cmd_avail
= 1;
746 case QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION
:
747 drv
->set_wifi_conf_vendor_cmd_avail
= 1;
749 case QCA_NL80211_VENDOR_SUBCMD_GET_HE_CAPABILITIES
:
750 drv
->he_capab_vendor_cmd_avail
= 1;
752 case QCA_NL80211_VENDOR_SUBCMD_FETCH_BSS_TRANSITION_STATUS
:
753 drv
->fetch_bss_trans_status
= 1;
755 case QCA_NL80211_VENDOR_SUBCMD_ROAM
:
756 drv
->roam_vendor_cmd_avail
= 1;
758 #endif /* CONFIG_DRIVER_NL80211_QCA */
762 wpa_printf(MSG_DEBUG
, "nl80211: Supported vendor command: vendor_id=0x%x subcmd=%u",
763 vinfo
->vendor_id
, vinfo
->subcmd
);
767 if (tb
[NL80211_ATTR_VENDOR_EVENTS
]) {
771 nla_for_each_nested(nl
, tb
[NL80211_ATTR_VENDOR_EVENTS
], rem
) {
772 struct nl80211_vendor_cmd_info
*vinfo
;
773 if (nla_len(nl
) != sizeof(*vinfo
)) {
774 wpa_printf(MSG_DEBUG
, "nl80211: Unexpected vendor data info");
777 vinfo
= nla_data(nl
);
778 wpa_printf(MSG_DEBUG
, "nl80211: Supported vendor event: vendor_id=0x%x subcmd=%u",
779 vinfo
->vendor_id
, vinfo
->subcmd
);
783 wiphy_info_wowlan_triggers(capa
,
784 tb
[NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED
]);
786 if (tb
[NL80211_ATTR_MAX_AP_ASSOC_STA
])
788 nla_get_u32(tb
[NL80211_ATTR_MAX_AP_ASSOC_STA
]);
790 if (tb
[NL80211_ATTR_MAX_CSA_COUNTERS
])
791 capa
->max_csa_counters
=
792 nla_get_u8(tb
[NL80211_ATTR_MAX_CSA_COUNTERS
]);
798 static int wpa_driver_nl80211_get_info(struct wpa_driver_nl80211_data
*drv
,
799 struct wiphy_info_data
*info
)
805 os_memset(info
, 0, sizeof(*info
));
806 info
->capa
= &drv
->capa
;
809 feat
= get_nl80211_protocol_features(drv
);
810 if (feat
& NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP
)
812 msg
= nl80211_cmd_msg(drv
->first_bss
, flags
, NL80211_CMD_GET_WIPHY
);
813 if (!msg
|| nla_put_flag(msg
, NL80211_ATTR_SPLIT_WIPHY_DUMP
)) {
818 if (send_and_recv_msgs(drv
, msg
, wiphy_info_handler
, info
))
821 if (info
->auth_supported
)
822 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_SME
;
823 else if (!info
->connect_supported
) {
824 wpa_printf(MSG_INFO
, "nl80211: Driver does not support "
825 "authentication/association or connect commands");
829 if (info
->p2p_go_supported
&& info
->p2p_client_supported
)
830 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_P2P_CAPABLE
;
831 if (info
->p2p_concurrent
) {
832 wpa_printf(MSG_DEBUG
, "nl80211: Use separate P2P group "
833 "interface (driver advertised support)");
834 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_P2P_CONCURRENT
;
835 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P
;
837 if (info
->num_multichan_concurrent
> 1) {
838 wpa_printf(MSG_DEBUG
, "nl80211: Enable multi-channel "
839 "concurrent (driver advertised support)");
840 drv
->capa
.num_multichan_concurrent
=
841 info
->num_multichan_concurrent
;
843 if (drv
->capa
.flags
& WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE
)
844 wpa_printf(MSG_DEBUG
, "nl80211: use P2P_DEVICE support");
846 /* default to 5000 since early versions of mac80211 don't set it */
847 if (!drv
->capa
.max_remain_on_chan
)
848 drv
->capa
.max_remain_on_chan
= 5000;
850 drv
->capa
.wmm_ac_supported
= info
->wmm_ac_supported
;
852 drv
->capa
.mac_addr_rand_sched_scan_supported
=
853 info
->mac_addr_rand_sched_scan_supported
;
854 drv
->capa
.mac_addr_rand_scan_supported
=
855 info
->mac_addr_rand_scan_supported
;
857 if (info
->channel_switch_supported
) {
858 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_AP_CSA
;
859 if (!drv
->capa
.max_csa_counters
)
860 drv
->capa
.max_csa_counters
= 1;
863 if (!drv
->capa
.max_sched_scan_plans
) {
864 drv
->capa
.max_sched_scan_plans
= 1;
865 drv
->capa
.max_sched_scan_plan_interval
= UINT32_MAX
;
866 drv
->capa
.max_sched_scan_plan_iterations
= 0;
873 #ifdef CONFIG_DRIVER_NL80211_QCA
875 static int dfs_info_handler(struct nl_msg
*msg
, void *arg
)
877 struct nlattr
*tb
[NL80211_ATTR_MAX
+ 1];
878 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
879 int *dfs_capability_ptr
= arg
;
881 nla_parse(tb
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
882 genlmsg_attrlen(gnlh
, 0), NULL
);
884 if (tb
[NL80211_ATTR_VENDOR_DATA
]) {
885 struct nlattr
*nl_vend
= tb
[NL80211_ATTR_VENDOR_DATA
];
886 struct nlattr
*tb_vendor
[QCA_WLAN_VENDOR_ATTR_MAX
+ 1];
888 nla_parse(tb_vendor
, QCA_WLAN_VENDOR_ATTR_MAX
,
889 nla_data(nl_vend
), nla_len(nl_vend
), NULL
);
891 if (tb_vendor
[QCA_WLAN_VENDOR_ATTR_DFS
]) {
893 val
= nla_get_u32(tb_vendor
[QCA_WLAN_VENDOR_ATTR_DFS
]);
894 wpa_printf(MSG_DEBUG
, "nl80211: DFS offload capability: %u",
896 *dfs_capability_ptr
= val
;
904 static void qca_nl80211_check_dfs_capa(struct wpa_driver_nl80211_data
*drv
)
907 int dfs_capability
= 0;
910 if (!drv
->dfs_vendor_cmd_avail
)
913 if (!(msg
= nl80211_drv_msg(drv
, 0, NL80211_CMD_VENDOR
)) ||
914 nla_put_u32(msg
, NL80211_ATTR_VENDOR_ID
, OUI_QCA
) ||
915 nla_put_u32(msg
, NL80211_ATTR_VENDOR_SUBCMD
,
916 QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY
)) {
921 ret
= send_and_recv_msgs(drv
, msg
, dfs_info_handler
, &dfs_capability
);
922 if (!ret
&& dfs_capability
)
923 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_DFS_OFFLOAD
;
927 static int qca_nl80211_he_capab_handler(struct nl_msg
*msg
, void *arg
)
929 struct nlattr
*tb
[NL80211_ATTR_MAX
+ 1];
930 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
931 struct he_capabilities
*he_capab
= arg
;
932 struct nlattr
*nl_vend
;
933 struct nlattr
*tb_vendor
[QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_MAX
+ 1];
936 nla_parse(tb
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
937 genlmsg_attrlen(gnlh
, 0), NULL
);
939 if (!tb
[NL80211_ATTR_VENDOR_DATA
])
942 nl_vend
= tb
[NL80211_ATTR_VENDOR_DATA
];
943 nla_parse(tb_vendor
, QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_MAX
,
944 nla_data(nl_vend
), nla_len(nl_vend
), NULL
);
946 if (tb_vendor
[QCA_WLAN_VENDOR_ATTR_HE_SUPPORTED
]) {
949 he_supported
= nla_get_u8(
950 tb_vendor
[QCA_WLAN_VENDOR_ATTR_HE_SUPPORTED
]);
951 wpa_printf(MSG_DEBUG
, "nl80211: HE capabilities supported: %u",
953 he_capab
->he_supported
= he_supported
;
958 if (tb_vendor
[QCA_WLAN_VENDOR_ATTR_PHY_CAPAB
]) {
959 len
= nla_len(tb_vendor
[QCA_WLAN_VENDOR_ATTR_PHY_CAPAB
]);
961 if (len
> sizeof(he_capab
->phy_cap
))
962 len
= sizeof(he_capab
->phy_cap
);
963 os_memcpy(he_capab
->phy_cap
,
964 nla_data(tb_vendor
[QCA_WLAN_VENDOR_ATTR_PHY_CAPAB
]),
968 if (tb_vendor
[QCA_WLAN_VENDOR_ATTR_MAC_CAPAB
])
970 nla_get_u32(tb_vendor
[QCA_WLAN_VENDOR_ATTR_MAC_CAPAB
]);
972 if (tb_vendor
[QCA_WLAN_VENDOR_ATTR_HE_MCS
])
974 nla_get_u32(tb_vendor
[QCA_WLAN_VENDOR_ATTR_HE_MCS
]);
976 if (tb_vendor
[QCA_WLAN_VENDOR_ATTR_NUM_SS
])
977 he_capab
->ppet
.numss_m1
=
978 nla_get_u32(tb_vendor
[QCA_WLAN_VENDOR_ATTR_NUM_SS
]);
980 if (tb_vendor
[QCA_WLAN_VENDOR_ATTR_RU_IDX_MASK
])
981 he_capab
->ppet
.ru_count
=
982 nla_get_u32(tb_vendor
[QCA_WLAN_VENDOR_ATTR_RU_IDX_MASK
]);
984 if (tb_vendor
[QCA_WLAN_VENDOR_ATTR_PPE_THRESHOLD
]) {
985 len
= nla_len(tb_vendor
[QCA_WLAN_VENDOR_ATTR_PPE_THRESHOLD
]);
987 if (len
> sizeof(he_capab
->ppet
.ppet16_ppet8_ru3_ru0
))
988 len
= sizeof(he_capab
->ppet
.ppet16_ppet8_ru3_ru0
);
989 os_memcpy(he_capab
->ppet
.ppet16_ppet8_ru3_ru0
,
990 nla_data(tb_vendor
[QCA_WLAN_VENDOR_ATTR_PPE_THRESHOLD
]),
998 static void qca_nl80211_check_he_capab(struct wpa_driver_nl80211_data
*drv
)
1003 if (!drv
->he_capab_vendor_cmd_avail
)
1006 if (!(msg
= nl80211_drv_msg(drv
, 0, NL80211_CMD_VENDOR
)) ||
1007 nla_put_u32(msg
, NL80211_ATTR_VENDOR_ID
, OUI_QCA
) ||
1008 nla_put_u32(msg
, NL80211_ATTR_VENDOR_SUBCMD
,
1009 QCA_NL80211_VENDOR_SUBCMD_GET_HE_CAPABILITIES
)) {
1014 ret
= send_and_recv_msgs(drv
, msg
, qca_nl80211_he_capab_handler
,
1016 if (!ret
&& drv
->he_capab
.he_supported
)
1017 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_HE_CAPABILITIES
;
1021 struct features_info
{
1024 struct wpa_driver_capa
*capa
;
1028 static int features_info_handler(struct nl_msg
*msg
, void *arg
)
1030 struct nlattr
*tb
[NL80211_ATTR_MAX
+ 1];
1031 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
1032 struct features_info
*info
= arg
;
1033 struct nlattr
*nl_vend
, *attr
;
1035 nla_parse(tb
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
1036 genlmsg_attrlen(gnlh
, 0), NULL
);
1038 nl_vend
= tb
[NL80211_ATTR_VENDOR_DATA
];
1040 struct nlattr
*tb_vendor
[QCA_WLAN_VENDOR_ATTR_MAX
+ 1];
1042 nla_parse(tb_vendor
, QCA_WLAN_VENDOR_ATTR_MAX
,
1043 nla_data(nl_vend
), nla_len(nl_vend
), NULL
);
1045 attr
= tb_vendor
[QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS
];
1047 int len
= nla_len(attr
);
1048 info
->flags
= os_malloc(len
);
1049 if (info
->flags
!= NULL
) {
1050 os_memcpy(info
->flags
, nla_data(attr
), len
);
1051 info
->flags_len
= len
;
1054 attr
= tb_vendor
[QCA_WLAN_VENDOR_ATTR_CONCURRENCY_CAPA
];
1056 info
->capa
->conc_capab
= nla_get_u32(attr
);
1059 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND
];
1061 info
->capa
->max_conc_chan_2_4
= nla_get_u32(attr
);
1064 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND
];
1066 info
->capa
->max_conc_chan_5_0
= nla_get_u32(attr
);
1073 static int check_feature(enum qca_wlan_vendor_features feature
,
1074 struct features_info
*info
)
1076 size_t idx
= feature
/ 8;
1078 return (idx
< info
->flags_len
) &&
1079 (info
->flags
[idx
] & BIT(feature
% 8));
1083 static void qca_nl80211_get_features(struct wpa_driver_nl80211_data
*drv
)
1086 struct features_info info
;
1089 if (!drv
->get_features_vendor_cmd_avail
)
1092 if (!(msg
= nl80211_drv_msg(drv
, 0, NL80211_CMD_VENDOR
)) ||
1093 nla_put_u32(msg
, NL80211_ATTR_VENDOR_ID
, OUI_QCA
) ||
1094 nla_put_u32(msg
, NL80211_ATTR_VENDOR_SUBCMD
,
1095 QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES
)) {
1100 os_memset(&info
, 0, sizeof(info
));
1101 info
.capa
= &drv
->capa
;
1102 ret
= send_and_recv_msgs(drv
, msg
, features_info_handler
, &info
);
1103 if (ret
|| !info
.flags
)
1106 if (check_feature(QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD
, &info
))
1107 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD
;
1109 if (check_feature(QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY
, &info
))
1110 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY
;
1112 if (check_feature(QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS
,
1114 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS
;
1115 if (check_feature(QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD
, &info
))
1116 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_P2P_LISTEN_OFFLOAD
;
1117 os_free(info
.flags
);
1120 #endif /* CONFIG_DRIVER_NL80211_QCA */
1123 int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data
*drv
)
1125 struct wiphy_info_data info
;
1126 if (wpa_driver_nl80211_get_info(drv
, &info
))
1132 drv
->has_capability
= 1;
1133 drv
->capa
.key_mgmt
= WPA_DRIVER_CAPA_KEY_MGMT_WPA
|
1134 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK
|
1135 WPA_DRIVER_CAPA_KEY_MGMT_WPA2
|
1136 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK
|
1137 WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B
|
1138 WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192
|
1139 WPA_DRIVER_CAPA_KEY_MGMT_OWE
|
1140 WPA_DRIVER_CAPA_KEY_MGMT_DPP
;
1141 drv
->capa
.auth
= WPA_DRIVER_AUTH_OPEN
|
1142 WPA_DRIVER_AUTH_SHARED
|
1143 WPA_DRIVER_AUTH_LEAP
;
1145 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_SANE_ERROR_CODES
;
1146 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE
;
1147 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_EAPOL_TX_STATUS
;
1150 * As all cfg80211 drivers must support cases where the AP interface is
1151 * removed without the knowledge of wpa_supplicant/hostapd, e.g., in
1152 * case that the user space daemon has crashed, they must be able to
1153 * cleanup all stations and key entries in the AP tear down flow. Thus,
1154 * this flag can/should always be set for cfg80211 drivers.
1156 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT
;
1158 if (!info
.device_ap_sme
) {
1159 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS
;
1162 * No AP SME is currently assumed to also indicate no AP MLME
1163 * in the driver/firmware.
1165 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_AP_MLME
;
1168 drv
->device_ap_sme
= info
.device_ap_sme
;
1169 drv
->poll_command_supported
= info
.poll_command_supported
;
1170 drv
->data_tx_status
= info
.data_tx_status
;
1171 drv
->p2p_go_ctwindow_supported
= info
.p2p_go_ctwindow_supported
;
1172 if (info
.set_qos_map_supported
)
1173 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_QOS_MAPPING
;
1174 drv
->have_low_prio_scan
= info
.have_low_prio_scan
;
1177 * If poll command and tx status are supported, mac80211 is new enough
1178 * to have everything we need to not need monitor interfaces.
1180 drv
->use_monitor
= !info
.device_ap_sme
&&
1181 (!info
.poll_command_supported
|| !info
.data_tx_status
);
1184 * If we aren't going to use monitor interfaces, but the
1185 * driver doesn't support data TX status, we won't get TX
1186 * status for EAPOL frames.
1188 if (!drv
->use_monitor
&& !info
.data_tx_status
)
1189 drv
->capa
.flags
&= ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS
;
1191 #ifdef CONFIG_DRIVER_NL80211_QCA
1192 qca_nl80211_check_dfs_capa(drv
);
1193 qca_nl80211_get_features(drv
);
1194 qca_nl80211_check_he_capab(drv
);
1197 * To enable offchannel simultaneous support in wpa_supplicant, the
1198 * underlying driver needs to support the same along with offchannel TX.
1199 * Offchannel TX support is needed since remain_on_channel and
1200 * action_tx use some common data structures and hence cannot be
1201 * scheduled simultaneously.
1203 if (!(drv
->capa
.flags
& WPA_DRIVER_FLAGS_OFFCHANNEL_TX
))
1204 drv
->capa
.flags
&= ~WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS
;
1205 #endif /* CONFIG_DRIVER_NL80211_QCA */
1211 struct phy_info_arg
{
1213 struct hostapd_hw_modes
*modes
;
1214 int last_mode
, last_chan_idx
;
1219 static void phy_info_ht_capa(struct hostapd_hw_modes
*mode
, struct nlattr
*capa
,
1220 struct nlattr
*ampdu_factor
,
1221 struct nlattr
*ampdu_density
,
1222 struct nlattr
*mcs_set
)
1225 mode
->ht_capab
= nla_get_u16(capa
);
1228 mode
->a_mpdu_params
|= nla_get_u8(ampdu_factor
) & 0x03;
1231 mode
->a_mpdu_params
|= nla_get_u8(ampdu_density
) << 2;
1233 if (mcs_set
&& nla_len(mcs_set
) >= 16) {
1235 mcs
= nla_data(mcs_set
);
1236 os_memcpy(mode
->mcs_set
, mcs
, 16);
1241 static void phy_info_vht_capa(struct hostapd_hw_modes
*mode
,
1242 struct nlattr
*capa
,
1243 struct nlattr
*mcs_set
)
1246 mode
->vht_capab
= nla_get_u32(capa
);
1248 if (mcs_set
&& nla_len(mcs_set
) >= 8) {
1250 mcs
= nla_data(mcs_set
);
1251 os_memcpy(mode
->vht_mcs_set
, mcs
, 8);
1256 static void phy_info_freq(struct hostapd_hw_modes
*mode
,
1257 struct hostapd_channel_data
*chan
,
1258 struct nlattr
*tb_freq
[])
1261 chan
->freq
= nla_get_u32(tb_freq
[NL80211_FREQUENCY_ATTR_FREQ
]);
1263 chan
->dfs_cac_ms
= 0;
1264 if (ieee80211_freq_to_chan(chan
->freq
, &channel
) != NUM_HOSTAPD_MODES
)
1265 chan
->chan
= channel
;
1267 if (tb_freq
[NL80211_FREQUENCY_ATTR_DISABLED
])
1268 chan
->flag
|= HOSTAPD_CHAN_DISABLED
;
1269 if (tb_freq
[NL80211_FREQUENCY_ATTR_NO_IR
])
1270 chan
->flag
|= HOSTAPD_CHAN_NO_IR
;
1271 if (tb_freq
[NL80211_FREQUENCY_ATTR_RADAR
])
1272 chan
->flag
|= HOSTAPD_CHAN_RADAR
;
1273 if (tb_freq
[NL80211_FREQUENCY_ATTR_INDOOR_ONLY
])
1274 chan
->flag
|= HOSTAPD_CHAN_INDOOR_ONLY
;
1275 if (tb_freq
[NL80211_FREQUENCY_ATTR_GO_CONCURRENT
])
1276 chan
->flag
|= HOSTAPD_CHAN_GO_CONCURRENT
;
1278 if (tb_freq
[NL80211_FREQUENCY_ATTR_DFS_STATE
]) {
1279 enum nl80211_dfs_state state
=
1280 nla_get_u32(tb_freq
[NL80211_FREQUENCY_ATTR_DFS_STATE
]);
1283 case NL80211_DFS_USABLE
:
1284 chan
->flag
|= HOSTAPD_CHAN_DFS_USABLE
;
1286 case NL80211_DFS_AVAILABLE
:
1287 chan
->flag
|= HOSTAPD_CHAN_DFS_AVAILABLE
;
1289 case NL80211_DFS_UNAVAILABLE
:
1290 chan
->flag
|= HOSTAPD_CHAN_DFS_UNAVAILABLE
;
1295 if (tb_freq
[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME
]) {
1296 chan
->dfs_cac_ms
= nla_get_u32(
1297 tb_freq
[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME
]);
1302 static int phy_info_freqs(struct phy_info_arg
*phy_info
,
1303 struct hostapd_hw_modes
*mode
, struct nlattr
*tb
)
1305 static struct nla_policy freq_policy
[NL80211_FREQUENCY_ATTR_MAX
+ 1] = {
1306 [NL80211_FREQUENCY_ATTR_FREQ
] = { .type
= NLA_U32
},
1307 [NL80211_FREQUENCY_ATTR_DISABLED
] = { .type
= NLA_FLAG
},
1308 [NL80211_FREQUENCY_ATTR_NO_IR
] = { .type
= NLA_FLAG
},
1309 [NL80211_FREQUENCY_ATTR_RADAR
] = { .type
= NLA_FLAG
},
1310 [NL80211_FREQUENCY_ATTR_MAX_TX_POWER
] = { .type
= NLA_U32
},
1311 [NL80211_FREQUENCY_ATTR_DFS_STATE
] = { .type
= NLA_U32
},
1313 int new_channels
= 0;
1314 struct hostapd_channel_data
*channel
;
1315 struct nlattr
*tb_freq
[NL80211_FREQUENCY_ATTR_MAX
+ 1];
1316 struct nlattr
*nl_freq
;
1322 nla_for_each_nested(nl_freq
, tb
, rem_freq
) {
1323 nla_parse(tb_freq
, NL80211_FREQUENCY_ATTR_MAX
,
1324 nla_data(nl_freq
), nla_len(nl_freq
), freq_policy
);
1325 if (!tb_freq
[NL80211_FREQUENCY_ATTR_FREQ
])
1330 channel
= os_realloc_array(mode
->channels
,
1331 mode
->num_channels
+ new_channels
,
1332 sizeof(struct hostapd_channel_data
));
1336 mode
->channels
= channel
;
1337 mode
->num_channels
+= new_channels
;
1339 idx
= phy_info
->last_chan_idx
;
1341 nla_for_each_nested(nl_freq
, tb
, rem_freq
) {
1342 nla_parse(tb_freq
, NL80211_FREQUENCY_ATTR_MAX
,
1343 nla_data(nl_freq
), nla_len(nl_freq
), freq_policy
);
1344 if (!tb_freq
[NL80211_FREQUENCY_ATTR_FREQ
])
1346 phy_info_freq(mode
, &mode
->channels
[idx
], tb_freq
);
1349 phy_info
->last_chan_idx
= idx
;
1355 static int phy_info_rates(struct hostapd_hw_modes
*mode
, struct nlattr
*tb
)
1357 static struct nla_policy rate_policy
[NL80211_BITRATE_ATTR_MAX
+ 1] = {
1358 [NL80211_BITRATE_ATTR_RATE
] = { .type
= NLA_U32
},
1359 [NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE
] =
1360 { .type
= NLA_FLAG
},
1362 struct nlattr
*tb_rate
[NL80211_BITRATE_ATTR_MAX
+ 1];
1363 struct nlattr
*nl_rate
;
1369 nla_for_each_nested(nl_rate
, tb
, rem_rate
) {
1370 nla_parse(tb_rate
, NL80211_BITRATE_ATTR_MAX
,
1371 nla_data(nl_rate
), nla_len(nl_rate
),
1373 if (!tb_rate
[NL80211_BITRATE_ATTR_RATE
])
1378 mode
->rates
= os_calloc(mode
->num_rates
, sizeof(int));
1384 nla_for_each_nested(nl_rate
, tb
, rem_rate
) {
1385 nla_parse(tb_rate
, NL80211_BITRATE_ATTR_MAX
,
1386 nla_data(nl_rate
), nla_len(nl_rate
),
1388 if (!tb_rate
[NL80211_BITRATE_ATTR_RATE
])
1390 mode
->rates
[idx
] = nla_get_u32(
1391 tb_rate
[NL80211_BITRATE_ATTR_RATE
]);
1399 static int phy_info_band(struct phy_info_arg
*phy_info
, struct nlattr
*nl_band
)
1401 struct nlattr
*tb_band
[NL80211_BAND_ATTR_MAX
+ 1];
1402 struct hostapd_hw_modes
*mode
;
1405 if (phy_info
->last_mode
!= nl_band
->nla_type
) {
1406 mode
= os_realloc_array(phy_info
->modes
,
1407 *phy_info
->num_modes
+ 1,
1410 phy_info
->failed
= 1;
1413 phy_info
->modes
= mode
;
1415 mode
= &phy_info
->modes
[*(phy_info
->num_modes
)];
1416 os_memset(mode
, 0, sizeof(*mode
));
1417 mode
->mode
= NUM_HOSTAPD_MODES
;
1418 mode
->flags
= HOSTAPD_MODE_FLAG_HT_INFO_KNOWN
|
1419 HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN
;
1422 * Unsupported VHT MCS stream is defined as value 3, so the VHT
1423 * MCS RX/TX map must be initialized with 0xffff to mark all 8
1424 * possible streams as unsupported. This will be overridden if
1425 * driver advertises VHT support.
1427 mode
->vht_mcs_set
[0] = 0xff;
1428 mode
->vht_mcs_set
[1] = 0xff;
1429 mode
->vht_mcs_set
[4] = 0xff;
1430 mode
->vht_mcs_set
[5] = 0xff;
1432 *(phy_info
->num_modes
) += 1;
1433 phy_info
->last_mode
= nl_band
->nla_type
;
1434 phy_info
->last_chan_idx
= 0;
1436 mode
= &phy_info
->modes
[*(phy_info
->num_modes
) - 1];
1438 nla_parse(tb_band
, NL80211_BAND_ATTR_MAX
, nla_data(nl_band
),
1439 nla_len(nl_band
), NULL
);
1441 phy_info_ht_capa(mode
, tb_band
[NL80211_BAND_ATTR_HT_CAPA
],
1442 tb_band
[NL80211_BAND_ATTR_HT_AMPDU_FACTOR
],
1443 tb_band
[NL80211_BAND_ATTR_HT_AMPDU_DENSITY
],
1444 tb_band
[NL80211_BAND_ATTR_HT_MCS_SET
]);
1445 phy_info_vht_capa(mode
, tb_band
[NL80211_BAND_ATTR_VHT_CAPA
],
1446 tb_band
[NL80211_BAND_ATTR_VHT_MCS_SET
]);
1447 ret
= phy_info_freqs(phy_info
, mode
, tb_band
[NL80211_BAND_ATTR_FREQS
]);
1449 ret
= phy_info_rates(mode
, tb_band
[NL80211_BAND_ATTR_RATES
]);
1451 phy_info
->failed
= 1;
1459 static int phy_info_handler(struct nl_msg
*msg
, void *arg
)
1461 struct nlattr
*tb_msg
[NL80211_ATTR_MAX
+ 1];
1462 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
1463 struct phy_info_arg
*phy_info
= arg
;
1464 struct nlattr
*nl_band
;
1467 nla_parse(tb_msg
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
1468 genlmsg_attrlen(gnlh
, 0), NULL
);
1470 if (!tb_msg
[NL80211_ATTR_WIPHY_BANDS
])
1473 nla_for_each_nested(nl_band
, tb_msg
[NL80211_ATTR_WIPHY_BANDS
], rem_band
)
1475 int res
= phy_info_band(phy_info
, nl_band
);
1484 static struct hostapd_hw_modes
*
1485 wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes
*modes
,
1489 struct hostapd_hw_modes
*mode11g
= NULL
, *nmodes
, *mode
;
1490 int i
, mode11g_idx
= -1;
1492 /* heuristic to set up modes */
1493 for (m
= 0; m
< *num_modes
; m
++) {
1494 if (!modes
[m
].num_channels
)
1496 if (modes
[m
].channels
[0].freq
< 4000) {
1497 modes
[m
].mode
= HOSTAPD_MODE_IEEE80211B
;
1498 for (i
= 0; i
< modes
[m
].num_rates
; i
++) {
1499 if (modes
[m
].rates
[i
] > 200) {
1500 modes
[m
].mode
= HOSTAPD_MODE_IEEE80211G
;
1504 } else if (modes
[m
].channels
[0].freq
> 50000)
1505 modes
[m
].mode
= HOSTAPD_MODE_IEEE80211AD
;
1507 modes
[m
].mode
= HOSTAPD_MODE_IEEE80211A
;
1510 /* If only 802.11g mode is included, use it to construct matching
1511 * 802.11b mode data. */
1513 for (m
= 0; m
< *num_modes
; m
++) {
1514 if (modes
[m
].mode
== HOSTAPD_MODE_IEEE80211B
)
1515 return modes
; /* 802.11b already included */
1516 if (modes
[m
].mode
== HOSTAPD_MODE_IEEE80211G
)
1520 if (mode11g_idx
< 0)
1521 return modes
; /* 2.4 GHz band not supported at all */
1523 nmodes
= os_realloc_array(modes
, *num_modes
+ 1, sizeof(*nmodes
));
1525 return modes
; /* Could not add 802.11b mode */
1527 mode
= &nmodes
[*num_modes
];
1528 os_memset(mode
, 0, sizeof(*mode
));
1532 mode
->mode
= HOSTAPD_MODE_IEEE80211B
;
1534 mode11g
= &modes
[mode11g_idx
];
1535 mode
->num_channels
= mode11g
->num_channels
;
1536 mode
->channels
= os_memdup(mode11g
->channels
,
1537 mode11g
->num_channels
*
1538 sizeof(struct hostapd_channel_data
));
1539 if (mode
->channels
== NULL
) {
1541 return modes
; /* Could not add 802.11b mode */
1544 mode
->num_rates
= 0;
1545 mode
->rates
= os_malloc(4 * sizeof(int));
1546 if (mode
->rates
== NULL
) {
1547 os_free(mode
->channels
);
1549 return modes
; /* Could not add 802.11b mode */
1552 for (i
= 0; i
< mode11g
->num_rates
; i
++) {
1553 if (mode11g
->rates
[i
] != 10 && mode11g
->rates
[i
] != 20 &&
1554 mode11g
->rates
[i
] != 55 && mode11g
->rates
[i
] != 110)
1556 mode
->rates
[mode
->num_rates
] = mode11g
->rates
[i
];
1558 if (mode
->num_rates
== 4)
1562 if (mode
->num_rates
== 0) {
1563 os_free(mode
->channels
);
1564 os_free(mode
->rates
);
1566 return modes
; /* No 802.11b rates */
1569 wpa_printf(MSG_DEBUG
, "nl80211: Added 802.11b mode based on 802.11g "
1576 static void nl80211_set_ht40_mode(struct hostapd_hw_modes
*mode
, int start
,
1581 for (c
= 0; c
< mode
->num_channels
; c
++) {
1582 struct hostapd_channel_data
*chan
= &mode
->channels
[c
];
1583 if (chan
->freq
- 10 >= start
&& chan
->freq
+ 10 <= end
)
1584 chan
->flag
|= HOSTAPD_CHAN_HT40
;
1589 static void nl80211_set_ht40_mode_sec(struct hostapd_hw_modes
*mode
, int start
,
1594 for (c
= 0; c
< mode
->num_channels
; c
++) {
1595 struct hostapd_channel_data
*chan
= &mode
->channels
[c
];
1596 if (!(chan
->flag
& HOSTAPD_CHAN_HT40
))
1598 if (chan
->freq
- 30 >= start
&& chan
->freq
- 10 <= end
)
1599 chan
->flag
|= HOSTAPD_CHAN_HT40MINUS
;
1600 if (chan
->freq
+ 10 >= start
&& chan
->freq
+ 30 <= end
)
1601 chan
->flag
|= HOSTAPD_CHAN_HT40PLUS
;
1606 static void nl80211_reg_rule_max_eirp(u32 start
, u32 end
, u32 max_eirp
,
1607 struct phy_info_arg
*results
)
1611 for (m
= 0; m
< *results
->num_modes
; m
++) {
1613 struct hostapd_hw_modes
*mode
= &results
->modes
[m
];
1615 for (c
= 0; c
< mode
->num_channels
; c
++) {
1616 struct hostapd_channel_data
*chan
= &mode
->channels
[c
];
1617 if ((u32
) chan
->freq
- 10 >= start
&&
1618 (u32
) chan
->freq
+ 10 <= end
)
1619 chan
->max_tx_power
= max_eirp
;
1625 static void nl80211_reg_rule_ht40(u32 start
, u32 end
,
1626 struct phy_info_arg
*results
)
1630 for (m
= 0; m
< *results
->num_modes
; m
++) {
1631 if (!(results
->modes
[m
].ht_capab
&
1632 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET
))
1634 nl80211_set_ht40_mode(&results
->modes
[m
], start
, end
);
1639 static void nl80211_reg_rule_sec(struct nlattr
*tb
[],
1640 struct phy_info_arg
*results
)
1642 u32 start
, end
, max_bw
;
1645 if (tb
[NL80211_ATTR_FREQ_RANGE_START
] == NULL
||
1646 tb
[NL80211_ATTR_FREQ_RANGE_END
] == NULL
||
1647 tb
[NL80211_ATTR_FREQ_RANGE_MAX_BW
] == NULL
)
1650 start
= nla_get_u32(tb
[NL80211_ATTR_FREQ_RANGE_START
]) / 1000;
1651 end
= nla_get_u32(tb
[NL80211_ATTR_FREQ_RANGE_END
]) / 1000;
1652 max_bw
= nla_get_u32(tb
[NL80211_ATTR_FREQ_RANGE_MAX_BW
]) / 1000;
1657 for (m
= 0; m
< *results
->num_modes
; m
++) {
1658 if (!(results
->modes
[m
].ht_capab
&
1659 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET
))
1661 nl80211_set_ht40_mode_sec(&results
->modes
[m
], start
, end
);
1666 static void nl80211_set_vht_mode(struct hostapd_hw_modes
*mode
, int start
,
1667 int end
, int max_bw
)
1671 for (c
= 0; c
< mode
->num_channels
; c
++) {
1672 struct hostapd_channel_data
*chan
= &mode
->channels
[c
];
1673 if (chan
->freq
- 10 >= start
&& chan
->freq
+ 70 <= end
)
1674 chan
->flag
|= HOSTAPD_CHAN_VHT_10_70
;
1676 if (chan
->freq
- 30 >= start
&& chan
->freq
+ 50 <= end
)
1677 chan
->flag
|= HOSTAPD_CHAN_VHT_30_50
;
1679 if (chan
->freq
- 50 >= start
&& chan
->freq
+ 30 <= end
)
1680 chan
->flag
|= HOSTAPD_CHAN_VHT_50_30
;
1682 if (chan
->freq
- 70 >= start
&& chan
->freq
+ 10 <= end
)
1683 chan
->flag
|= HOSTAPD_CHAN_VHT_70_10
;
1685 if (max_bw
>= 160) {
1686 if (chan
->freq
- 10 >= start
&& chan
->freq
+ 150 <= end
)
1687 chan
->flag
|= HOSTAPD_CHAN_VHT_10_150
;
1689 if (chan
->freq
- 30 >= start
&& chan
->freq
+ 130 <= end
)
1690 chan
->flag
|= HOSTAPD_CHAN_VHT_30_130
;
1692 if (chan
->freq
- 50 >= start
&& chan
->freq
+ 110 <= end
)
1693 chan
->flag
|= HOSTAPD_CHAN_VHT_50_110
;
1695 if (chan
->freq
- 70 >= start
&& chan
->freq
+ 90 <= end
)
1696 chan
->flag
|= HOSTAPD_CHAN_VHT_70_90
;
1698 if (chan
->freq
- 90 >= start
&& chan
->freq
+ 70 <= end
)
1699 chan
->flag
|= HOSTAPD_CHAN_VHT_90_70
;
1701 if (chan
->freq
- 110 >= start
&& chan
->freq
+ 50 <= end
)
1702 chan
->flag
|= HOSTAPD_CHAN_VHT_110_50
;
1704 if (chan
->freq
- 130 >= start
&& chan
->freq
+ 30 <= end
)
1705 chan
->flag
|= HOSTAPD_CHAN_VHT_130_30
;
1707 if (chan
->freq
- 150 >= start
&& chan
->freq
+ 10 <= end
)
1708 chan
->flag
|= HOSTAPD_CHAN_VHT_150_10
;
1714 static void nl80211_reg_rule_vht(struct nlattr
*tb
[],
1715 struct phy_info_arg
*results
)
1717 u32 start
, end
, max_bw
;
1720 if (tb
[NL80211_ATTR_FREQ_RANGE_START
] == NULL
||
1721 tb
[NL80211_ATTR_FREQ_RANGE_END
] == NULL
||
1722 tb
[NL80211_ATTR_FREQ_RANGE_MAX_BW
] == NULL
)
1725 start
= nla_get_u32(tb
[NL80211_ATTR_FREQ_RANGE_START
]) / 1000;
1726 end
= nla_get_u32(tb
[NL80211_ATTR_FREQ_RANGE_END
]) / 1000;
1727 max_bw
= nla_get_u32(tb
[NL80211_ATTR_FREQ_RANGE_MAX_BW
]) / 1000;
1732 for (m
= 0; m
< *results
->num_modes
; m
++) {
1733 if (!(results
->modes
[m
].ht_capab
&
1734 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET
))
1736 /* TODO: use a real VHT support indication */
1737 if (!results
->modes
[m
].vht_capab
)
1740 nl80211_set_vht_mode(&results
->modes
[m
], start
, end
, max_bw
);
1745 static void nl80211_set_dfs_domain(enum nl80211_dfs_regions region
,
1748 if (region
== NL80211_DFS_FCC
)
1749 *dfs_domain
= HOSTAPD_DFS_REGION_FCC
;
1750 else if (region
== NL80211_DFS_ETSI
)
1751 *dfs_domain
= HOSTAPD_DFS_REGION_ETSI
;
1752 else if (region
== NL80211_DFS_JP
)
1753 *dfs_domain
= HOSTAPD_DFS_REGION_JP
;
1759 static const char * dfs_domain_name(enum nl80211_dfs_regions region
)
1762 case NL80211_DFS_UNSET
:
1764 case NL80211_DFS_FCC
:
1766 case NL80211_DFS_ETSI
:
1768 case NL80211_DFS_JP
:
1771 return "DFS-invalid";
1776 static int nl80211_get_reg(struct nl_msg
*msg
, void *arg
)
1778 struct phy_info_arg
*results
= arg
;
1779 struct nlattr
*tb_msg
[NL80211_ATTR_MAX
+ 1];
1780 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
1781 struct nlattr
*nl_rule
;
1782 struct nlattr
*tb_rule
[NL80211_FREQUENCY_ATTR_MAX
+ 1];
1784 static struct nla_policy reg_policy
[NL80211_FREQUENCY_ATTR_MAX
+ 1] = {
1785 [NL80211_ATTR_REG_RULE_FLAGS
] = { .type
= NLA_U32
},
1786 [NL80211_ATTR_FREQ_RANGE_START
] = { .type
= NLA_U32
},
1787 [NL80211_ATTR_FREQ_RANGE_END
] = { .type
= NLA_U32
},
1788 [NL80211_ATTR_FREQ_RANGE_MAX_BW
] = { .type
= NLA_U32
},
1789 [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN
] = { .type
= NLA_U32
},
1790 [NL80211_ATTR_POWER_RULE_MAX_EIRP
] = { .type
= NLA_U32
},
1793 nla_parse(tb_msg
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
1794 genlmsg_attrlen(gnlh
, 0), NULL
);
1795 if (!tb_msg
[NL80211_ATTR_REG_ALPHA2
] ||
1796 !tb_msg
[NL80211_ATTR_REG_RULES
]) {
1797 wpa_printf(MSG_DEBUG
, "nl80211: No regulatory information "
1802 if (tb_msg
[NL80211_ATTR_DFS_REGION
]) {
1803 enum nl80211_dfs_regions dfs_domain
;
1804 dfs_domain
= nla_get_u8(tb_msg
[NL80211_ATTR_DFS_REGION
]);
1805 nl80211_set_dfs_domain(dfs_domain
, &results
->dfs_domain
);
1806 wpa_printf(MSG_DEBUG
, "nl80211: Regulatory information - country=%s (%s)",
1807 (char *) nla_data(tb_msg
[NL80211_ATTR_REG_ALPHA2
]),
1808 dfs_domain_name(dfs_domain
));
1810 wpa_printf(MSG_DEBUG
, "nl80211: Regulatory information - country=%s",
1811 (char *) nla_data(tb_msg
[NL80211_ATTR_REG_ALPHA2
]));
1814 nla_for_each_nested(nl_rule
, tb_msg
[NL80211_ATTR_REG_RULES
], rem_rule
)
1816 u32 start
, end
, max_eirp
= 0, max_bw
= 0, flags
= 0;
1817 nla_parse(tb_rule
, NL80211_FREQUENCY_ATTR_MAX
,
1818 nla_data(nl_rule
), nla_len(nl_rule
), reg_policy
);
1819 if (tb_rule
[NL80211_ATTR_FREQ_RANGE_START
] == NULL
||
1820 tb_rule
[NL80211_ATTR_FREQ_RANGE_END
] == NULL
)
1822 start
= nla_get_u32(tb_rule
[NL80211_ATTR_FREQ_RANGE_START
]) / 1000;
1823 end
= nla_get_u32(tb_rule
[NL80211_ATTR_FREQ_RANGE_END
]) / 1000;
1824 if (tb_rule
[NL80211_ATTR_POWER_RULE_MAX_EIRP
])
1825 max_eirp
= nla_get_u32(tb_rule
[NL80211_ATTR_POWER_RULE_MAX_EIRP
]) / 100;
1826 if (tb_rule
[NL80211_ATTR_FREQ_RANGE_MAX_BW
])
1827 max_bw
= nla_get_u32(tb_rule
[NL80211_ATTR_FREQ_RANGE_MAX_BW
]) / 1000;
1828 if (tb_rule
[NL80211_ATTR_REG_RULE_FLAGS
])
1829 flags
= nla_get_u32(tb_rule
[NL80211_ATTR_REG_RULE_FLAGS
]);
1831 wpa_printf(MSG_DEBUG
, "nl80211: %u-%u @ %u MHz %u mBm%s%s%s%s%s%s%s%s",
1832 start
, end
, max_bw
, max_eirp
,
1833 flags
& NL80211_RRF_NO_OFDM
? " (no OFDM)" : "",
1834 flags
& NL80211_RRF_NO_CCK
? " (no CCK)" : "",
1835 flags
& NL80211_RRF_NO_INDOOR
? " (no indoor)" : "",
1836 flags
& NL80211_RRF_NO_OUTDOOR
? " (no outdoor)" :
1838 flags
& NL80211_RRF_DFS
? " (DFS)" : "",
1839 flags
& NL80211_RRF_PTP_ONLY
? " (PTP only)" : "",
1840 flags
& NL80211_RRF_PTMP_ONLY
? " (PTMP only)" : "",
1841 flags
& NL80211_RRF_NO_IR
? " (no IR)" : "");
1843 nl80211_reg_rule_ht40(start
, end
, results
);
1844 if (tb_rule
[NL80211_ATTR_POWER_RULE_MAX_EIRP
])
1845 nl80211_reg_rule_max_eirp(start
, end
, max_eirp
,
1849 nla_for_each_nested(nl_rule
, tb_msg
[NL80211_ATTR_REG_RULES
], rem_rule
)
1851 nla_parse(tb_rule
, NL80211_FREQUENCY_ATTR_MAX
,
1852 nla_data(nl_rule
), nla_len(nl_rule
), reg_policy
);
1853 nl80211_reg_rule_sec(tb_rule
, results
);
1856 nla_for_each_nested(nl_rule
, tb_msg
[NL80211_ATTR_REG_RULES
], rem_rule
)
1858 nla_parse(tb_rule
, NL80211_FREQUENCY_ATTR_MAX
,
1859 nla_data(nl_rule
), nla_len(nl_rule
), reg_policy
);
1860 nl80211_reg_rule_vht(tb_rule
, results
);
1867 static int nl80211_set_regulatory_flags(struct wpa_driver_nl80211_data
*drv
,
1868 struct phy_info_arg
*results
)
1872 msg
= nlmsg_alloc();
1876 nl80211_cmd(drv
, msg
, 0, NL80211_CMD_GET_REG
);
1877 return send_and_recv_msgs(drv
, msg
, nl80211_get_reg
, results
);
1881 struct hostapd_hw_modes
*
1882 nl80211_get_hw_feature_data(void *priv
, u16
*num_modes
, u16
*flags
,
1886 struct i802_bss
*bss
= priv
;
1887 struct wpa_driver_nl80211_data
*drv
= bss
->drv
;
1890 struct phy_info_arg result
= {
1891 .num_modes
= num_modes
,
1902 feat
= get_nl80211_protocol_features(drv
);
1903 if (feat
& NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP
)
1904 nl_flags
= NLM_F_DUMP
;
1905 if (!(msg
= nl80211_cmd_msg(bss
, nl_flags
, NL80211_CMD_GET_WIPHY
)) ||
1906 nla_put_flag(msg
, NL80211_ATTR_SPLIT_WIPHY_DUMP
)) {
1911 if (send_and_recv_msgs(drv
, msg
, phy_info_handler
, &result
) == 0) {
1912 nl80211_set_regulatory_flags(drv
, &result
);
1913 if (result
.failed
) {
1916 for (i
= 0; result
.modes
&& i
< *num_modes
; i
++) {
1917 os_free(result
.modes
[i
].channels
);
1918 os_free(result
.modes
[i
].rates
);
1920 os_free(result
.modes
);
1925 *dfs_domain
= result
.dfs_domain
;
1927 return wpa_driver_nl80211_postprocess_modes(result
.modes
,