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_defs.h"
16 #include "common/ieee802_11_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 monitor_supported
:1;
70 unsigned int auth_supported
:1;
71 unsigned int connect_supported
:1;
72 unsigned int p2p_go_supported
:1;
73 unsigned int p2p_client_supported
:1;
74 unsigned int p2p_go_ctwindow_supported
:1;
75 unsigned int p2p_concurrent
:1;
76 unsigned int channel_switch_supported
:1;
77 unsigned int set_qos_map_supported
:1;
78 unsigned int have_low_prio_scan
:1;
79 unsigned int wmm_ac_supported
:1;
80 unsigned int mac_addr_rand_scan_supported
:1;
81 unsigned int mac_addr_rand_sched_scan_supported
:1;
85 static unsigned int probe_resp_offload_support(int supp_protocols
)
87 unsigned int prot
= 0;
89 if (supp_protocols
& NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS
)
90 prot
|= WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS
;
91 if (supp_protocols
& NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2
)
92 prot
|= WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2
;
93 if (supp_protocols
& NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P
)
94 prot
|= WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P
;
95 if (supp_protocols
& NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U
)
96 prot
|= WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING
;
102 static void wiphy_info_supported_iftypes(struct wiphy_info_data
*info
,
105 struct nlattr
*nl_mode
;
111 nla_for_each_nested(nl_mode
, tb
, i
) {
112 switch (nla_type(nl_mode
)) {
113 case NL80211_IFTYPE_AP
:
114 info
->capa
->flags
|= WPA_DRIVER_FLAGS_AP
;
116 case NL80211_IFTYPE_MESH_POINT
:
117 info
->capa
->flags
|= WPA_DRIVER_FLAGS_MESH
;
119 case NL80211_IFTYPE_ADHOC
:
120 info
->capa
->flags
|= WPA_DRIVER_FLAGS_IBSS
;
122 case NL80211_IFTYPE_P2P_DEVICE
:
124 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE
;
126 case NL80211_IFTYPE_P2P_GO
:
127 info
->p2p_go_supported
= 1;
129 case NL80211_IFTYPE_P2P_CLIENT
:
130 info
->p2p_client_supported
= 1;
132 case NL80211_IFTYPE_MONITOR
:
133 info
->monitor_supported
= 1;
140 static int wiphy_info_iface_comb_process(struct wiphy_info_data
*info
,
141 struct nlattr
*nl_combi
)
143 struct nlattr
*tb_comb
[NUM_NL80211_IFACE_COMB
];
144 struct nlattr
*tb_limit
[NUM_NL80211_IFACE_LIMIT
];
145 struct nlattr
*nl_limit
, *nl_mode
;
146 int err
, rem_limit
, rem_mode
;
147 int combination_has_p2p
= 0, combination_has_mgd
= 0;
148 static struct nla_policy
149 iface_combination_policy
[NUM_NL80211_IFACE_COMB
] = {
150 [NL80211_IFACE_COMB_LIMITS
] = { .type
= NLA_NESTED
},
151 [NL80211_IFACE_COMB_MAXNUM
] = { .type
= NLA_U32
},
152 [NL80211_IFACE_COMB_STA_AP_BI_MATCH
] = { .type
= NLA_FLAG
},
153 [NL80211_IFACE_COMB_NUM_CHANNELS
] = { .type
= NLA_U32
},
154 [NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS
] = { .type
= NLA_U32
},
156 iface_limit_policy
[NUM_NL80211_IFACE_LIMIT
] = {
157 [NL80211_IFACE_LIMIT_TYPES
] = { .type
= NLA_NESTED
},
158 [NL80211_IFACE_LIMIT_MAX
] = { .type
= NLA_U32
},
161 err
= nla_parse_nested(tb_comb
, MAX_NL80211_IFACE_COMB
,
162 nl_combi
, iface_combination_policy
);
163 if (err
|| !tb_comb
[NL80211_IFACE_COMB_LIMITS
] ||
164 !tb_comb
[NL80211_IFACE_COMB_MAXNUM
] ||
165 !tb_comb
[NL80211_IFACE_COMB_NUM_CHANNELS
])
166 return 0; /* broken combination */
168 if (tb_comb
[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS
])
169 info
->capa
->flags
|= WPA_DRIVER_FLAGS_RADAR
;
171 nla_for_each_nested(nl_limit
, tb_comb
[NL80211_IFACE_COMB_LIMITS
],
173 err
= nla_parse_nested(tb_limit
, MAX_NL80211_IFACE_LIMIT
,
174 nl_limit
, iface_limit_policy
);
175 if (err
|| !tb_limit
[NL80211_IFACE_LIMIT_TYPES
])
176 return 0; /* broken combination */
178 nla_for_each_nested(nl_mode
,
179 tb_limit
[NL80211_IFACE_LIMIT_TYPES
],
181 int ift
= nla_type(nl_mode
);
182 if (ift
== NL80211_IFTYPE_P2P_GO
||
183 ift
== NL80211_IFTYPE_P2P_CLIENT
)
184 combination_has_p2p
= 1;
185 if (ift
== NL80211_IFTYPE_STATION
)
186 combination_has_mgd
= 1;
188 if (combination_has_p2p
&& combination_has_mgd
)
192 if (combination_has_p2p
&& combination_has_mgd
) {
193 unsigned int num_channels
=
194 nla_get_u32(tb_comb
[NL80211_IFACE_COMB_NUM_CHANNELS
]);
196 info
->p2p_concurrent
= 1;
197 if (info
->num_multichan_concurrent
< num_channels
)
198 info
->num_multichan_concurrent
= num_channels
;
205 static void wiphy_info_iface_comb(struct wiphy_info_data
*info
,
208 struct nlattr
*nl_combi
;
214 nla_for_each_nested(nl_combi
, tb
, rem_combi
) {
215 if (wiphy_info_iface_comb_process(info
, nl_combi
) > 0)
221 static void wiphy_info_supp_cmds(struct wiphy_info_data
*info
,
224 struct nlattr
*nl_cmd
;
230 nla_for_each_nested(nl_cmd
, tb
, i
) {
231 switch (nla_get_u32(nl_cmd
)) {
232 case NL80211_CMD_AUTHENTICATE
:
233 info
->auth_supported
= 1;
235 case NL80211_CMD_CONNECT
:
236 info
->connect_supported
= 1;
238 case NL80211_CMD_START_SCHED_SCAN
:
239 info
->capa
->sched_scan_supported
= 1;
241 case NL80211_CMD_PROBE_CLIENT
:
242 info
->poll_command_supported
= 1;
244 case NL80211_CMD_CHANNEL_SWITCH
:
245 info
->channel_switch_supported
= 1;
247 case NL80211_CMD_SET_QOS_MAP
:
248 info
->set_qos_map_supported
= 1;
255 static void wiphy_info_cipher_suites(struct wiphy_info_data
*info
,
264 num
= nla_len(tb
) / sizeof(u32
);
265 ciphers
= nla_data(tb
);
266 for (i
= 0; i
< num
; i
++) {
269 wpa_printf(MSG_DEBUG
, "nl80211: Supported cipher %02x-%02x-%02x:%d",
270 c
>> 24, (c
>> 16) & 0xff,
271 (c
>> 8) & 0xff, c
& 0xff);
273 case WLAN_CIPHER_SUITE_CCMP_256
:
274 info
->capa
->enc
|= WPA_DRIVER_CAPA_ENC_CCMP_256
;
276 case WLAN_CIPHER_SUITE_GCMP_256
:
277 info
->capa
->enc
|= WPA_DRIVER_CAPA_ENC_GCMP_256
;
279 case WLAN_CIPHER_SUITE_CCMP
:
280 info
->capa
->enc
|= WPA_DRIVER_CAPA_ENC_CCMP
;
282 case WLAN_CIPHER_SUITE_GCMP
:
283 info
->capa
->enc
|= WPA_DRIVER_CAPA_ENC_GCMP
;
285 case WLAN_CIPHER_SUITE_TKIP
:
286 info
->capa
->enc
|= WPA_DRIVER_CAPA_ENC_TKIP
;
288 case WLAN_CIPHER_SUITE_WEP104
:
289 info
->capa
->enc
|= WPA_DRIVER_CAPA_ENC_WEP104
;
291 case WLAN_CIPHER_SUITE_WEP40
:
292 info
->capa
->enc
|= WPA_DRIVER_CAPA_ENC_WEP40
;
294 case WLAN_CIPHER_SUITE_AES_CMAC
:
295 info
->capa
->enc
|= WPA_DRIVER_CAPA_ENC_BIP
;
297 case WLAN_CIPHER_SUITE_BIP_GMAC_128
:
298 info
->capa
->enc
|= WPA_DRIVER_CAPA_ENC_BIP_GMAC_128
;
300 case WLAN_CIPHER_SUITE_BIP_GMAC_256
:
301 info
->capa
->enc
|= WPA_DRIVER_CAPA_ENC_BIP_GMAC_256
;
303 case WLAN_CIPHER_SUITE_BIP_CMAC_256
:
304 info
->capa
->enc
|= WPA_DRIVER_CAPA_ENC_BIP_CMAC_256
;
306 case WLAN_CIPHER_SUITE_NO_GROUP_ADDR
:
307 info
->capa
->enc
|= WPA_DRIVER_CAPA_ENC_GTK_NOT_USED
;
314 static void wiphy_info_max_roc(struct wpa_driver_capa
*capa
,
318 capa
->max_remain_on_chan
= nla_get_u32(tb
);
322 static void wiphy_info_tdls(struct wpa_driver_capa
*capa
, struct nlattr
*tdls
,
323 struct nlattr
*ext_setup
)
328 wpa_printf(MSG_DEBUG
, "nl80211: TDLS supported");
329 capa
->flags
|= WPA_DRIVER_FLAGS_TDLS_SUPPORT
;
332 wpa_printf(MSG_DEBUG
, "nl80211: TDLS external setup");
333 capa
->flags
|= WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP
;
338 static int ext_feature_isset(const u8
*ext_features
, int ext_features_len
,
339 enum nl80211_ext_feature_index ftidx
)
343 if ((int) ftidx
/ 8 >= ext_features_len
)
346 ft_byte
= ext_features
[ftidx
/ 8];
347 return (ft_byte
& BIT(ftidx
% 8)) != 0;
351 static void wiphy_info_ext_feature_flags(struct wiphy_info_data
*info
,
354 struct wpa_driver_capa
*capa
= info
->capa
;
359 if (ext_feature_isset(nla_data(tb
), nla_len(tb
),
360 NL80211_EXT_FEATURE_VHT_IBSS
))
361 capa
->flags
|= WPA_DRIVER_FLAGS_VHT_IBSS
;
365 static void wiphy_info_feature_flags(struct wiphy_info_data
*info
,
369 struct wpa_driver_capa
*capa
= info
->capa
;
374 flags
= nla_get_u32(tb
);
376 if (flags
& NL80211_FEATURE_SK_TX_STATUS
)
377 info
->data_tx_status
= 1;
379 if (flags
& NL80211_FEATURE_INACTIVITY_TIMER
)
380 capa
->flags
|= WPA_DRIVER_FLAGS_INACTIVITY_TIMER
;
382 if (flags
& NL80211_FEATURE_SAE
)
383 capa
->flags
|= WPA_DRIVER_FLAGS_SAE
;
385 if (flags
& NL80211_FEATURE_NEED_OBSS_SCAN
)
386 capa
->flags
|= WPA_DRIVER_FLAGS_OBSS_SCAN
;
388 if (flags
& NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE
)
389 capa
->flags
|= WPA_DRIVER_FLAGS_HT_2040_COEX
;
391 if (flags
& NL80211_FEATURE_TDLS_CHANNEL_SWITCH
) {
392 wpa_printf(MSG_DEBUG
, "nl80211: TDLS channel switch");
393 capa
->flags
|= WPA_DRIVER_FLAGS_TDLS_CHANNEL_SWITCH
;
396 if (flags
& NL80211_FEATURE_P2P_GO_CTWIN
)
397 info
->p2p_go_ctwindow_supported
= 1;
399 if (flags
& NL80211_FEATURE_LOW_PRIORITY_SCAN
)
400 info
->have_low_prio_scan
= 1;
402 if (flags
& NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR
)
403 info
->mac_addr_rand_scan_supported
= 1;
405 if (flags
& NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR
)
406 info
->mac_addr_rand_sched_scan_supported
= 1;
408 if (flags
& NL80211_FEATURE_STATIC_SMPS
)
409 capa
->smps_modes
|= WPA_DRIVER_SMPS_MODE_STATIC
;
411 if (flags
& NL80211_FEATURE_DYNAMIC_SMPS
)
412 capa
->smps_modes
|= WPA_DRIVER_SMPS_MODE_DYNAMIC
;
414 if (flags
& NL80211_FEATURE_SUPPORTS_WMM_ADMISSION
)
415 info
->wmm_ac_supported
= 1;
417 if (flags
& NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES
)
418 capa
->rrm_flags
|= WPA_DRIVER_FLAGS_DS_PARAM_SET_IE_IN_PROBES
;
420 if (flags
& NL80211_FEATURE_WFA_TPC_IE_IN_PROBES
)
421 capa
->rrm_flags
|= WPA_DRIVER_FLAGS_WFA_TPC_IE_IN_PROBES
;
423 if (flags
& NL80211_FEATURE_QUIET
)
424 capa
->rrm_flags
|= WPA_DRIVER_FLAGS_QUIET
;
426 if (flags
& NL80211_FEATURE_TX_POWER_INSERTION
)
427 capa
->rrm_flags
|= WPA_DRIVER_FLAGS_TX_POWER_INSERTION
;
429 if (flags
& NL80211_FEATURE_HT_IBSS
)
430 capa
->flags
|= WPA_DRIVER_FLAGS_HT_IBSS
;
434 static void wiphy_info_probe_resp_offload(struct wpa_driver_capa
*capa
,
442 protocols
= nla_get_u32(tb
);
443 wpa_printf(MSG_DEBUG
, "nl80211: Supports Probe Response offload in AP "
445 capa
->flags
|= WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD
;
446 capa
->probe_resp_offloads
= probe_resp_offload_support(protocols
);
450 static void wiphy_info_wowlan_triggers(struct wpa_driver_capa
*capa
,
453 struct nlattr
*triggers
[MAX_NL80211_WOWLAN_TRIG
+ 1];
458 if (nla_parse_nested(triggers
, MAX_NL80211_WOWLAN_TRIG
,
462 if (triggers
[NL80211_WOWLAN_TRIG_ANY
])
463 capa
->wowlan_triggers
.any
= 1;
464 if (triggers
[NL80211_WOWLAN_TRIG_DISCONNECT
])
465 capa
->wowlan_triggers
.disconnect
= 1;
466 if (triggers
[NL80211_WOWLAN_TRIG_MAGIC_PKT
])
467 capa
->wowlan_triggers
.magic_pkt
= 1;
468 if (triggers
[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE
])
469 capa
->wowlan_triggers
.gtk_rekey_failure
= 1;
470 if (triggers
[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST
])
471 capa
->wowlan_triggers
.eap_identity_req
= 1;
472 if (triggers
[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE
])
473 capa
->wowlan_triggers
.four_way_handshake
= 1;
474 if (triggers
[NL80211_WOWLAN_TRIG_RFKILL_RELEASE
])
475 capa
->wowlan_triggers
.rfkill_release
= 1;
479 static int wiphy_info_handler(struct nl_msg
*msg
, void *arg
)
481 struct nlattr
*tb
[NL80211_ATTR_MAX
+ 1];
482 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
483 struct wiphy_info_data
*info
= arg
;
484 struct wpa_driver_capa
*capa
= info
->capa
;
485 struct wpa_driver_nl80211_data
*drv
= info
->drv
;
487 nla_parse(tb
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
488 genlmsg_attrlen(gnlh
, 0), NULL
);
490 if (tb
[NL80211_ATTR_WIPHY_NAME
])
491 os_strlcpy(drv
->phyname
,
492 nla_get_string(tb
[NL80211_ATTR_WIPHY_NAME
]),
493 sizeof(drv
->phyname
));
494 if (tb
[NL80211_ATTR_MAX_NUM_SCAN_SSIDS
])
495 capa
->max_scan_ssids
=
496 nla_get_u8(tb
[NL80211_ATTR_MAX_NUM_SCAN_SSIDS
]);
498 if (tb
[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS
])
499 capa
->max_sched_scan_ssids
=
500 nla_get_u8(tb
[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS
]);
502 if (tb
[NL80211_ATTR_MAX_MATCH_SETS
])
503 capa
->max_match_sets
=
504 nla_get_u8(tb
[NL80211_ATTR_MAX_MATCH_SETS
]);
506 if (tb
[NL80211_ATTR_MAC_ACL_MAX
])
507 capa
->max_acl_mac_addrs
=
508 nla_get_u8(tb
[NL80211_ATTR_MAC_ACL_MAX
]);
510 wiphy_info_supported_iftypes(info
, tb
[NL80211_ATTR_SUPPORTED_IFTYPES
]);
511 wiphy_info_iface_comb(info
, tb
[NL80211_ATTR_INTERFACE_COMBINATIONS
]);
512 wiphy_info_supp_cmds(info
, tb
[NL80211_ATTR_SUPPORTED_COMMANDS
]);
513 wiphy_info_cipher_suites(info
, tb
[NL80211_ATTR_CIPHER_SUITES
]);
515 if (tb
[NL80211_ATTR_OFFCHANNEL_TX_OK
]) {
516 wpa_printf(MSG_DEBUG
, "nl80211: Using driver-based "
518 capa
->flags
|= WPA_DRIVER_FLAGS_OFFCHANNEL_TX
;
521 if (tb
[NL80211_ATTR_ROAM_SUPPORT
]) {
522 wpa_printf(MSG_DEBUG
, "nl80211: Using driver-based roaming");
523 capa
->flags
|= WPA_DRIVER_FLAGS_BSS_SELECTION
;
526 wiphy_info_max_roc(capa
,
527 tb
[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION
]);
529 if (tb
[NL80211_ATTR_SUPPORT_AP_UAPSD
])
530 capa
->flags
|= WPA_DRIVER_FLAGS_AP_UAPSD
;
532 wiphy_info_tdls(capa
, tb
[NL80211_ATTR_TDLS_SUPPORT
],
533 tb
[NL80211_ATTR_TDLS_EXTERNAL_SETUP
]);
535 if (tb
[NL80211_ATTR_DEVICE_AP_SME
])
536 info
->device_ap_sme
= 1;
538 wiphy_info_feature_flags(info
, tb
[NL80211_ATTR_FEATURE_FLAGS
]);
539 wiphy_info_ext_feature_flags(info
, tb
[NL80211_ATTR_EXT_FEATURES
]);
540 wiphy_info_probe_resp_offload(capa
,
541 tb
[NL80211_ATTR_PROBE_RESP_OFFLOAD
]);
543 if (tb
[NL80211_ATTR_EXT_CAPA
] && tb
[NL80211_ATTR_EXT_CAPA_MASK
] &&
544 drv
->extended_capa
== NULL
) {
546 os_malloc(nla_len(tb
[NL80211_ATTR_EXT_CAPA
]));
547 if (drv
->extended_capa
) {
548 os_memcpy(drv
->extended_capa
,
549 nla_data(tb
[NL80211_ATTR_EXT_CAPA
]),
550 nla_len(tb
[NL80211_ATTR_EXT_CAPA
]));
551 drv
->extended_capa_len
=
552 nla_len(tb
[NL80211_ATTR_EXT_CAPA
]);
554 drv
->extended_capa_mask
=
555 os_malloc(nla_len(tb
[NL80211_ATTR_EXT_CAPA_MASK
]));
556 if (drv
->extended_capa_mask
) {
557 os_memcpy(drv
->extended_capa_mask
,
558 nla_data(tb
[NL80211_ATTR_EXT_CAPA_MASK
]),
559 nla_len(tb
[NL80211_ATTR_EXT_CAPA_MASK
]));
561 os_free(drv
->extended_capa
);
562 drv
->extended_capa
= NULL
;
563 drv
->extended_capa_len
= 0;
567 if (tb
[NL80211_ATTR_VENDOR_DATA
]) {
571 nla_for_each_nested(nl
, tb
[NL80211_ATTR_VENDOR_DATA
], rem
) {
572 struct nl80211_vendor_cmd_info
*vinfo
;
573 if (nla_len(nl
) != sizeof(*vinfo
)) {
574 wpa_printf(MSG_DEBUG
, "nl80211: Unexpected vendor data info");
577 vinfo
= nla_data(nl
);
578 if (vinfo
->vendor_id
== OUI_QCA
) {
579 switch (vinfo
->subcmd
) {
580 case QCA_NL80211_VENDOR_SUBCMD_TEST
:
581 drv
->vendor_cmd_test_avail
= 1;
583 case QCA_NL80211_VENDOR_SUBCMD_ROAMING
:
584 drv
->roaming_vendor_cmd_avail
= 1;
586 case QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY
:
587 drv
->dfs_vendor_cmd_avail
= 1;
589 case QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES
:
590 drv
->get_features_vendor_cmd_avail
= 1;
592 case QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST
:
593 drv
->get_pref_freq_list
= 1;
595 case QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL
:
596 drv
->set_prob_oper_freq
= 1;
598 case QCA_NL80211_VENDOR_SUBCMD_DO_ACS
:
600 WPA_DRIVER_FLAGS_ACS_OFFLOAD
;
602 case QCA_NL80211_VENDOR_SUBCMD_SETBAND
:
603 drv
->setband_vendor_cmd_avail
= 1;
605 case QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
:
606 drv
->scan_vendor_cmd_avail
= 1;
611 wpa_printf(MSG_DEBUG
, "nl80211: Supported vendor command: vendor_id=0x%x subcmd=%u",
612 vinfo
->vendor_id
, vinfo
->subcmd
);
616 if (tb
[NL80211_ATTR_VENDOR_EVENTS
]) {
620 nla_for_each_nested(nl
, tb
[NL80211_ATTR_VENDOR_EVENTS
], rem
) {
621 struct nl80211_vendor_cmd_info
*vinfo
;
622 if (nla_len(nl
) != sizeof(*vinfo
)) {
623 wpa_printf(MSG_DEBUG
, "nl80211: Unexpected vendor data info");
626 vinfo
= nla_data(nl
);
627 wpa_printf(MSG_DEBUG
, "nl80211: Supported vendor event: vendor_id=0x%x subcmd=%u",
628 vinfo
->vendor_id
, vinfo
->subcmd
);
632 wiphy_info_wowlan_triggers(capa
,
633 tb
[NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED
]);
635 if (tb
[NL80211_ATTR_MAX_AP_ASSOC_STA
])
637 nla_get_u32(tb
[NL80211_ATTR_MAX_AP_ASSOC_STA
]);
643 static int wpa_driver_nl80211_get_info(struct wpa_driver_nl80211_data
*drv
,
644 struct wiphy_info_data
*info
)
650 os_memset(info
, 0, sizeof(*info
));
651 info
->capa
= &drv
->capa
;
654 feat
= get_nl80211_protocol_features(drv
);
655 if (feat
& NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP
)
657 msg
= nl80211_cmd_msg(drv
->first_bss
, flags
, NL80211_CMD_GET_WIPHY
);
658 if (!msg
|| nla_put_flag(msg
, NL80211_ATTR_SPLIT_WIPHY_DUMP
)) {
663 if (send_and_recv_msgs(drv
, msg
, wiphy_info_handler
, info
))
666 if (info
->auth_supported
)
667 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_SME
;
668 else if (!info
->connect_supported
) {
669 wpa_printf(MSG_INFO
, "nl80211: Driver does not support "
670 "authentication/association or connect commands");
674 if (info
->p2p_go_supported
&& info
->p2p_client_supported
)
675 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_P2P_CAPABLE
;
676 if (info
->p2p_concurrent
) {
677 wpa_printf(MSG_DEBUG
, "nl80211: Use separate P2P group "
678 "interface (driver advertised support)");
679 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_P2P_CONCURRENT
;
680 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P
;
682 if (info
->num_multichan_concurrent
> 1) {
683 wpa_printf(MSG_DEBUG
, "nl80211: Enable multi-channel "
684 "concurrent (driver advertised support)");
685 drv
->capa
.num_multichan_concurrent
=
686 info
->num_multichan_concurrent
;
688 if (drv
->capa
.flags
& WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE
)
689 wpa_printf(MSG_DEBUG
, "nl80211: use P2P_DEVICE support");
691 /* default to 5000 since early versions of mac80211 don't set it */
692 if (!drv
->capa
.max_remain_on_chan
)
693 drv
->capa
.max_remain_on_chan
= 5000;
695 if (info
->channel_switch_supported
)
696 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_AP_CSA
;
697 drv
->capa
.wmm_ac_supported
= info
->wmm_ac_supported
;
699 drv
->capa
.mac_addr_rand_sched_scan_supported
=
700 info
->mac_addr_rand_sched_scan_supported
;
701 drv
->capa
.mac_addr_rand_scan_supported
=
702 info
->mac_addr_rand_scan_supported
;
708 static int dfs_info_handler(struct nl_msg
*msg
, void *arg
)
710 struct nlattr
*tb
[NL80211_ATTR_MAX
+ 1];
711 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
712 int *dfs_capability_ptr
= arg
;
714 nla_parse(tb
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
715 genlmsg_attrlen(gnlh
, 0), NULL
);
717 if (tb
[NL80211_ATTR_VENDOR_DATA
]) {
718 struct nlattr
*nl_vend
= tb
[NL80211_ATTR_VENDOR_DATA
];
719 struct nlattr
*tb_vendor
[QCA_WLAN_VENDOR_ATTR_MAX
+ 1];
721 nla_parse(tb_vendor
, QCA_WLAN_VENDOR_ATTR_MAX
,
722 nla_data(nl_vend
), nla_len(nl_vend
), NULL
);
724 if (tb_vendor
[QCA_WLAN_VENDOR_ATTR_DFS
]) {
726 val
= nla_get_u32(tb_vendor
[QCA_WLAN_VENDOR_ATTR_DFS
]);
727 wpa_printf(MSG_DEBUG
, "nl80211: DFS offload capability: %u",
729 *dfs_capability_ptr
= val
;
737 static void qca_nl80211_check_dfs_capa(struct wpa_driver_nl80211_data
*drv
)
740 int dfs_capability
= 0;
743 if (!drv
->dfs_vendor_cmd_avail
)
746 if (!(msg
= nl80211_drv_msg(drv
, 0, NL80211_CMD_VENDOR
)) ||
747 nla_put_u32(msg
, NL80211_ATTR_VENDOR_ID
, OUI_QCA
) ||
748 nla_put_u32(msg
, NL80211_ATTR_VENDOR_SUBCMD
,
749 QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY
)) {
754 ret
= send_and_recv_msgs(drv
, msg
, dfs_info_handler
, &dfs_capability
);
755 if (!ret
&& dfs_capability
)
756 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_DFS_OFFLOAD
;
760 struct features_info
{
763 struct wpa_driver_capa
*capa
;
767 static int features_info_handler(struct nl_msg
*msg
, void *arg
)
769 struct nlattr
*tb
[NL80211_ATTR_MAX
+ 1];
770 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
771 struct features_info
*info
= arg
;
772 struct nlattr
*nl_vend
, *attr
;
774 nla_parse(tb
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
775 genlmsg_attrlen(gnlh
, 0), NULL
);
777 nl_vend
= tb
[NL80211_ATTR_VENDOR_DATA
];
779 struct nlattr
*tb_vendor
[QCA_WLAN_VENDOR_ATTR_MAX
+ 1];
781 nla_parse(tb_vendor
, QCA_WLAN_VENDOR_ATTR_MAX
,
782 nla_data(nl_vend
), nla_len(nl_vend
), NULL
);
784 attr
= tb_vendor
[QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS
];
786 info
->flags
= nla_data(attr
);
787 info
->flags_len
= nla_len(attr
);
789 attr
= tb_vendor
[QCA_WLAN_VENDOR_ATTR_CONCURRENCY_CAPA
];
791 info
->capa
->conc_capab
= nla_get_u32(attr
);
794 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND
];
796 info
->capa
->max_conc_chan_2_4
= nla_get_u32(attr
);
799 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND
];
801 info
->capa
->max_conc_chan_5_0
= nla_get_u32(attr
);
808 static int check_feature(enum qca_wlan_vendor_features feature
,
809 struct features_info
*info
)
811 size_t idx
= feature
/ 8;
813 return (idx
< info
->flags_len
) &&
814 (info
->flags
[idx
] & BIT(feature
% 8));
818 static void qca_nl80211_get_features(struct wpa_driver_nl80211_data
*drv
)
821 struct features_info info
;
824 if (!drv
->get_features_vendor_cmd_avail
)
827 if (!(msg
= nl80211_drv_msg(drv
, 0, NL80211_CMD_VENDOR
)) ||
828 nla_put_u32(msg
, NL80211_ATTR_VENDOR_ID
, OUI_QCA
) ||
829 nla_put_u32(msg
, NL80211_ATTR_VENDOR_SUBCMD
,
830 QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES
)) {
835 os_memset(&info
, 0, sizeof(info
));
836 info
.capa
= &drv
->capa
;
837 ret
= send_and_recv_msgs(drv
, msg
, features_info_handler
, &info
);
838 if (ret
|| !info
.flags
)
841 if (check_feature(QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD
, &info
))
842 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD
;
844 if (check_feature(QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY
, &info
))
845 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY
;
847 if (check_feature(QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS
,
849 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS
;
853 int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data
*drv
)
855 struct wiphy_info_data info
;
856 if (wpa_driver_nl80211_get_info(drv
, &info
))
862 drv
->has_capability
= 1;
863 drv
->capa
.key_mgmt
= WPA_DRIVER_CAPA_KEY_MGMT_WPA
|
864 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK
|
865 WPA_DRIVER_CAPA_KEY_MGMT_WPA2
|
866 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK
|
867 WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B
|
868 WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192
;
869 drv
->capa
.auth
= WPA_DRIVER_AUTH_OPEN
|
870 WPA_DRIVER_AUTH_SHARED
|
871 WPA_DRIVER_AUTH_LEAP
;
873 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_SANE_ERROR_CODES
;
874 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE
;
875 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_EAPOL_TX_STATUS
;
878 * As all cfg80211 drivers must support cases where the AP interface is
879 * removed without the knowledge of wpa_supplicant/hostapd, e.g., in
880 * case that the user space daemon has crashed, they must be able to
881 * cleanup all stations and key entries in the AP tear down flow. Thus,
882 * this flag can/should always be set for cfg80211 drivers.
884 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT
;
886 if (!info
.device_ap_sme
) {
887 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS
;
890 * No AP SME is currently assumed to also indicate no AP MLME
891 * in the driver/firmware.
893 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_AP_MLME
;
896 drv
->device_ap_sme
= info
.device_ap_sme
;
897 drv
->poll_command_supported
= info
.poll_command_supported
;
898 drv
->data_tx_status
= info
.data_tx_status
;
899 drv
->p2p_go_ctwindow_supported
= info
.p2p_go_ctwindow_supported
;
900 if (info
.set_qos_map_supported
)
901 drv
->capa
.flags
|= WPA_DRIVER_FLAGS_QOS_MAPPING
;
902 drv
->have_low_prio_scan
= info
.have_low_prio_scan
;
905 * If poll command and tx status are supported, mac80211 is new enough
906 * to have everything we need to not need monitor interfaces.
908 drv
->use_monitor
= !info
.poll_command_supported
|| !info
.data_tx_status
;
910 if (drv
->device_ap_sme
&& drv
->use_monitor
) {
912 * Non-mac80211 drivers may not support monitor interface.
913 * Make sure we do not get stuck with incorrect capability here
914 * by explicitly testing this.
916 if (!info
.monitor_supported
) {
917 wpa_printf(MSG_DEBUG
, "nl80211: Disable use_monitor "
918 "with device_ap_sme since no monitor mode "
920 drv
->use_monitor
= 0;
925 * If we aren't going to use monitor interfaces, but the
926 * driver doesn't support data TX status, we won't get TX
927 * status for EAPOL frames.
929 if (!drv
->use_monitor
&& !info
.data_tx_status
)
930 drv
->capa
.flags
&= ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS
;
932 qca_nl80211_check_dfs_capa(drv
);
933 qca_nl80211_get_features(drv
);
936 * To enable offchannel simultaneous support in wpa_supplicant, the
937 * underlying driver needs to support the same along with offchannel TX.
938 * Offchannel TX support is needed since remain_on_channel and
939 * action_tx use some common data structures and hence cannot be
940 * scheduled simultaneously.
942 if (!(drv
->capa
.flags
& WPA_DRIVER_FLAGS_OFFCHANNEL_TX
))
943 drv
->capa
.flags
&= ~WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS
;
949 struct phy_info_arg
{
951 struct hostapd_hw_modes
*modes
;
952 int last_mode
, last_chan_idx
;
955 static void phy_info_ht_capa(struct hostapd_hw_modes
*mode
, struct nlattr
*capa
,
956 struct nlattr
*ampdu_factor
,
957 struct nlattr
*ampdu_density
,
958 struct nlattr
*mcs_set
)
961 mode
->ht_capab
= nla_get_u16(capa
);
964 mode
->a_mpdu_params
|= nla_get_u8(ampdu_factor
) & 0x03;
967 mode
->a_mpdu_params
|= nla_get_u8(ampdu_density
) << 2;
969 if (mcs_set
&& nla_len(mcs_set
) >= 16) {
971 mcs
= nla_data(mcs_set
);
972 os_memcpy(mode
->mcs_set
, mcs
, 16);
977 static void phy_info_vht_capa(struct hostapd_hw_modes
*mode
,
979 struct nlattr
*mcs_set
)
982 mode
->vht_capab
= nla_get_u32(capa
);
984 if (mcs_set
&& nla_len(mcs_set
) >= 8) {
986 mcs
= nla_data(mcs_set
);
987 os_memcpy(mode
->vht_mcs_set
, mcs
, 8);
992 static void phy_info_freq(struct hostapd_hw_modes
*mode
,
993 struct hostapd_channel_data
*chan
,
994 struct nlattr
*tb_freq
[])
997 chan
->freq
= nla_get_u32(tb_freq
[NL80211_FREQUENCY_ATTR_FREQ
]);
999 chan
->dfs_cac_ms
= 0;
1000 if (ieee80211_freq_to_chan(chan
->freq
, &channel
) != NUM_HOSTAPD_MODES
)
1001 chan
->chan
= channel
;
1003 if (tb_freq
[NL80211_FREQUENCY_ATTR_DISABLED
])
1004 chan
->flag
|= HOSTAPD_CHAN_DISABLED
;
1005 if (tb_freq
[NL80211_FREQUENCY_ATTR_NO_IR
])
1006 chan
->flag
|= HOSTAPD_CHAN_NO_IR
;
1007 if (tb_freq
[NL80211_FREQUENCY_ATTR_RADAR
])
1008 chan
->flag
|= HOSTAPD_CHAN_RADAR
;
1009 if (tb_freq
[NL80211_FREQUENCY_ATTR_INDOOR_ONLY
])
1010 chan
->flag
|= HOSTAPD_CHAN_INDOOR_ONLY
;
1011 if (tb_freq
[NL80211_FREQUENCY_ATTR_GO_CONCURRENT
])
1012 chan
->flag
|= HOSTAPD_CHAN_GO_CONCURRENT
;
1014 if (tb_freq
[NL80211_FREQUENCY_ATTR_DFS_STATE
]) {
1015 enum nl80211_dfs_state state
=
1016 nla_get_u32(tb_freq
[NL80211_FREQUENCY_ATTR_DFS_STATE
]);
1019 case NL80211_DFS_USABLE
:
1020 chan
->flag
|= HOSTAPD_CHAN_DFS_USABLE
;
1022 case NL80211_DFS_AVAILABLE
:
1023 chan
->flag
|= HOSTAPD_CHAN_DFS_AVAILABLE
;
1025 case NL80211_DFS_UNAVAILABLE
:
1026 chan
->flag
|= HOSTAPD_CHAN_DFS_UNAVAILABLE
;
1031 if (tb_freq
[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME
]) {
1032 chan
->dfs_cac_ms
= nla_get_u32(
1033 tb_freq
[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME
]);
1038 static int phy_info_freqs(struct phy_info_arg
*phy_info
,
1039 struct hostapd_hw_modes
*mode
, struct nlattr
*tb
)
1041 static struct nla_policy freq_policy
[NL80211_FREQUENCY_ATTR_MAX
+ 1] = {
1042 [NL80211_FREQUENCY_ATTR_FREQ
] = { .type
= NLA_U32
},
1043 [NL80211_FREQUENCY_ATTR_DISABLED
] = { .type
= NLA_FLAG
},
1044 [NL80211_FREQUENCY_ATTR_NO_IR
] = { .type
= NLA_FLAG
},
1045 [NL80211_FREQUENCY_ATTR_RADAR
] = { .type
= NLA_FLAG
},
1046 [NL80211_FREQUENCY_ATTR_MAX_TX_POWER
] = { .type
= NLA_U32
},
1047 [NL80211_FREQUENCY_ATTR_DFS_STATE
] = { .type
= NLA_U32
},
1049 int new_channels
= 0;
1050 struct hostapd_channel_data
*channel
;
1051 struct nlattr
*tb_freq
[NL80211_FREQUENCY_ATTR_MAX
+ 1];
1052 struct nlattr
*nl_freq
;
1058 nla_for_each_nested(nl_freq
, tb
, rem_freq
) {
1059 nla_parse(tb_freq
, NL80211_FREQUENCY_ATTR_MAX
,
1060 nla_data(nl_freq
), nla_len(nl_freq
), freq_policy
);
1061 if (!tb_freq
[NL80211_FREQUENCY_ATTR_FREQ
])
1066 channel
= os_realloc_array(mode
->channels
,
1067 mode
->num_channels
+ new_channels
,
1068 sizeof(struct hostapd_channel_data
));
1072 mode
->channels
= channel
;
1073 mode
->num_channels
+= new_channels
;
1075 idx
= phy_info
->last_chan_idx
;
1077 nla_for_each_nested(nl_freq
, tb
, rem_freq
) {
1078 nla_parse(tb_freq
, NL80211_FREQUENCY_ATTR_MAX
,
1079 nla_data(nl_freq
), nla_len(nl_freq
), freq_policy
);
1080 if (!tb_freq
[NL80211_FREQUENCY_ATTR_FREQ
])
1082 phy_info_freq(mode
, &mode
->channels
[idx
], tb_freq
);
1085 phy_info
->last_chan_idx
= idx
;
1091 static int phy_info_rates(struct hostapd_hw_modes
*mode
, struct nlattr
*tb
)
1093 static struct nla_policy rate_policy
[NL80211_BITRATE_ATTR_MAX
+ 1] = {
1094 [NL80211_BITRATE_ATTR_RATE
] = { .type
= NLA_U32
},
1095 [NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE
] =
1096 { .type
= NLA_FLAG
},
1098 struct nlattr
*tb_rate
[NL80211_BITRATE_ATTR_MAX
+ 1];
1099 struct nlattr
*nl_rate
;
1105 nla_for_each_nested(nl_rate
, tb
, rem_rate
) {
1106 nla_parse(tb_rate
, NL80211_BITRATE_ATTR_MAX
,
1107 nla_data(nl_rate
), nla_len(nl_rate
),
1109 if (!tb_rate
[NL80211_BITRATE_ATTR_RATE
])
1114 mode
->rates
= os_calloc(mode
->num_rates
, sizeof(int));
1120 nla_for_each_nested(nl_rate
, tb
, rem_rate
) {
1121 nla_parse(tb_rate
, NL80211_BITRATE_ATTR_MAX
,
1122 nla_data(nl_rate
), nla_len(nl_rate
),
1124 if (!tb_rate
[NL80211_BITRATE_ATTR_RATE
])
1126 mode
->rates
[idx
] = nla_get_u32(
1127 tb_rate
[NL80211_BITRATE_ATTR_RATE
]);
1135 static int phy_info_band(struct phy_info_arg
*phy_info
, struct nlattr
*nl_band
)
1137 struct nlattr
*tb_band
[NL80211_BAND_ATTR_MAX
+ 1];
1138 struct hostapd_hw_modes
*mode
;
1141 if (phy_info
->last_mode
!= nl_band
->nla_type
) {
1142 mode
= os_realloc_array(phy_info
->modes
,
1143 *phy_info
->num_modes
+ 1,
1147 phy_info
->modes
= mode
;
1149 mode
= &phy_info
->modes
[*(phy_info
->num_modes
)];
1150 os_memset(mode
, 0, sizeof(*mode
));
1151 mode
->mode
= NUM_HOSTAPD_MODES
;
1152 mode
->flags
= HOSTAPD_MODE_FLAG_HT_INFO_KNOWN
|
1153 HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN
;
1156 * Unsupported VHT MCS stream is defined as value 3, so the VHT
1157 * MCS RX/TX map must be initialized with 0xffff to mark all 8
1158 * possible streams as unsupported. This will be overridden if
1159 * driver advertises VHT support.
1161 mode
->vht_mcs_set
[0] = 0xff;
1162 mode
->vht_mcs_set
[1] = 0xff;
1163 mode
->vht_mcs_set
[4] = 0xff;
1164 mode
->vht_mcs_set
[5] = 0xff;
1166 *(phy_info
->num_modes
) += 1;
1167 phy_info
->last_mode
= nl_band
->nla_type
;
1168 phy_info
->last_chan_idx
= 0;
1170 mode
= &phy_info
->modes
[*(phy_info
->num_modes
) - 1];
1172 nla_parse(tb_band
, NL80211_BAND_ATTR_MAX
, nla_data(nl_band
),
1173 nla_len(nl_band
), NULL
);
1175 phy_info_ht_capa(mode
, tb_band
[NL80211_BAND_ATTR_HT_CAPA
],
1176 tb_band
[NL80211_BAND_ATTR_HT_AMPDU_FACTOR
],
1177 tb_band
[NL80211_BAND_ATTR_HT_AMPDU_DENSITY
],
1178 tb_band
[NL80211_BAND_ATTR_HT_MCS_SET
]);
1179 phy_info_vht_capa(mode
, tb_band
[NL80211_BAND_ATTR_VHT_CAPA
],
1180 tb_band
[NL80211_BAND_ATTR_VHT_MCS_SET
]);
1181 ret
= phy_info_freqs(phy_info
, mode
, tb_band
[NL80211_BAND_ATTR_FREQS
]);
1184 ret
= phy_info_rates(mode
, tb_band
[NL80211_BAND_ATTR_RATES
]);
1192 static int phy_info_handler(struct nl_msg
*msg
, void *arg
)
1194 struct nlattr
*tb_msg
[NL80211_ATTR_MAX
+ 1];
1195 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
1196 struct phy_info_arg
*phy_info
= arg
;
1197 struct nlattr
*nl_band
;
1200 nla_parse(tb_msg
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
1201 genlmsg_attrlen(gnlh
, 0), NULL
);
1203 if (!tb_msg
[NL80211_ATTR_WIPHY_BANDS
])
1206 nla_for_each_nested(nl_band
, tb_msg
[NL80211_ATTR_WIPHY_BANDS
], rem_band
)
1208 int res
= phy_info_band(phy_info
, nl_band
);
1217 static struct hostapd_hw_modes
*
1218 wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes
*modes
,
1222 struct hostapd_hw_modes
*mode11g
= NULL
, *nmodes
, *mode
;
1223 int i
, mode11g_idx
= -1;
1225 /* heuristic to set up modes */
1226 for (m
= 0; m
< *num_modes
; m
++) {
1227 if (!modes
[m
].num_channels
)
1229 if (modes
[m
].channels
[0].freq
< 4000) {
1230 modes
[m
].mode
= HOSTAPD_MODE_IEEE80211B
;
1231 for (i
= 0; i
< modes
[m
].num_rates
; i
++) {
1232 if (modes
[m
].rates
[i
] > 200) {
1233 modes
[m
].mode
= HOSTAPD_MODE_IEEE80211G
;
1237 } else if (modes
[m
].channels
[0].freq
> 50000)
1238 modes
[m
].mode
= HOSTAPD_MODE_IEEE80211AD
;
1240 modes
[m
].mode
= HOSTAPD_MODE_IEEE80211A
;
1243 /* If only 802.11g mode is included, use it to construct matching
1244 * 802.11b mode data. */
1246 for (m
= 0; m
< *num_modes
; m
++) {
1247 if (modes
[m
].mode
== HOSTAPD_MODE_IEEE80211B
)
1248 return modes
; /* 802.11b already included */
1249 if (modes
[m
].mode
== HOSTAPD_MODE_IEEE80211G
)
1253 if (mode11g_idx
< 0)
1254 return modes
; /* 2.4 GHz band not supported at all */
1256 nmodes
= os_realloc_array(modes
, *num_modes
+ 1, sizeof(*nmodes
));
1258 return modes
; /* Could not add 802.11b mode */
1260 mode
= &nmodes
[*num_modes
];
1261 os_memset(mode
, 0, sizeof(*mode
));
1265 mode
->mode
= HOSTAPD_MODE_IEEE80211B
;
1267 mode11g
= &modes
[mode11g_idx
];
1268 mode
->num_channels
= mode11g
->num_channels
;
1269 mode
->channels
= os_malloc(mode11g
->num_channels
*
1270 sizeof(struct hostapd_channel_data
));
1271 if (mode
->channels
== NULL
) {
1273 return modes
; /* Could not add 802.11b mode */
1275 os_memcpy(mode
->channels
, mode11g
->channels
,
1276 mode11g
->num_channels
* sizeof(struct hostapd_channel_data
));
1278 mode
->num_rates
= 0;
1279 mode
->rates
= os_malloc(4 * sizeof(int));
1280 if (mode
->rates
== NULL
) {
1281 os_free(mode
->channels
);
1283 return modes
; /* Could not add 802.11b mode */
1286 for (i
= 0; i
< mode11g
->num_rates
; i
++) {
1287 if (mode11g
->rates
[i
] != 10 && mode11g
->rates
[i
] != 20 &&
1288 mode11g
->rates
[i
] != 55 && mode11g
->rates
[i
] != 110)
1290 mode
->rates
[mode
->num_rates
] = mode11g
->rates
[i
];
1292 if (mode
->num_rates
== 4)
1296 if (mode
->num_rates
== 0) {
1297 os_free(mode
->channels
);
1298 os_free(mode
->rates
);
1300 return modes
; /* No 802.11b rates */
1303 wpa_printf(MSG_DEBUG
, "nl80211: Added 802.11b mode based on 802.11g "
1310 static void nl80211_set_ht40_mode(struct hostapd_hw_modes
*mode
, int start
,
1315 for (c
= 0; c
< mode
->num_channels
; c
++) {
1316 struct hostapd_channel_data
*chan
= &mode
->channels
[c
];
1317 if (chan
->freq
- 10 >= start
&& chan
->freq
+ 10 <= end
)
1318 chan
->flag
|= HOSTAPD_CHAN_HT40
;
1323 static void nl80211_set_ht40_mode_sec(struct hostapd_hw_modes
*mode
, int start
,
1328 for (c
= 0; c
< mode
->num_channels
; c
++) {
1329 struct hostapd_channel_data
*chan
= &mode
->channels
[c
];
1330 if (!(chan
->flag
& HOSTAPD_CHAN_HT40
))
1332 if (chan
->freq
- 30 >= start
&& chan
->freq
- 10 <= end
)
1333 chan
->flag
|= HOSTAPD_CHAN_HT40MINUS
;
1334 if (chan
->freq
+ 10 >= start
&& chan
->freq
+ 30 <= end
)
1335 chan
->flag
|= HOSTAPD_CHAN_HT40PLUS
;
1340 static void nl80211_reg_rule_max_eirp(u32 start
, u32 end
, u32 max_eirp
,
1341 struct phy_info_arg
*results
)
1345 for (m
= 0; m
< *results
->num_modes
; m
++) {
1347 struct hostapd_hw_modes
*mode
= &results
->modes
[m
];
1349 for (c
= 0; c
< mode
->num_channels
; c
++) {
1350 struct hostapd_channel_data
*chan
= &mode
->channels
[c
];
1351 if ((u32
) chan
->freq
- 10 >= start
&&
1352 (u32
) chan
->freq
+ 10 <= end
)
1353 chan
->max_tx_power
= max_eirp
;
1359 static void nl80211_reg_rule_ht40(u32 start
, u32 end
,
1360 struct phy_info_arg
*results
)
1364 for (m
= 0; m
< *results
->num_modes
; m
++) {
1365 if (!(results
->modes
[m
].ht_capab
&
1366 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET
))
1368 nl80211_set_ht40_mode(&results
->modes
[m
], start
, end
);
1373 static void nl80211_reg_rule_sec(struct nlattr
*tb
[],
1374 struct phy_info_arg
*results
)
1376 u32 start
, end
, max_bw
;
1379 if (tb
[NL80211_ATTR_FREQ_RANGE_START
] == NULL
||
1380 tb
[NL80211_ATTR_FREQ_RANGE_END
] == NULL
||
1381 tb
[NL80211_ATTR_FREQ_RANGE_MAX_BW
] == NULL
)
1384 start
= nla_get_u32(tb
[NL80211_ATTR_FREQ_RANGE_START
]) / 1000;
1385 end
= nla_get_u32(tb
[NL80211_ATTR_FREQ_RANGE_END
]) / 1000;
1386 max_bw
= nla_get_u32(tb
[NL80211_ATTR_FREQ_RANGE_MAX_BW
]) / 1000;
1391 for (m
= 0; m
< *results
->num_modes
; m
++) {
1392 if (!(results
->modes
[m
].ht_capab
&
1393 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET
))
1395 nl80211_set_ht40_mode_sec(&results
->modes
[m
], start
, end
);
1400 static void nl80211_set_vht_mode(struct hostapd_hw_modes
*mode
, int start
,
1405 for (c
= 0; c
< mode
->num_channels
; c
++) {
1406 struct hostapd_channel_data
*chan
= &mode
->channels
[c
];
1407 if (chan
->freq
- 10 >= start
&& chan
->freq
+ 70 <= end
)
1408 chan
->flag
|= HOSTAPD_CHAN_VHT_10_70
;
1410 if (chan
->freq
- 30 >= start
&& chan
->freq
+ 50 <= end
)
1411 chan
->flag
|= HOSTAPD_CHAN_VHT_30_50
;
1413 if (chan
->freq
- 50 >= start
&& chan
->freq
+ 30 <= end
)
1414 chan
->flag
|= HOSTAPD_CHAN_VHT_50_30
;
1416 if (chan
->freq
- 70 >= start
&& chan
->freq
+ 10 <= end
)
1417 chan
->flag
|= HOSTAPD_CHAN_VHT_70_10
;
1422 static void nl80211_reg_rule_vht(struct nlattr
*tb
[],
1423 struct phy_info_arg
*results
)
1425 u32 start
, end
, max_bw
;
1428 if (tb
[NL80211_ATTR_FREQ_RANGE_START
] == NULL
||
1429 tb
[NL80211_ATTR_FREQ_RANGE_END
] == NULL
||
1430 tb
[NL80211_ATTR_FREQ_RANGE_MAX_BW
] == NULL
)
1433 start
= nla_get_u32(tb
[NL80211_ATTR_FREQ_RANGE_START
]) / 1000;
1434 end
= nla_get_u32(tb
[NL80211_ATTR_FREQ_RANGE_END
]) / 1000;
1435 max_bw
= nla_get_u32(tb
[NL80211_ATTR_FREQ_RANGE_MAX_BW
]) / 1000;
1440 for (m
= 0; m
< *results
->num_modes
; m
++) {
1441 if (!(results
->modes
[m
].ht_capab
&
1442 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET
))
1444 /* TODO: use a real VHT support indication */
1445 if (!results
->modes
[m
].vht_capab
)
1448 nl80211_set_vht_mode(&results
->modes
[m
], start
, end
);
1453 static const char * dfs_domain_name(enum nl80211_dfs_regions region
)
1456 case NL80211_DFS_UNSET
:
1458 case NL80211_DFS_FCC
:
1460 case NL80211_DFS_ETSI
:
1462 case NL80211_DFS_JP
:
1465 return "DFS-invalid";
1470 static int nl80211_get_reg(struct nl_msg
*msg
, void *arg
)
1472 struct phy_info_arg
*results
= arg
;
1473 struct nlattr
*tb_msg
[NL80211_ATTR_MAX
+ 1];
1474 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
1475 struct nlattr
*nl_rule
;
1476 struct nlattr
*tb_rule
[NL80211_FREQUENCY_ATTR_MAX
+ 1];
1478 static struct nla_policy reg_policy
[NL80211_FREQUENCY_ATTR_MAX
+ 1] = {
1479 [NL80211_ATTR_REG_RULE_FLAGS
] = { .type
= NLA_U32
},
1480 [NL80211_ATTR_FREQ_RANGE_START
] = { .type
= NLA_U32
},
1481 [NL80211_ATTR_FREQ_RANGE_END
] = { .type
= NLA_U32
},
1482 [NL80211_ATTR_FREQ_RANGE_MAX_BW
] = { .type
= NLA_U32
},
1483 [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN
] = { .type
= NLA_U32
},
1484 [NL80211_ATTR_POWER_RULE_MAX_EIRP
] = { .type
= NLA_U32
},
1487 nla_parse(tb_msg
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
1488 genlmsg_attrlen(gnlh
, 0), NULL
);
1489 if (!tb_msg
[NL80211_ATTR_REG_ALPHA2
] ||
1490 !tb_msg
[NL80211_ATTR_REG_RULES
]) {
1491 wpa_printf(MSG_DEBUG
, "nl80211: No regulatory information "
1496 if (tb_msg
[NL80211_ATTR_DFS_REGION
]) {
1497 enum nl80211_dfs_regions dfs_domain
;
1498 dfs_domain
= nla_get_u8(tb_msg
[NL80211_ATTR_DFS_REGION
]);
1499 wpa_printf(MSG_DEBUG
, "nl80211: Regulatory information - country=%s (%s)",
1500 (char *) nla_data(tb_msg
[NL80211_ATTR_REG_ALPHA2
]),
1501 dfs_domain_name(dfs_domain
));
1503 wpa_printf(MSG_DEBUG
, "nl80211: Regulatory information - country=%s",
1504 (char *) nla_data(tb_msg
[NL80211_ATTR_REG_ALPHA2
]));
1507 nla_for_each_nested(nl_rule
, tb_msg
[NL80211_ATTR_REG_RULES
], rem_rule
)
1509 u32 start
, end
, max_eirp
= 0, max_bw
= 0, flags
= 0;
1510 nla_parse(tb_rule
, NL80211_FREQUENCY_ATTR_MAX
,
1511 nla_data(nl_rule
), nla_len(nl_rule
), reg_policy
);
1512 if (tb_rule
[NL80211_ATTR_FREQ_RANGE_START
] == NULL
||
1513 tb_rule
[NL80211_ATTR_FREQ_RANGE_END
] == NULL
)
1515 start
= nla_get_u32(tb_rule
[NL80211_ATTR_FREQ_RANGE_START
]) / 1000;
1516 end
= nla_get_u32(tb_rule
[NL80211_ATTR_FREQ_RANGE_END
]) / 1000;
1517 if (tb_rule
[NL80211_ATTR_POWER_RULE_MAX_EIRP
])
1518 max_eirp
= nla_get_u32(tb_rule
[NL80211_ATTR_POWER_RULE_MAX_EIRP
]) / 100;
1519 if (tb_rule
[NL80211_ATTR_FREQ_RANGE_MAX_BW
])
1520 max_bw
= nla_get_u32(tb_rule
[NL80211_ATTR_FREQ_RANGE_MAX_BW
]) / 1000;
1521 if (tb_rule
[NL80211_ATTR_REG_RULE_FLAGS
])
1522 flags
= nla_get_u32(tb_rule
[NL80211_ATTR_REG_RULE_FLAGS
]);
1524 wpa_printf(MSG_DEBUG
, "nl80211: %u-%u @ %u MHz %u mBm%s%s%s%s%s%s%s%s",
1525 start
, end
, max_bw
, max_eirp
,
1526 flags
& NL80211_RRF_NO_OFDM
? " (no OFDM)" : "",
1527 flags
& NL80211_RRF_NO_CCK
? " (no CCK)" : "",
1528 flags
& NL80211_RRF_NO_INDOOR
? " (no indoor)" : "",
1529 flags
& NL80211_RRF_NO_OUTDOOR
? " (no outdoor)" :
1531 flags
& NL80211_RRF_DFS
? " (DFS)" : "",
1532 flags
& NL80211_RRF_PTP_ONLY
? " (PTP only)" : "",
1533 flags
& NL80211_RRF_PTMP_ONLY
? " (PTMP only)" : "",
1534 flags
& NL80211_RRF_NO_IR
? " (no IR)" : "");
1536 nl80211_reg_rule_ht40(start
, end
, results
);
1537 if (tb_rule
[NL80211_ATTR_POWER_RULE_MAX_EIRP
])
1538 nl80211_reg_rule_max_eirp(start
, end
, max_eirp
,
1542 nla_for_each_nested(nl_rule
, tb_msg
[NL80211_ATTR_REG_RULES
], rem_rule
)
1544 nla_parse(tb_rule
, NL80211_FREQUENCY_ATTR_MAX
,
1545 nla_data(nl_rule
), nla_len(nl_rule
), reg_policy
);
1546 nl80211_reg_rule_sec(tb_rule
, results
);
1549 nla_for_each_nested(nl_rule
, tb_msg
[NL80211_ATTR_REG_RULES
], rem_rule
)
1551 nla_parse(tb_rule
, NL80211_FREQUENCY_ATTR_MAX
,
1552 nla_data(nl_rule
), nla_len(nl_rule
), reg_policy
);
1553 nl80211_reg_rule_vht(tb_rule
, results
);
1560 static int nl80211_set_regulatory_flags(struct wpa_driver_nl80211_data
*drv
,
1561 struct phy_info_arg
*results
)
1565 msg
= nlmsg_alloc();
1569 nl80211_cmd(drv
, msg
, 0, NL80211_CMD_GET_REG
);
1570 return send_and_recv_msgs(drv
, msg
, nl80211_get_reg
, results
);
1574 struct hostapd_hw_modes
*
1575 nl80211_get_hw_feature_data(void *priv
, u16
*num_modes
, u16
*flags
)
1578 struct i802_bss
*bss
= priv
;
1579 struct wpa_driver_nl80211_data
*drv
= bss
->drv
;
1582 struct phy_info_arg result
= {
1583 .num_modes
= num_modes
,
1591 feat
= get_nl80211_protocol_features(drv
);
1592 if (feat
& NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP
)
1593 nl_flags
= NLM_F_DUMP
;
1594 if (!(msg
= nl80211_cmd_msg(bss
, nl_flags
, NL80211_CMD_GET_WIPHY
)) ||
1595 nla_put_flag(msg
, NL80211_ATTR_SPLIT_WIPHY_DUMP
)) {
1600 if (send_and_recv_msgs(drv
, msg
, phy_info_handler
, &result
) == 0) {
1601 nl80211_set_regulatory_flags(drv
, &result
);
1602 return wpa_driver_nl80211_postprocess_modes(result
.modes
,