diff options
Diffstat (limited to 'src/drivers')
| -rw-r--r-- | src/drivers/driver.h | 152 | ||||
| -rw-r--r-- | src/drivers/driver_atheros.c | 6 | ||||
| -rw-r--r-- | src/drivers/driver_bsd.c | 8 | ||||
| -rw-r--r-- | src/drivers/driver_common.c | 2 | ||||
| -rw-r--r-- | src/drivers/driver_hostap.c | 4 | ||||
| -rw-r--r-- | src/drivers/driver_macsec_linux.c | 214 | ||||
| -rw-r--r-- | src/drivers/driver_macsec_qca.c | 225 | ||||
| -rw-r--r-- | src/drivers/driver_ndis.c | 2 | ||||
| -rw-r--r-- | src/drivers/driver_nl80211.c | 246 | ||||
| -rw-r--r-- | src/drivers/driver_nl80211.h | 16 | ||||
| -rw-r--r-- | src/drivers/driver_nl80211_capa.c | 257 | ||||
| -rw-r--r-- | src/drivers/driver_nl80211_event.c | 57 | ||||
| -rw-r--r-- | src/drivers/driver_privsep.c | 2 | ||||
| -rw-r--r-- | src/drivers/driver_wext.c | 4 | ||||
| -rw-r--r-- | src/drivers/nl80211_copy.h | 86 |
15 files changed, 1071 insertions, 210 deletions
diff --git a/src/drivers/driver.h b/src/drivers/driver.h index e7c8f318f35d..2a8459ae3f2d 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -102,6 +102,20 @@ enum reg_type { }; /** + * struct hostapd_wmm_rule - WMM regulatory rule + * @min_cwmin: Lower bound of CW_min value + * @min_cwmax: Lower bound of CW_max value + * @min_aifs: Lower bound of AIFS value + * @max_txop: Upper bound of TXOP, value in units of 32 usec + */ +struct hostapd_wmm_rule { + int min_cwmin; + int min_cwmax; + int min_aifs; + int max_txop; +}; + +/** * struct hostapd_channel_data - Channel information */ struct hostapd_channel_data { @@ -156,34 +170,48 @@ struct hostapd_channel_data { * dfs_cac_ms - DFS CAC time in milliseconds */ unsigned int dfs_cac_ms; -}; -#define HE_MAX_NUM_SS 8 -#define HE_MAX_PHY_CAPAB_SIZE 3 + /** + * wmm_rules_valid - Indicates wmm_rules state + */ + int wmm_rules_valid; -/** - * struct he_ppe_threshold - IEEE 802.11ax HE PPE Threshold - */ -struct he_ppe_threshold { - u32 numss_m1; - u32 ru_count; - u32 ppet16_ppet8_ru3_ru0[HE_MAX_NUM_SS]; + /** + * wmm_rules - WMM regulatory rules + */ + struct hostapd_wmm_rule wmm_rules[WMM_AC_NUM]; }; +#define HE_MAX_MAC_CAPAB_SIZE 6 +#define HE_MAX_PHY_CAPAB_SIZE 11 +#define HE_MAX_MCS_CAPAB_SIZE 12 +#define HE_MAX_PPET_CAPAB_SIZE 25 + /** * struct he_capabilities - IEEE 802.11ax HE capabilities */ struct he_capabilities { u8 he_supported; - u32 phy_cap[HE_MAX_PHY_CAPAB_SIZE]; - u32 mac_cap; - u32 mcs; - struct he_ppe_threshold ppet; + u8 phy_cap[HE_MAX_PHY_CAPAB_SIZE]; + u8 mac_cap[HE_MAX_MAC_CAPAB_SIZE]; + u8 mcs[HE_MAX_MCS_CAPAB_SIZE]; + u8 ppet[HE_MAX_PPET_CAPAB_SIZE]; }; #define HOSTAPD_MODE_FLAG_HT_INFO_KNOWN BIT(0) #define HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN BIT(1) + +enum ieee80211_op_mode { + IEEE80211_MODE_INFRA = 0, + IEEE80211_MODE_IBSS = 1, + IEEE80211_MODE_AP = 2, + IEEE80211_MODE_MESH = 5, + + /* only add new entries before IEEE80211_MODE_NUM */ + IEEE80211_MODE_NUM +}; + /** * struct hostapd_hw_modes - Supported hardware mode information */ @@ -243,15 +271,10 @@ struct hostapd_hw_modes { /** * he_capab - HE (IEEE 802.11ax) capabilities */ - struct he_capabilities he_capab; + struct he_capabilities he_capab[IEEE80211_MODE_NUM]; }; -#define IEEE80211_MODE_INFRA 0 -#define IEEE80211_MODE_IBSS 1 -#define IEEE80211_MODE_AP 2 -#define IEEE80211_MODE_MESH 5 - #define IEEE80211_CAP_ESS 0x0001 #define IEEE80211_CAP_IBSS 0x0002 #define IEEE80211_CAP_PRIVACY 0x0010 @@ -699,6 +722,11 @@ struct hostapd_freq_params { int vht_enabled; /** + * he_enabled - Whether HE is enabled + */ + int he_enabled; + + /** * center_freq1 - Segment 0 center frequency in MHz * * Valid for both HT and VHT. @@ -1046,6 +1074,14 @@ struct wpa_driver_associate_params { int req_key_mgmt_offload; /** + * req_handshake_offload - Request EAPOL handshake offload + * + * Request EAPOL handshake offload for this connection if the device + * supports it. + */ + int req_handshake_offload; + + /** * Flag for indicating whether this association includes support for * RRM (Radio Resource Measurements) */ @@ -1122,6 +1158,11 @@ enum hide_ssid { HIDDEN_SSID_ZERO_CONTENTS }; +enum ch_switch_state { + CH_SW_STARTED, + CH_SW_FINISHED +}; + struct wowlan_triggers { u8 any; u8 disconnect; @@ -1752,6 +1793,7 @@ struct hostapd_data; struct hostap_sta_driver_data { unsigned long rx_packets, tx_packets; unsigned long long rx_bytes, tx_bytes; + unsigned long long rx_airtime, tx_airtime; int bytes_64bit; /* whether 64-bit byte counters are supported */ unsigned long current_tx_rate; unsigned long current_rx_rate; @@ -1761,6 +1803,8 @@ struct hostap_sta_driver_data { unsigned long tx_retry_failed; unsigned long tx_retry_count; s8 last_ack_rssi; + unsigned long backlog_packets; + unsigned long backlog_bytes; s8 signal; u8 rx_vhtmcs; u8 tx_vhtmcs; @@ -1781,6 +1825,8 @@ struct hostapd_sta_add_params { const struct ieee80211_vht_capabilities *vht_capabilities; int vht_opmode_enabled; u8 vht_opmode; + const struct ieee80211_he_capabilities *he_capab; + size_t he_capab_len; u32 flags; /* bitmask of WPA_STA_* flags */ u32 flags_mask; /* unset bits in flags */ #ifdef CONFIG_MESH @@ -2337,7 +2383,7 @@ struct wpa_driver_ops { * * Returns: 0 on success, -1 on failure */ - int (*deauthenticate)(void *priv, const u8 *addr, int reason_code); + int (*deauthenticate)(void *priv, const u8 *addr, u16 reason_code); /** * associate - Request driver to associate @@ -2806,7 +2852,7 @@ struct wpa_driver_ops { * a Deauthentication frame to be sent to it. */ int (*sta_deauth)(void *priv, const u8 *own_addr, const u8 *addr, - int reason); + u16 reason); /** * sta_disassoc - Disassociate a station (AP only) @@ -2820,7 +2866,7 @@ struct wpa_driver_ops { * a Disassociation frame to be sent to it. */ int (*sta_disassoc)(void *priv, const u8 *own_addr, const u8 *addr, - int reason); + u16 reason); /** * sta_remove - Remove a station entry (AP only) @@ -2938,6 +2984,16 @@ struct wpa_driver_ops { unsigned int flags_and); /** + * sta_set_airtime_weight - Set station airtime weight (AP only) + * @priv: Private driver interface data + * @addr: Station address + * @weight: New weight for station airtime assignment + * Returns: 0 on success, -1 on failure + */ + int (*sta_set_airtime_weight)(void *priv, const u8 *addr, + unsigned int weight); + + /** * set_tx_queue_params - Set TX queue parameters * @priv: Private driver interface data * @queue: Queue number (0 = VO, 1 = VI, 2 = BE, 3 = BK) @@ -3975,6 +4031,18 @@ struct wpa_driver_ops { int (*leave_mesh)(void *priv); /** + * probe_mesh_link - Inject a frame over direct mesh link to a given + * peer skipping the next_hop lookup from mpath table. + * @priv: Private driver interface data + * @addr: Peer MAC address + * @eth: Ethernet frame to be sent + * @len: Ethernet frame lengtn in bytes + * Returns 0 on success, -1 on failure + */ + int (*probe_mesh_link)(void *priv, const u8 *addr, const u8 *eth, + size_t len); + + /** * do_acs - Automatically select channel * @priv: Private driver interface data * @params: Parameters for ACS @@ -4167,6 +4235,21 @@ struct wpa_driver_ops { * Returns: 0 on success, < 0 on failure */ int (*set_4addr_mode)(void *priv, const char *bridge_ifname, int val); + + /** + * update_dh_ie - Update DH IE + * @priv: Private driver interface data + * @peer_mac: Peer MAC address + * @reason_code: Reacon code + * @ie: DH IE + * @ie_len: DH IE length in bytes + * Returns: 0 on success, -1 on failure + * + * This callback is used to let the driver know the DH processing result + * and DH IE for a pending association. + */ + int (*update_dh_ie)(void *priv, const u8 *peer_mac, u16 reason_code, + const u8 *ie, size_t ie_len); }; /** @@ -4541,6 +4624,15 @@ enum wpa_event_type { EVENT_CH_SWITCH, /** + * EVENT_CH_SWITCH_STARTED - AP or GO started to switch channels + * + * This is a pre-switch event indicating the shortly following switch + * of operating channels. + * + * Described in wpa_event_data.ch_switch + */ + EVENT_CH_SWITCH_STARTED, + /** * EVENT_WNM - Request WNM operation * * This event can be used to request a WNM operation to be performed. @@ -4703,6 +4795,11 @@ enum wpa_event_type { * This event is emitted when an interface is added/removed for WDS STA. */ EVENT_WDS_STA_INTERFACE_STATUS, + + /** + * EVENT_UPDATE_DH - Notification of updated DH information + */ + EVENT_UPDATE_DH, }; @@ -5536,6 +5633,15 @@ union wpa_event_data { INTERFACE_REMOVED } istatus; } wds_sta_interface; + + /** + * struct update_dh - Data for EVENT_UPDATE_DH + */ + struct update_dh { + const u8 *peer; + const u8 *ie; + size_t ie_len; + } update_dh; }; /** diff --git a/src/drivers/driver_atheros.c b/src/drivers/driver_atheros.c index 807cd94691d0..840d4ff4057e 100644 --- a/src/drivers/driver_atheros.c +++ b/src/drivers/driver_atheros.c @@ -86,7 +86,7 @@ struct atheros_driver_data { }; static int atheros_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, - int reason_code); + u16 reason_code); static int atheros_set_privacy(void *priv, int enabled); static const char * athr_get_ioctl_name(int op) @@ -761,7 +761,7 @@ atheros_set_opt_ie(void *priv, const u8 *ie, size_t ie_len) static int atheros_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, - int reason_code) + u16 reason_code) { struct atheros_driver_data *drv = priv; struct ieee80211req_mlme mlme; @@ -785,7 +785,7 @@ atheros_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, static int atheros_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, - int reason_code) + u16 reason_code) { struct atheros_driver_data *drv = priv; struct ieee80211req_mlme mlme; diff --git a/src/drivers/driver_bsd.c b/src/drivers/driver_bsd.c index 46754968f13d..82ca0612eefa 100644 --- a/src/drivers/driver_bsd.c +++ b/src/drivers/driver_bsd.c @@ -663,7 +663,7 @@ rtbuf_len(void) #undef WPA_OUI_TYPE static int bsd_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, - int reason_code); + u16 reason_code); static const char * ether_sprintf(const u8 *addr) @@ -755,7 +755,7 @@ bsd_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data, } static int -bsd_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, int reason_code) +bsd_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, u16 reason_code) { return bsd_send_mlme_param(priv, IEEE80211_MLME_DEAUTH, reason_code, addr); @@ -763,7 +763,7 @@ bsd_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, int reason_code) static int bsd_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, - int reason_code) + u16 reason_code) { return bsd_send_mlme_param(priv, IEEE80211_MLME_DISASSOC, reason_code, addr); @@ -1026,7 +1026,7 @@ wpa_driver_bsd_set_drop_unencrypted(void *priv, int enabled) } static int -wpa_driver_bsd_deauthenticate(void *priv, const u8 *addr, int reason_code) +wpa_driver_bsd_deauthenticate(void *priv, const u8 *addr, u16 reason_code) { return bsd_send_mlme_param(priv, IEEE80211_MLME_DEAUTH, reason_code, addr); diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c index e55e6cd2b795..731c6a3b16bd 100644 --- a/src/drivers/driver_common.c +++ b/src/drivers/driver_common.c @@ -67,6 +67,7 @@ const char * event_to_string(enum wpa_event_type event) E2S(DRIVER_CLIENT_POLL_OK); E2S(EAPOL_TX_STATUS); E2S(CH_SWITCH); + E2S(CH_SWITCH_STARTED); E2S(WNM); E2S(CONNECT_FAILED_REASON); E2S(DFS_RADAR_DETECTED); @@ -87,6 +88,7 @@ const char * event_to_string(enum wpa_event_type event) E2S(STATION_OPMODE_CHANGED); E2S(INTERFACE_MAC_CHANGED); E2S(WDS_STA_INTERFACE_STATUS); + E2S(UPDATE_DH); } return "UNKNOWN"; diff --git a/src/drivers/driver_hostap.c b/src/drivers/driver_hostap.c index 61b39b19721c..186eccbf2181 100644 --- a/src/drivers/driver_hostap.c +++ b/src/drivers/driver_hostap.c @@ -1028,7 +1028,7 @@ static void hostap_driver_deinit(void *priv) static int hostap_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, - int reason) + u16 reason) { struct hostap_driver_data *drv = priv; struct ieee80211_mgmt mgmt; @@ -1076,7 +1076,7 @@ static int hostap_set_freq(void *priv, struct hostapd_freq_params *freq) static int hostap_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, - int reason) + u16 reason) { struct hostap_driver_data *drv = priv; struct ieee80211_mgmt mgmt; diff --git a/src/drivers/driver_macsec_linux.c b/src/drivers/driver_macsec_linux.c index 9d981bb70f78..e922503fccd0 100644 --- a/src/drivers/driver_macsec_linux.c +++ b/src/drivers/driver_macsec_linux.c @@ -1,6 +1,7 @@ /* * Driver interaction with Linux MACsec kernel module * Copyright (c) 2016, Sabrina Dubroca <sd@queasysnail.net> and Red Hat, Inc. + * Copyright (c) 2019, The Linux Foundation * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -22,6 +23,7 @@ #include "utils/common.h" #include "utils/eloop.h" +#include "common/eapol_common.h" #include "pae/ieee802_1x_kay.h" #include "driver.h" #include "driver_wired_common.h" @@ -57,6 +59,7 @@ struct macsec_drv_data { char ifname[IFNAMSIZ + 1]; int ifi; int parent_ifi; + int use_pae_group_addr; Boolean created_link; @@ -1399,6 +1402,214 @@ static int macsec_drv_status(void *priv, char *buf, size_t buflen) } +#ifdef __linux__ + +static void macsec_drv_handle_data(void *ctx, unsigned char *buf, size_t len) +{ +#ifdef HOSTAPD + struct ieee8023_hdr *hdr; + u8 *pos, *sa; + size_t left; + union wpa_event_data event; + + /* must contain at least ieee8023_hdr 6 byte source, 6 byte dest, + * 2 byte ethertype */ + if (len < 14) { + wpa_printf(MSG_MSGDUMP, "%s: too short (%lu)", + __func__, (unsigned long) len); + return; + } + + hdr = (struct ieee8023_hdr *) buf; + + switch (ntohs(hdr->ethertype)) { + case ETH_P_PAE: + wpa_printf(MSG_MSGDUMP, "Received EAPOL packet"); + sa = hdr->src; + os_memset(&event, 0, sizeof(event)); + event.new_sta.addr = sa; + wpa_supplicant_event(ctx, EVENT_NEW_STA, &event); + + pos = (u8 *) (hdr + 1); + left = len - sizeof(*hdr); + drv_event_eapol_rx(ctx, sa, pos, left); + break; + + default: + wpa_printf(MSG_DEBUG, "Unknown ethertype 0x%04x in data frame", + ntohs(hdr->ethertype)); + break; + } +#endif /* HOSTAPD */ +} + + +static void macsec_drv_handle_read(int sock, void *eloop_ctx, void *sock_ctx) +{ + int len; + unsigned char buf[3000]; + + len = recv(sock, buf, sizeof(buf), 0); + if (len < 0) { + wpa_printf(MSG_ERROR, "macsec_linux: recv: %s", + strerror(errno)); + return; + } + + macsec_drv_handle_data(eloop_ctx, buf, len); +} + +#endif /* __linux__ */ + + +static int macsec_drv_init_sockets(struct macsec_drv_data *drv, u8 *own_addr) +{ +#ifdef __linux__ + struct ifreq ifr; + struct sockaddr_ll addr; + + drv->common.sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE)); + if (drv->common.sock < 0) { + wpa_printf(MSG_ERROR, "socket[PF_PACKET,SOCK_RAW]: %s", + strerror(errno)); + return -1; + } + + if (eloop_register_read_sock(drv->common.sock, macsec_drv_handle_read, + drv->common.ctx, NULL)) { + wpa_printf(MSG_INFO, "Could not register read socket"); + return -1; + } + + os_memset(&ifr, 0, sizeof(ifr)); + os_strlcpy(ifr.ifr_name, drv->common.ifname, sizeof(ifr.ifr_name)); + if (ioctl(drv->common.sock, SIOCGIFINDEX, &ifr) != 0) { + wpa_printf(MSG_ERROR, "ioctl(SIOCGIFINDEX): %s", + strerror(errno)); + return -1; + } + + os_memset(&addr, 0, sizeof(addr)); + addr.sll_family = AF_PACKET; + addr.sll_ifindex = ifr.ifr_ifindex; + wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d", + addr.sll_ifindex); + + if (bind(drv->common.sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) + { + wpa_printf(MSG_ERROR, "bind: %s", strerror(errno)); + return -1; + } + + /* filter multicast address */ + if (wired_multicast_membership(drv->common.sock, ifr.ifr_ifindex, + pae_group_addr, 1) < 0) { + wpa_printf(MSG_ERROR, "wired: Failed to add multicast group " + "membership"); + return -1; + } + + os_memset(&ifr, 0, sizeof(ifr)); + os_strlcpy(ifr.ifr_name, drv->common.ifname, sizeof(ifr.ifr_name)); + if (ioctl(drv->common.sock, SIOCGIFHWADDR, &ifr) != 0) { + wpa_printf(MSG_ERROR, "ioctl(SIOCGIFHWADDR): %s", + strerror(errno)); + return -1; + } + + if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { + wpa_printf(MSG_INFO, "Invalid HW-addr family 0x%04x", + ifr.ifr_hwaddr.sa_family); + return -1; + } + os_memcpy(own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); + + return 0; +#else /* __linux__ */ + return -1; +#endif /* __linux__ */ +} + + +static void * macsec_drv_hapd_init(struct hostapd_data *hapd, + struct wpa_init_params *params) +{ + struct macsec_drv_data *drv; + + drv = os_zalloc(sizeof(struct macsec_drv_data)); + if (drv == NULL) { + wpa_printf(MSG_INFO, + "Could not allocate memory for wired driver data"); + return NULL; + } + + drv->common.ctx = hapd; + os_strlcpy(drv->common.ifname, params->ifname, + sizeof(drv->common.ifname)); + drv->use_pae_group_addr = params->use_pae_group_addr; + + if (macsec_drv_init_sockets(drv, params->own_addr)) { + os_free(drv); + return NULL; + } + + return drv; +} + + +static void macsec_drv_hapd_deinit(void *priv) +{ + struct macsec_drv_data *drv = priv; + + if (drv->common.sock >= 0) { + eloop_unregister_read_sock(drv->common.sock); + close(drv->common.sock); + } + + os_free(drv); +} + + +static int macsec_drv_send_eapol(void *priv, const u8 *addr, + const u8 *data, size_t data_len, int encrypt, + const u8 *own_addr, u32 flags) +{ + struct macsec_drv_data *drv = priv; + struct ieee8023_hdr *hdr; + size_t len; + u8 *pos; + int res; + + len = sizeof(*hdr) + data_len; + hdr = os_zalloc(len); + if (hdr == NULL) { + wpa_printf(MSG_INFO, + "%s: malloc() failed (len=%lu)", + __func__, (unsigned long) len); + return -1; + } + + os_memcpy(hdr->dest, drv->use_pae_group_addr ? pae_group_addr : addr, + ETH_ALEN); + os_memcpy(hdr->src, own_addr, ETH_ALEN); + hdr->ethertype = htons(ETH_P_PAE); + + pos = (u8 *) (hdr + 1); + os_memcpy(pos, data, data_len); + + res = send(drv->common.sock, (u8 *) hdr, len, 0); + os_free(hdr); + + if (res < 0) { + wpa_printf(MSG_ERROR, + "%s: packet len: %lu - failed: send: %s", + __func__, (unsigned long) len, strerror(errno)); + } + + return res; +} + + const struct wpa_driver_ops wpa_driver_macsec_linux_ops = { .name = "macsec_linux", .desc = "MACsec Ethernet driver for Linux", @@ -1407,6 +1618,9 @@ const struct wpa_driver_ops wpa_driver_macsec_linux_ops = { .get_capa = driver_wired_get_capa, .init = macsec_drv_wpa_init, .deinit = macsec_drv_wpa_deinit, + .hapd_init = macsec_drv_hapd_init, + .hapd_deinit = macsec_drv_hapd_deinit, + .hapd_send_eapol = macsec_drv_send_eapol, .macsec_init = macsec_drv_macsec_init, .macsec_deinit = macsec_drv_macsec_deinit, diff --git a/src/drivers/driver_macsec_qca.c b/src/drivers/driver_macsec_qca.c index 8372393f26c2..f4e55d5d99a1 100644 --- a/src/drivers/driver_macsec_qca.c +++ b/src/drivers/driver_macsec_qca.c @@ -3,6 +3,7 @@ * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi> * Copyright (c) 2004, Gunter Burchardt <tira@isx.de> * Copyright (c) 2013-2014, Qualcomm Atheros, Inc. + * Copyright (c) 2019, The Linux Foundation * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -29,6 +30,7 @@ #include "utils/eloop.h" #include "common/defs.h" #include "common/ieee802_1x_defs.h" +#include "common/eapol_common.h" #include "pae/ieee802_1x_kay.h" #include "driver.h" #include "driver_wired_common.h" @@ -64,6 +66,7 @@ struct channel_map { struct macsec_qca_data { struct driver_wired_common_data common; + int use_pae_group_addr; u32 secy_id; /* shadow */ @@ -126,6 +129,134 @@ static void __macsec_drv_deinit(struct macsec_qca_data *drv) } +#ifdef __linux__ + +static void macsec_qca_handle_data(void *ctx, unsigned char *buf, size_t len) +{ +#ifdef HOSTAPD + struct ieee8023_hdr *hdr; + u8 *pos, *sa; + size_t left; + union wpa_event_data event; + + /* at least 6 bytes src macaddress, 6 bytes dst macaddress + * and 2 bytes ethertype + */ + if (len < 14) { + wpa_printf(MSG_MSGDUMP, + "macsec_qca_handle_data: too short (%lu)", + (unsigned long) len); + return; + } + hdr = (struct ieee8023_hdr *) buf; + + switch (ntohs(hdr->ethertype)) { + case ETH_P_PAE: + wpa_printf(MSG_MSGDUMP, "Received EAPOL packet"); + sa = hdr->src; + os_memset(&event, 0, sizeof(event)); + event.new_sta.addr = sa; + wpa_supplicant_event(ctx, EVENT_NEW_STA, &event); + + pos = (u8 *) (hdr + 1); + left = len - sizeof(*hdr); + drv_event_eapol_rx(ctx, sa, pos, left); + break; + default: + wpa_printf(MSG_DEBUG, "Unknown ethertype 0x%04x in data frame", + ntohs(hdr->ethertype)); + break; + } +#endif /* HOSTAPD */ +} + + +static void macsec_qca_handle_read(int sock, void *eloop_ctx, void *sock_ctx) +{ + int len; + unsigned char buf[3000]; + + len = recv(sock, buf, sizeof(buf), 0); + if (len < 0) { + wpa_printf(MSG_ERROR, "macsec_qca: recv: %s", strerror(errno)); + return; + } + + macsec_qca_handle_data(eloop_ctx, buf, len); +} + +#endif /* __linux__ */ + + +static int macsec_qca_init_sockets(struct macsec_qca_data *drv, u8 *own_addr) +{ +#ifdef __linux__ + struct ifreq ifr; + struct sockaddr_ll addr; + + drv->common.sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE)); + if (drv->common.sock < 0) { + wpa_printf(MSG_ERROR, "socket[PF_PACKET,SOCK_RAW]: %s", + strerror(errno)); + return -1; + } + + if (eloop_register_read_sock(drv->common.sock, macsec_qca_handle_read, + drv->common.ctx, NULL)) { + wpa_printf(MSG_INFO, "Could not register read socket"); + return -1; + } + + os_memset(&ifr, 0, sizeof(ifr)); + os_strlcpy(ifr.ifr_name, drv->common.ifname, sizeof(ifr.ifr_name)); + if (ioctl(drv->common.sock, SIOCGIFINDEX, &ifr) != 0) { + wpa_printf(MSG_ERROR, "ioctl(SIOCGIFINDEX): %s", + strerror(errno)); + return -1; + } + + os_memset(&addr, 0, sizeof(addr)); + addr.sll_family = AF_PACKET; + addr.sll_ifindex = ifr.ifr_ifindex; + wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d", + addr.sll_ifindex); + + if (bind(drv->common.sock, (struct sockaddr *) &addr, + sizeof(addr)) < 0) { + wpa_printf(MSG_ERROR, "macsec_qca: bind: %s", strerror(errno)); + return -1; + } + + /* filter multicast address */ + if (wired_multicast_membership(drv->common.sock, ifr.ifr_ifindex, + pae_group_addr, 1) < 0) { + wpa_printf(MSG_ERROR, + "macsec_qca_init_sockets: Failed to add multicast group membership"); + return -1; + } + + os_memset(&ifr, 0, sizeof(ifr)); + os_strlcpy(ifr.ifr_name, drv->common.ifname, sizeof(ifr.ifr_name)); + if (ioctl(drv->common.sock, SIOCGIFHWADDR, &ifr) != 0) { + wpa_printf(MSG_ERROR, "ioctl(SIOCGIFHWADDR): %s", + strerror(errno)); + return -1; + } + + if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { + wpa_printf(MSG_INFO, "Invalid HW-addr family 0x%04x", + ifr.ifr_hwaddr.sa_family); + return -1; + } + os_memcpy(own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); + + return 0; +#else /* __linux__ */ + return -1; +#endif /* __linux__ */ +} + + static void * macsec_qca_init(void *ctx, const char *ifname) { struct macsec_qca_data *drv; @@ -160,6 +291,97 @@ static void macsec_qca_deinit(void *priv) } +static void * macsec_qca_hapd_init(struct hostapd_data *hapd, + struct wpa_init_params *params) +{ + struct macsec_qca_data *drv; + + drv = os_zalloc(sizeof(struct macsec_qca_data)); + if (!drv) { + wpa_printf(MSG_INFO, + "Could not allocate memory for macsec_qca driver data"); + return NULL; + } + + /* Board specific settings */ + if (os_memcmp("eth2", params->ifname, 4) == 0) + drv->secy_id = 1; + else if (os_memcmp("eth3", params->ifname, 4) == 0) + drv->secy_id = 2; + else if (os_memcmp("eth4", params->ifname, 4) == 0) + drv->secy_id = 0; + else if (os_memcmp("eth5", params->ifname, 4) == 0) + drv->secy_id = 1; + else + drv->secy_id = -1; + + drv->common.ctx = hapd; + os_strlcpy(drv->common.ifname, params->ifname, + sizeof(drv->common.ifname)); + drv->use_pae_group_addr = params->use_pae_group_addr; + + if (macsec_qca_init_sockets(drv, params->own_addr)) { + os_free(drv); + return NULL; + } + + return drv; +} + + +static void macsec_qca_hapd_deinit(void *priv) +{ + struct macsec_qca_data *drv = priv; + + if (drv->common.sock >= 0) { + eloop_unregister_read_sock(drv->common.sock); + close(drv->common.sock); + } + + os_free(drv); +} + + +static int macsec_qca_send_eapol(void *priv, const u8 *addr, + const u8 *data, size_t data_len, int encrypt, + const u8 *own_addr, u32 flags) +{ + struct macsec_qca_data *drv = priv; + struct ieee8023_hdr *hdr; + size_t len; + u8 *pos; + int res; + + len = sizeof(*hdr) + data_len; + hdr = os_zalloc(len); + if (!hdr) { + wpa_printf(MSG_INFO, + "malloc() failed for macsec_qca_send_eapol(len=%lu)", + (unsigned long) len); + return -1; + } + + os_memcpy(hdr->dest, drv->use_pae_group_addr ? pae_group_addr : addr, + ETH_ALEN); + os_memcpy(hdr->src, own_addr, ETH_ALEN); + hdr->ethertype = htons(ETH_P_PAE); + + pos = (u8 *) (hdr + 1); + os_memcpy(pos, data, data_len); + + res = send(drv->common.sock, (u8 *) hdr, len, 0); + os_free(hdr); + + if (res < 0) { + wpa_printf(MSG_ERROR, + "macsec_qca_send_eapol - packet len: %lu - failed: send: %s", + (unsigned long) len, strerror(errno)); + } + + return res; +} + + static int macsec_qca_macsec_init(void *priv, struct macsec_init_params *params) { struct macsec_qca_data *drv = priv; @@ -800,6 +1022,9 @@ const struct wpa_driver_ops wpa_driver_macsec_qca_ops = { .get_capa = driver_wired_get_capa, .init = macsec_qca_init, .deinit = macsec_qca_deinit, + .hapd_init = macsec_qca_hapd_init, + .hapd_deinit = macsec_qca_hapd_deinit, + .hapd_send_eapol = macsec_qca_send_eapol, .macsec_init = macsec_qca_macsec_init, .macsec_deinit = macsec_qca_macsec_deinit, diff --git a/src/drivers/driver_ndis.c b/src/drivers/driver_ndis.c index 614c4521e6ff..5b4b9247ecd1 100644 --- a/src/drivers/driver_ndis.c +++ b/src/drivers/driver_ndis.c @@ -719,7 +719,7 @@ static int wpa_driver_ndis_disconnect(struct wpa_driver_ndis_data *drv) static int wpa_driver_ndis_deauthenticate(void *priv, const u8 *addr, - int reason_code) + u16 reason_code) { struct wpa_driver_ndis_data *drv = priv; return wpa_driver_ndis_disconnect(drv); diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 54fe3900096a..0a356eefd588 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -236,7 +236,7 @@ static int nl80211_put_mesh_config(struct nl_msg *msg, struct wpa_driver_mesh_bss_params *params); #endif /* CONFIG_MESH */ static int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, - int reason); + u16 reason); /* Converts nl80211_chan_width to a common format */ @@ -2010,9 +2010,8 @@ static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname, */ drv->set_rekey_offload = 1; - drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int); + drv->num_if_indices = ARRAY_SIZE(drv->default_if_indices); drv->if_indices = drv->default_if_indices; - drv->if_indices_reason = drv->default_if_indices_reason; drv->first_bss = os_zalloc(sizeof(*drv->first_bss)); if (!drv->first_bss) { @@ -2789,9 +2788,6 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss) if (drv->if_indices != drv->default_if_indices) os_free(drv->if_indices); - if (drv->if_indices_reason != drv->default_if_indices_reason) - os_free(drv->if_indices_reason); - if (drv->disabled_11b_rates) nl80211_disable_11b_rates(drv, drv->ifindex, 0); @@ -3282,7 +3278,7 @@ int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv, static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv, - int reason_code, + u16 reason_code, struct nl_handle *nl_connect) { int ret; @@ -3304,7 +3300,7 @@ static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv, static int wpa_driver_nl80211_deauthenticate(struct i802_bss *bss, - const u8 *addr, int reason_code) + const u8 *addr, u16 reason_code) { struct wpa_driver_nl80211_data *drv = bss->drv; int ret; @@ -4352,10 +4348,11 @@ static int nl80211_put_freq_params(struct nl_msg *msg, if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq)) return -ENOBUFS; + wpa_printf(MSG_DEBUG, " * he_enabled=%d", freq->he_enabled); wpa_printf(MSG_DEBUG, " * vht_enabled=%d", freq->vht_enabled); wpa_printf(MSG_DEBUG, " * ht_enabled=%d", freq->ht_enabled); - if (freq->vht_enabled) { + if (freq->vht_enabled || freq->he_enabled) { enum nl80211_chan_width cw; wpa_printf(MSG_DEBUG, " * bandwidth=%d", freq->bandwidth); @@ -4430,8 +4427,8 @@ static int nl80211_set_channel(struct i802_bss *bss, int ret; wpa_printf(MSG_DEBUG, - "nl80211: Set freq %d (ht_enabled=%d, vht_enabled=%d, bandwidth=%d MHz, cf1=%d MHz, cf2=%d MHz)", - freq->freq, freq->ht_enabled, freq->vht_enabled, + "nl80211: Set freq %d (ht_enabled=%d, vht_enabled=%d, he_enabled=%d, bandwidth=%d MHz, cf1=%d MHz, cf2=%d MHz)", + freq->freq, freq->ht_enabled, freq->vht_enabled, freq->he_enabled, freq->bandwidth, freq->center_freq1, freq->center_freq2); msg = nl80211_drv_msg(drv, 0, set_chan ? NL80211_CMD_SET_CHANNEL : @@ -4563,6 +4560,14 @@ static int wpa_driver_nl80211_sta_add(void *priv, goto fail; } + if (params->he_capab) { + wpa_hexdump(MSG_DEBUG, " * he_capab", + params->he_capab, params->he_capab_len); + if (nla_put(msg, NL80211_ATTR_HE_CAPABILITY, + params->he_capab_len, params->he_capab)) + goto fail; + } + if (params->ext_capab) { wpa_hexdump(MSG_DEBUG, " * ext_capab", params->ext_capab, params->ext_capab_len); @@ -4695,8 +4700,9 @@ static int wpa_driver_nl80211_sta_add(void *priv, goto fail; #endif /* CONFIG_MESH */ - if ((!params->set || FULL_AP_CLIENT_STATE_SUPP(drv->capa.flags)) && - (params->flags & WPA_STA_WMM)) { + if ((!params->set || (params->flags & WPA_STA_TDLS_PEER) || + FULL_AP_CLIENT_STATE_SUPP(drv->capa.flags)) && + (params->flags & WPA_STA_WMM)) { struct nlattr *wme = nla_nest_start(msg, NL80211_ATTR_STA_WME); wpa_printf(MSG_DEBUG, " * qosinfo=0x%x", params->qosinfo); @@ -5187,6 +5193,28 @@ fail: } +static int driver_nl80211_sta_set_airtime_weight(void *priv, const u8 *addr, + unsigned int weight) +{ + struct i802_bss *bss = priv; + struct nl_msg *msg; + + wpa_printf(MSG_DEBUG, + "nl80211: Set STA airtime weight - ifname=%s addr=" MACSTR + " weight=%u", bss->ifname, MAC2STR(addr), weight); + + if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_STATION)) || + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) || + nla_put_u16(msg, NL80211_ATTR_AIRTIME_WEIGHT, weight)) + goto fail; + + return send_and_recv_msgs(bss->drv, msg, NULL, NULL); +fail: + nlmsg_free(msg); + return -ENOBUFS; +} + + static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv, struct wpa_driver_associate_params *params) { @@ -5605,7 +5633,7 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv, return -1; } - if (params->req_key_mgmt_offload && + if (params->req_handshake_offload && (drv->capa.flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X)) { wpa_printf(MSG_DEBUG, " * WANT_1X_4WAY_HS"); if (nla_put_flag(msg, NL80211_ATTR_WANT_1X_4WAY_HS)) @@ -6266,6 +6294,36 @@ static int i802_flush(void *priv) } +static void get_sta_tid_stats(struct hostap_sta_driver_data *data, + struct nlattr *attr) +{ + struct nlattr *tid_stats[NL80211_TID_STATS_MAX + 1], *tidattr; + struct nlattr *txq_stats[NL80211_TXQ_STATS_MAX + 1]; + static struct nla_policy txq_stats_policy[NL80211_TXQ_STATS_MAX + 1] = { + [NL80211_TXQ_STATS_BACKLOG_BYTES] = { .type = NLA_U32 }, + [NL80211_TXQ_STATS_BACKLOG_PACKETS] = { .type = NLA_U32 }, + }; + int rem; + + nla_for_each_nested(tidattr, attr, rem) { + if (nla_parse_nested(tid_stats, NL80211_TID_STATS_MAX, + tidattr, NULL) != 0 || + !tid_stats[NL80211_TID_STATS_TXQ_STATS] || + nla_parse_nested(txq_stats, NL80211_TXQ_STATS_MAX, + tid_stats[NL80211_TID_STATS_TXQ_STATS], + txq_stats_policy) != 0) + continue; + /* sum the backlogs over all TIDs for station */ + if (txq_stats[NL80211_TXQ_STATS_BACKLOG_BYTES]) + data->backlog_bytes += nla_get_u32( + txq_stats[NL80211_TXQ_STATS_BACKLOG_BYTES]); + if (txq_stats[NL80211_TXQ_STATS_BACKLOG_PACKETS]) + data->backlog_bytes += nla_get_u32( + txq_stats[NL80211_TXQ_STATS_BACKLOG_PACKETS]); + } +} + + static int get_sta_handler(struct nl_msg *msg, void *arg) { struct nlattr *tb[NL80211_ATTR_MAX + 1]; @@ -6283,6 +6341,8 @@ static int get_sta_handler(struct nl_msg *msg, void *arg) [NL80211_STA_INFO_TX_BYTES64] = { .type = NLA_U64 }, [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 }, [NL80211_STA_INFO_ACK_SIGNAL] = { .type = NLA_U8 }, + [NL80211_STA_INFO_RX_DURATION] = { .type = NLA_U64 }, + [NL80211_STA_INFO_TX_DURATION] = { .type = NLA_U64 }, }; struct nlattr *rate[NL80211_RATE_INFO_MAX + 1]; static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = { @@ -6340,6 +6400,12 @@ static int get_sta_handler(struct nl_msg *msg, void *arg) if (stats[NL80211_STA_INFO_TX_PACKETS]) data->tx_packets = nla_get_u32(stats[NL80211_STA_INFO_TX_PACKETS]); + if (stats[NL80211_STA_INFO_RX_DURATION]) + data->rx_airtime = + nla_get_u64(stats[NL80211_STA_INFO_RX_DURATION]); + if (stats[NL80211_STA_INFO_TX_DURATION]) + data->tx_airtime = + nla_get_u64(stats[NL80211_STA_INFO_TX_DURATION]); if (stats[NL80211_STA_INFO_TX_FAILED]) data->tx_retry_failed = nla_get_u32(stats[NL80211_STA_INFO_TX_FAILED]); @@ -6410,6 +6476,9 @@ static int get_sta_handler(struct nl_msg *msg, void *arg) } } + if (stats[NL80211_STA_INFO_TID_STATS]) + get_sta_tid_stats(data, stats[NL80211_STA_INFO_TID_STATS]); + return NL_SKIP; } @@ -6550,7 +6619,7 @@ static int i802_sta_clear_stats(void *priv, const u8 *addr) static int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, - int reason) + u16 reason) { struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; @@ -6585,7 +6654,7 @@ static int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, static int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, - int reason) + u16 reason) { struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; @@ -6620,11 +6689,11 @@ static void dump_ifidx(struct wpa_driver_nl80211_data *drv) end = pos + sizeof(buf); for (i = 0; i < drv->num_if_indices; i++) { - if (!drv->if_indices[i]) + if (!drv->if_indices[i].ifindex) continue; res = os_snprintf(pos, end - pos, " %d(%d)", - drv->if_indices[i], - drv->if_indices_reason[i]); + drv->if_indices[i].ifindex, + drv->if_indices[i].reason); if (os_snprintf_error(end - pos, res)) break; pos += res; @@ -6640,7 +6709,7 @@ static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx, int ifidx_reason) { int i; - int *old, *old_reason; + struct drv_nl80211_if_info *old; wpa_printf(MSG_DEBUG, "nl80211: Add own interface ifindex %d (ifidx_reason %d)", @@ -6651,9 +6720,9 @@ static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx, return; } for (i = 0; i < drv->num_if_indices; i++) { - if (drv->if_indices[i] == 0) { - drv->if_indices[i] = ifidx; - drv->if_indices_reason[i] = ifidx_reason; + if (drv->if_indices[i].ifindex == 0) { + drv->if_indices[i].ifindex = ifidx; + drv->if_indices[i].reason = ifidx_reason; dump_ifidx(drv); return; } @@ -6664,29 +6733,13 @@ static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx, else old = NULL; - if (drv->if_indices_reason != drv->default_if_indices_reason) - old_reason = drv->if_indices_reason; - else - old_reason = NULL; - drv->if_indices = os_realloc_array(old, drv->num_if_indices + 1, - sizeof(int)); - drv->if_indices_reason = os_realloc_array(old_reason, - drv->num_if_indices + 1, - sizeof(int)); + sizeof(*old)); if (!drv->if_indices) { if (!old) drv->if_indices = drv->default_if_indices; else drv->if_indices = old; - } - if (!drv->if_indices_reason) { - if (!old_reason) - drv->if_indices_reason = drv->default_if_indices_reason; - else - drv->if_indices_reason = old_reason; - } - if (!drv->if_indices || !drv->if_indices_reason) { wpa_printf(MSG_ERROR, "Failed to reallocate memory for " "interfaces"); wpa_printf(MSG_ERROR, "Ignoring EAPOL on interface %d", ifidx); @@ -6695,12 +6748,8 @@ static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx, if (!old) os_memcpy(drv->if_indices, drv->default_if_indices, sizeof(drv->default_if_indices)); - if (!old_reason) - os_memcpy(drv->if_indices_reason, - drv->default_if_indices_reason, - sizeof(drv->default_if_indices_reason)); - drv->if_indices[drv->num_if_indices] = ifidx; - drv->if_indices_reason[drv->num_if_indices] = ifidx_reason; + drv->if_indices[drv->num_if_indices].ifindex = ifidx; + drv->if_indices[drv->num_if_indices].reason = ifidx_reason; drv->num_if_indices++; dump_ifidx(drv); } @@ -6712,10 +6761,12 @@ static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx, int i; for (i = 0; i < drv->num_if_indices; i++) { - if ((drv->if_indices[i] == ifidx || ifidx == IFIDX_ANY) && - (drv->if_indices_reason[i] == ifidx_reason || + if ((drv->if_indices[i].ifindex == ifidx || + ifidx == IFIDX_ANY) && + (drv->if_indices[i].reason == ifidx_reason || ifidx_reason == IFIDX_ANY)) { - drv->if_indices[i] = 0; + drv->if_indices[i].ifindex = 0; + drv->if_indices[i].reason = 0; break; } } @@ -6729,8 +6780,8 @@ static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx, int i; for (i = 0; i < drv->num_if_indices; i++) - if (drv->if_indices[i] == ifidx && - (drv->if_indices_reason[i] == ifidx_reason || + if (drv->if_indices[i].ifindex == ifidx && + (drv->if_indices[i].reason == ifidx_reason || ifidx_reason == IFIDX_ANY)) return 1; @@ -8372,8 +8423,8 @@ static int nl80211_start_radar_detection(void *priv, struct nl_msg *msg; int ret; - wpa_printf(MSG_DEBUG, "nl80211: Start radar detection (CAC) %d MHz (ht_enabled=%d, vht_enabled=%d, bandwidth=%d MHz, cf1=%d MHz, cf2=%d MHz)", - freq->freq, freq->ht_enabled, freq->vht_enabled, + wpa_printf(MSG_DEBUG, "nl80211: Start radar detection (CAC) %d MHz (ht_enabled=%d, vht_enabled=%d, he_enabled=%d, bandwidth=%d MHz, cf1=%d MHz, cf2=%d MHz)", + freq->freq, freq->ht_enabled, freq->vht_enabled, freq->he_enabled, freq->bandwidth, freq->center_freq1, freq->center_freq2); if (!(drv->capa.flags & WPA_DRIVER_FLAGS_RADAR)) { @@ -8585,7 +8636,7 @@ static int driver_nl80211_scan2(void *priv, static int driver_nl80211_deauthenticate(void *priv, const u8 *addr, - int reason_code) + u16 reason_code) { struct i802_bss *bss = priv; return wpa_driver_nl80211_deauthenticate(bss, addr, reason_code); @@ -8700,6 +8751,35 @@ static int wpa_driver_nl80211_update_ft_ies(void *priv, const u8 *md, } +static int nl80211_update_dh_ie(void *priv, const u8 *peer_mac, + u16 reason_code, const u8 *ie, size_t ie_len) +{ + int ret; + struct nl_msg *msg; + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + + wpa_printf(MSG_DEBUG, "nl80211: Updating DH IE peer: " MACSTR + " reason %u", MAC2STR(peer_mac), reason_code); + if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_UPDATE_OWE_INFO)) || + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer_mac) || + nla_put_u16(msg, NL80211_ATTR_STATUS_CODE, reason_code) || + (ie && nla_put(msg, NL80211_ATTR_IE, ie_len, ie))) { + nlmsg_free(msg); + return -ENOBUFS; + } + + ret = send_and_recv_msgs(drv, msg, NULL, NULL); + if (ret) { + wpa_printf(MSG_DEBUG, + "nl80211: update_dh_ie failed err=%d (%s)", + ret, strerror(-ret)); + } + + return ret; +} + + static const u8 * wpa_driver_nl80211_get_macaddr(void *priv) { struct i802_bss *bss = priv; @@ -9648,6 +9728,36 @@ static int wpa_driver_nl80211_leave_mesh(void *priv) return ret; } + +static int nl80211_probe_mesh_link(void *priv, const u8 *addr, const u8 *eth, + size_t len) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + int ret; + + msg = nl80211_drv_msg(drv, 0, NL80211_CMD_PROBE_MESH_LINK); + if (!msg || + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) || + nla_put(msg, NL80211_ATTR_FRAME, len, eth)) { + nlmsg_free(msg); + return -ENOBUFS; + } + + ret = send_and_recv_msgs(drv, msg, NULL, NULL); + if (ret) { + wpa_printf(MSG_DEBUG, "nl80211: mesh link probe to " MACSTR + " failed: ret=%d (%s)", + MAC2STR(addr), ret, strerror(-ret)); + } else { + wpa_printf(MSG_DEBUG, "nl80211: Mesh link to " MACSTR + " probed successfully", MAC2STR(addr)); + } + + return ret; +} + #endif /* CONFIG_MESH */ @@ -10636,22 +10746,37 @@ static int nl80211_write_to_file(const char *name, unsigned int val) { int fd, len; char tmp[128]; + int ret = 0; fd = open(name, O_RDWR); if (fd < 0) { - wpa_printf(MSG_ERROR, "nl80211: Failed to open %s: %s", + int level; + /* + * Flags may not exist on older kernels, or while we're tearing + * down a disappearing device. + */ + if (errno == ENOENT) { + ret = 0; + level = MSG_DEBUG; + } else { + ret = -1; + level = MSG_ERROR; + } + wpa_printf(level, "nl80211: Failed to open %s: %s", name, strerror(errno)); - return fd; + return ret; } len = os_snprintf(tmp, sizeof(tmp), "%u\n", val); len = write(fd, tmp, len); - if (len < 0) + if (len < 0) { + ret = -1; wpa_printf(MSG_ERROR, "nl80211: Failed to write to %s: %s", name, strerror(errno)); + } close(fd); - return 0; + return ret; } @@ -10819,7 +10944,7 @@ static int nl80211_send_external_auth_status(void *priv, * SAE) to hostapd/wpa_supplicant. Do nott send the status to drivers * which do not support AP SME or use wpa_supplicant/hostapd SME. */ - if (!bss->drv->device_ap_sme || + if ((is_ap_interface(drv->nlmode) && !bss->drv->device_ap_sme) || (drv->capa.flags & WPA_DRIVER_FLAGS_SME)) return -1; @@ -10926,6 +11051,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { .sta_remove = driver_nl80211_sta_remove, .hapd_send_eapol = wpa_driver_nl80211_hapd_send_eapol, .sta_set_flags = wpa_driver_nl80211_sta_set_flags, + .sta_set_airtime_weight = driver_nl80211_sta_set_airtime_weight, .hapd_init = i802_init, .hapd_deinit = i802_deinit, .set_wds_sta = i802_set_wds_sta, @@ -10971,6 +11097,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { .tdls_disable_channel_switch = nl80211_tdls_disable_channel_switch, #endif /* CONFIG_TDLS */ .update_ft_ies = wpa_driver_nl80211_update_ft_ies, + .update_dh_ie = nl80211_update_dh_ie, .get_mac_addr = wpa_driver_nl80211_get_macaddr, .get_survey = wpa_driver_nl80211_get_survey, .status = wpa_driver_nl80211_status, @@ -10993,6 +11120,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { .init_mesh = wpa_driver_nl80211_init_mesh, .join_mesh = wpa_driver_nl80211_join_mesh, .leave_mesh = wpa_driver_nl80211_leave_mesh, + .probe_mesh_link = nl80211_probe_mesh_link, #endif /* CONFIG_MESH */ .br_add_ip_neigh = wpa_driver_br_add_ip_neigh, .br_delete_ip_neigh = wpa_driver_br_delete_ip_neigh, diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index 1e7fe7a98fff..74982694561e 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -83,6 +83,12 @@ struct i802_bss { u8 rand_addr[ETH_ALEN]; }; +struct drv_nl80211_if_info { + int ifindex; + /* the AP/AP_VLAN iface that is in this bridge */ + int reason; +}; + struct wpa_driver_nl80211_data { struct nl80211_global *global; struct dl_list list; @@ -163,7 +169,6 @@ struct wpa_driver_nl80211_data { unsigned int scan_vendor_cmd_avail:1; unsigned int connect_reassoc:1; unsigned int set_wifi_conf_vendor_cmd_avail:1; - unsigned int he_capab_vendor_cmd_avail:1; unsigned int fetch_bss_trans_status:1; unsigned int roam_vendor_cmd_avail:1; unsigned int get_supported_akm_suites_avail:1; @@ -188,11 +193,8 @@ struct wpa_driver_nl80211_data { struct nl_handle *rtnl_sk; /* nl_sock for NETLINK_ROUTE */ - int default_if_indices[16]; - /* the AP/AP_VLAN iface that is in this bridge */ - int default_if_indices_reason[16]; - int *if_indices; - int *if_indices_reason; + struct drv_nl80211_if_info default_if_indices[16]; + struct drv_nl80211_if_info *if_indices; int num_if_indices; /* From failed authentication command */ @@ -215,8 +217,6 @@ struct wpa_driver_nl80211_data { * (NL80211_CMD_VENDOR). 0 if no pending scan request. */ int last_scan_cmd; - - struct he_capabilities he_capab; }; struct nl_msg; diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index 37eeb5e6686d..8318b10ab9e7 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -778,9 +778,6 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg) case QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION: drv->set_wifi_conf_vendor_cmd_avail = 1; break; - case QCA_NL80211_VENDOR_SUBCMD_GET_HE_CAPABILITIES: - drv->he_capab_vendor_cmd_avail = 1; - break; case QCA_NL80211_VENDOR_SUBCMD_FETCH_BSS_TRANSITION_STATUS: drv->fetch_bss_trans_status = 1; break; @@ -1082,100 +1079,6 @@ static int qca_nl80211_get_akm_suites(struct wpa_driver_nl80211_data *drv) } -static int qca_nl80211_he_capab_handler(struct nl_msg *msg, void *arg) -{ - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct he_capabilities *he_capab = arg; - struct nlattr *nl_vend; - struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_MAX + 1]; - size_t len; - - nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - - if (!tb[NL80211_ATTR_VENDOR_DATA]) - return NL_SKIP; - - nl_vend = tb[NL80211_ATTR_VENDOR_DATA]; - nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_MAX, - nla_data(nl_vend), nla_len(nl_vend), NULL); - - if (tb_vendor[QCA_WLAN_VENDOR_ATTR_HE_SUPPORTED]) { - u8 he_supported; - - he_supported = nla_get_u8( - tb_vendor[QCA_WLAN_VENDOR_ATTR_HE_SUPPORTED]); - wpa_printf(MSG_DEBUG, "nl80211: HE capabilities supported: %u", - he_supported); - he_capab->he_supported = he_supported; - if (!he_supported) - return NL_SKIP; - } - - if (tb_vendor[QCA_WLAN_VENDOR_ATTR_PHY_CAPAB]) { - len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_PHY_CAPAB]); - - if (len > sizeof(he_capab->phy_cap)) - len = sizeof(he_capab->phy_cap); - os_memcpy(he_capab->phy_cap, - nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_PHY_CAPAB]), - len); - } - - if (tb_vendor[QCA_WLAN_VENDOR_ATTR_MAC_CAPAB]) - he_capab->mac_cap = - nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_MAC_CAPAB]); - - if (tb_vendor[QCA_WLAN_VENDOR_ATTR_HE_MCS]) - he_capab->mcs = - nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_HE_MCS]); - - if (tb_vendor[QCA_WLAN_VENDOR_ATTR_NUM_SS]) - he_capab->ppet.numss_m1 = - nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_NUM_SS]); - - if (tb_vendor[QCA_WLAN_VENDOR_ATTR_RU_IDX_MASK]) - he_capab->ppet.ru_count = - nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_RU_IDX_MASK]); - - if (tb_vendor[QCA_WLAN_VENDOR_ATTR_PPE_THRESHOLD]) { - len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_PPE_THRESHOLD]); - - if (len > sizeof(he_capab->ppet.ppet16_ppet8_ru3_ru0)) - len = sizeof(he_capab->ppet.ppet16_ppet8_ru3_ru0); - os_memcpy(he_capab->ppet.ppet16_ppet8_ru3_ru0, - nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_PPE_THRESHOLD]), - len); - } - - return NL_SKIP; -} - - -static void qca_nl80211_check_he_capab(struct wpa_driver_nl80211_data *drv) -{ - struct nl_msg *msg; - int ret; - - if (!drv->he_capab_vendor_cmd_avail) - return; - - if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) || - nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) || - nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, - QCA_NL80211_VENDOR_SUBCMD_GET_HE_CAPABILITIES)) { - nlmsg_free(msg); - return; - } - - ret = send_and_recv_msgs(drv, msg, qca_nl80211_he_capab_handler, - &drv->he_capab); - if (!ret && drv->he_capab.he_supported) - drv->capa.flags |= WPA_DRIVER_FLAGS_HE_CAPABILITIES; -} - - struct features_info { u8 *flags; size_t flags_len; @@ -1373,7 +1276,6 @@ int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv) if (!(info.capa->flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)) qca_nl80211_check_dfs_capa(drv); qca_nl80211_get_features(drv); - qca_nl80211_check_he_capab(drv); /* * To enable offchannel simultaneous support in wpa_supplicant, the @@ -1492,6 +1394,57 @@ static void phy_info_freq(struct hostapd_hw_modes *mode, chan->dfs_cac_ms = nla_get_u32( tb_freq[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME]); } + + chan->wmm_rules_valid = 0; + if (tb_freq[NL80211_FREQUENCY_ATTR_WMM]) { + static struct nla_policy wmm_policy[NL80211_WMMR_MAX + 1] = { + [NL80211_WMMR_CW_MIN] = { .type = NLA_U16 }, + [NL80211_WMMR_CW_MAX] = { .type = NLA_U16 }, + [NL80211_WMMR_AIFSN] = { .type = NLA_U8 }, + [NL80211_WMMR_TXOP] = { .type = NLA_U16 }, + }; + struct nlattr *nl_wmm; + struct nlattr *tb_wmm[NL80211_WMMR_MAX + 1]; + int rem_wmm, ac, count = 0; + + nla_for_each_nested(nl_wmm, tb_freq[NL80211_FREQUENCY_ATTR_WMM], + rem_wmm) { + if (nla_parse_nested(tb_wmm, NL80211_WMMR_MAX, nl_wmm, + wmm_policy)) { + wpa_printf(MSG_DEBUG, + "nl80211: Failed to parse WMM rules attribute"); + return; + } + if (!tb_wmm[NL80211_WMMR_CW_MIN] || + !tb_wmm[NL80211_WMMR_CW_MAX] || + !tb_wmm[NL80211_WMMR_AIFSN] || + !tb_wmm[NL80211_WMMR_TXOP]) { + wpa_printf(MSG_DEBUG, + "nl80211: Channel is missing WMM rule attribute"); + return; + } + ac = nl_wmm->nla_type; + if (ac < 0 || ac >= WMM_AC_NUM) { + wpa_printf(MSG_DEBUG, + "nl80211: Invalid AC value %d", ac); + return; + } + + chan->wmm_rules[ac].min_cwmin = + nla_get_u16(tb_wmm[NL80211_WMMR_CW_MIN]); + chan->wmm_rules[ac].min_cwmax = + nla_get_u16(tb_wmm[NL80211_WMMR_CW_MAX]); + chan->wmm_rules[ac].min_aifs = + nla_get_u8(tb_wmm[NL80211_WMMR_AIFSN]); + chan->wmm_rules[ac].max_txop = + nla_get_u16(tb_wmm[NL80211_WMMR_TXOP]) / 32; + count++; + } + + /* Set valid flag if all the AC rules are present */ + if (count == WMM_AC_NUM) + chan->wmm_rules_valid = 1; + } } @@ -1598,6 +1551,101 @@ static int phy_info_rates(struct hostapd_hw_modes *mode, struct nlattr *tb) } +static void phy_info_iftype_copy(struct he_capabilities *he_capab, + enum ieee80211_op_mode opmode, + struct nlattr **tb, struct nlattr **tb_flags) +{ + enum nl80211_iftype iftype; + size_t len; + + switch (opmode) { + case IEEE80211_MODE_INFRA: + iftype = NL80211_IFTYPE_STATION; + break; + case IEEE80211_MODE_IBSS: + iftype = NL80211_IFTYPE_ADHOC; + break; + case IEEE80211_MODE_AP: + iftype = NL80211_IFTYPE_AP; + break; + case IEEE80211_MODE_MESH: + iftype = NL80211_IFTYPE_MESH_POINT; + break; + default: + return; + } + + if (!nla_get_flag(tb_flags[iftype])) + return; + + he_capab->he_supported = 1; + + if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]) { + len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]); + + if (len > sizeof(he_capab->phy_cap)) + len = sizeof(he_capab->phy_cap); + os_memcpy(he_capab->phy_cap, + nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]), + len); + } + + if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC]) { + len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC]); + + if (len > sizeof(he_capab->mac_cap)) + len = sizeof(he_capab->mac_cap); + os_memcpy(he_capab->mac_cap, + nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC]), + len); + } + + if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET]) { + len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET]); + + if (len > sizeof(he_capab->mcs)) + len = sizeof(he_capab->mcs); + os_memcpy(he_capab->mcs, + nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET]), + len); + } + + if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE]) { + len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE]); + + if (len > sizeof(he_capab->ppet)) + len = sizeof(he_capab->ppet); + os_memcpy(&he_capab->ppet, + nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE]), + len); + } +} + + +static int phy_info_iftype(struct hostapd_hw_modes *mode, + struct nlattr *nl_iftype) +{ + struct nlattr *tb[NL80211_BAND_IFTYPE_ATTR_MAX + 1]; + struct nlattr *tb_flags[NL80211_IFTYPE_MAX + 1]; + unsigned int i; + + nla_parse(tb, NL80211_BAND_IFTYPE_ATTR_MAX, + nla_data(nl_iftype), nla_len(nl_iftype), NULL); + + if (!tb[NL80211_BAND_IFTYPE_ATTR_IFTYPES]) + return NL_STOP; + + if (nla_parse_nested(tb_flags, NL80211_IFTYPE_MAX, + tb[NL80211_BAND_IFTYPE_ATTR_IFTYPES], NULL)) + return NL_STOP; + + for (i = 0; i < IEEE80211_MODE_NUM; i++) + phy_info_iftype_copy(&mode->he_capab[i], i, tb, tb_flags); + + return NL_OK; +} + + static int phy_info_band(struct phy_info_arg *phy_info, struct nlattr *nl_band) { struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1]; @@ -1654,6 +1702,19 @@ static int phy_info_band(struct phy_info_arg *phy_info, struct nlattr *nl_band) return ret; } + if (tb_band[NL80211_BAND_ATTR_IFTYPE_DATA]) { + struct nlattr *nl_iftype; + int rem_band; + + nla_for_each_nested(nl_iftype, + tb_band[NL80211_BAND_ATTR_IFTYPE_DATA], + rem_band) { + ret = phy_info_iftype(mode, nl_iftype); + if (ret != NL_OK) + return ret; + } + } + return NL_OK; } diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index ee7b4da38d87..7c16330662eb 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -136,6 +136,7 @@ static const char * nl80211_command_to_string(enum nl80211_commands cmd) C2S(NL80211_CMD_EXTERNAL_AUTH) C2S(NL80211_CMD_STA_OPMODE_CHANGED) C2S(NL80211_CMD_CONTROL_PORT_FRAME) + C2S(NL80211_CMD_UPDATE_OWE_INFO) default: return "NL80211_CMD_UNKNOWN"; } @@ -534,7 +535,8 @@ static int calculate_chan_offset(int width, int freq, int cf1, int cf2) static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv, struct nlattr *ifindex, struct nlattr *freq, struct nlattr *type, struct nlattr *bw, - struct nlattr *cf1, struct nlattr *cf2) + struct nlattr *cf1, struct nlattr *cf2, + int finished) { struct i802_bss *bss; union wpa_event_data data; @@ -542,7 +544,8 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv, int chan_offset = 0; int ifidx; - wpa_printf(MSG_DEBUG, "nl80211: Channel switch event"); + wpa_printf(MSG_DEBUG, "nl80211: Channel switch%s event", + finished ? "" : " started"); if (!freq) return; @@ -593,10 +596,12 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv, if (cf2) data.ch_switch.cf2 = nla_get_u32(cf2); - bss->freq = data.ch_switch.freq; + if (finished) + bss->freq = data.ch_switch.freq; drv->assoc_freq = data.ch_switch.freq; - wpa_supplicant_event(bss->ctx, EVENT_CH_SWITCH, &data); + wpa_supplicant_event(bss->ctx, finished ? + EVENT_CH_SWITCH : EVENT_CH_SWITCH_STARTED, &data); } @@ -1101,6 +1106,29 @@ static void mlme_event_ft_event(struct wpa_driver_nl80211_data *drv, } +static void mlme_event_dh_event(struct wpa_driver_nl80211_data *drv, + struct i802_bss *bss, + struct nlattr *tb[]) +{ + union wpa_event_data data; + + if (!is_ap_interface(drv->nlmode)) + return; + if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_IE]) + return; + + os_memset(&data, 0, sizeof(data)); + data.update_dh.peer = nla_data(tb[NL80211_ATTR_MAC]); + data.update_dh.ie = nla_data(tb[NL80211_ATTR_IE]); + data.update_dh.ie_len = nla_len(tb[NL80211_ATTR_IE]); + + wpa_printf(MSG_DEBUG, "nl80211: DH event - peer " MACSTR, + MAC2STR(data.update_dh.peer)); + + wpa_supplicant_event(bss->ctx, EVENT_UPDATE_DH, &data); +} + + static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted, struct nlattr *tb[], int external_scan) { @@ -2508,6 +2536,16 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd, tb[NL80211_ATTR_PMK], tb[NL80211_ATTR_PMKID]); break; + case NL80211_CMD_CH_SWITCH_STARTED_NOTIFY: + mlme_event_ch_switch(drv, + tb[NL80211_ATTR_IFINDEX], + tb[NL80211_ATTR_WIPHY_FREQ], + tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE], + tb[NL80211_ATTR_CHANNEL_WIDTH], + tb[NL80211_ATTR_CENTER_FREQ1], + tb[NL80211_ATTR_CENTER_FREQ2], + 0); + break; case NL80211_CMD_CH_SWITCH_NOTIFY: mlme_event_ch_switch(drv, tb[NL80211_ATTR_IFINDEX], @@ -2515,7 +2553,8 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd, tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE], tb[NL80211_ATTR_CHANNEL_WIDTH], tb[NL80211_ATTR_CENTER_FREQ1], - tb[NL80211_ATTR_CENTER_FREQ2]); + tb[NL80211_ATTR_CENTER_FREQ2], + 1); break; case NL80211_CMD_DISCONNECT: mlme_event_disconnect(drv, tb[NL80211_ATTR_REASON_CODE], @@ -2586,6 +2625,9 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd, case NL80211_CMD_STA_OPMODE_CHANGED: nl80211_sta_opmode_change_event(drv, tb); break; + case NL80211_CMD_UPDATE_OWE_INFO: + mlme_event_dh_event(drv, bss, tb); + break; default: wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event " "(cmd=%d)", cmd); @@ -2634,8 +2676,9 @@ int process_global_event(struct nl_msg *msg, void *arg) } } wpa_printf(MSG_DEBUG, - "nl80211: Ignored event (cmd=%d) for foreign interface (ifindex %d wdev 0x%llx)", - gnlh->cmd, ifidx, (long long unsigned int) wdev_id); + "nl80211: Ignored event %d (%s) for foreign interface (ifindex %d wdev 0x%llx)", + gnlh->cmd, nl80211_command_to_string(gnlh->cmd), + ifidx, (long long unsigned int) wdev_id); } return NL_SKIP; diff --git a/src/drivers/driver_privsep.c b/src/drivers/driver_privsep.c index a3f0837e1569..55cf61885741 100644 --- a/src/drivers/driver_privsep.c +++ b/src/drivers/driver_privsep.c @@ -368,7 +368,7 @@ static int wpa_driver_privsep_get_ssid(void *priv, u8 *ssid) static int wpa_driver_privsep_deauthenticate(void *priv, const u8 *addr, - int reason_code) + u16 reason_code) { //struct wpa_driver_privsep_data *drv = priv; wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d", diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c index f7755cccde27..4d4a05d0cb72 100644 --- a/src/drivers/driver_wext.c +++ b/src/drivers/driver_wext.c @@ -1915,7 +1915,7 @@ static int wpa_driver_wext_set_drop_unencrypted(void *priv, static int wpa_driver_wext_mlme(struct wpa_driver_wext_data *drv, - const u8 *addr, int cmd, int reason_code) + const u8 *addr, int cmd, u16 reason_code) { struct iwreq iwr; struct iw_mlme mlme; @@ -1998,7 +1998,7 @@ static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv) static int wpa_driver_wext_deauthenticate(void *priv, const u8 *addr, - int reason_code) + u16 reason_code) { struct wpa_driver_wext_data *drv = priv; int ret; diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h index dd4f86ee286e..6f09d1500960 100644 --- a/src/drivers/nl80211_copy.h +++ b/src/drivers/nl80211_copy.h @@ -11,7 +11,7 @@ * Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com> * Copyright 2008 Colin McCabe <colin@cozybit.com> * Copyright 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018-2019 Intel Corporation * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -1065,6 +1065,26 @@ * indicated by %NL80211_ATTR_WIPHY_FREQ and other attributes * determining the width and type. * + * @NL80211_CMD_UPDATE_OWE_INFO: This interface allows the host driver to + * offload OWE processing to user space. This intends to support + * OWE AKM by the host drivers that implement SME but rely + * on the user space for the cryptographic/DH IE processing in AP mode. + * + * @NL80211_CMD_PROBE_MESH_LINK: The requirement for mesh link metric + * refreshing, is that from one mesh point we be able to send some data + * frames to other mesh points which are not currently selected as a + * primary traffic path, but which are only 1 hop away. The absence of + * the primary path to the chosen node makes it necessary to apply some + * form of marking on a chosen packet stream so that the packets can be + * properly steered to the selected node for testing, and not by the + * regular mesh path lookup. Further, the packets must be of type data + * so that the rate control (often embedded in firmware) is used for + * rate selection. + * + * Here attribute %NL80211_ATTR_MAC is used to specify connected mesh + * peer MAC address and %NL80211_ATTR_FRAME is used to specify the frame + * content. The frame is ethernet data. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -1285,6 +1305,10 @@ enum nl80211_commands { NL80211_CMD_NOTIFY_RADAR, + NL80211_CMD_UPDATE_OWE_INFO, + + NL80211_CMD_PROBE_MESH_LINK, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -2308,6 +2332,15 @@ enum nl80211_commands { * @NL80211_ATTR_AIRTIME_WEIGHT: Station's weight when scheduled by the airtime * scheduler. * + * @NL80211_ATTR_STA_TX_POWER_SETTING: Transmit power setting type (u8) for + * station associated with the AP. See &enum nl80211_tx_power_setting for + * possible values. + * @NL80211_ATTR_STA_TX_POWER: Transmit power level (s16) in dBm units. This + * allows to set Tx power for a station. If this attribute is not included, + * the default per-interface tx power setting will be overriding. Driver + * should be picking up the lowest tx power, either tx power per-interface + * or per-station. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -2758,6 +2791,8 @@ enum nl80211_attrs { NL80211_ATTR_PEER_MEASUREMENTS, NL80211_ATTR_AIRTIME_WEIGHT, + NL80211_ATTR_STA_TX_POWER_SETTING, + NL80211_ATTR_STA_TX_POWER, /* add attributes here, update the policy in nl80211.c */ @@ -2802,7 +2837,7 @@ enum nl80211_attrs { #define NL80211_MAX_SUPP_RATES 32 #define NL80211_MAX_SUPP_HT_RATES 77 -#define NL80211_MAX_SUPP_REG_RULES 64 +#define NL80211_MAX_SUPP_REG_RULES 128 #define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0 #define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16 #define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24 @@ -3139,6 +3174,7 @@ enum nl80211_sta_bss_param { * @NL80211_STA_INFO_TX_DURATION: aggregate PPDU duration for all frames * sent to the station (u64, usec) * @NL80211_STA_INFO_AIRTIME_WEIGHT: current airtime weight for station (u16) + * @NL80211_STA_INFO_AIRTIME_LINK_METRIC: airtime link metric for mesh station * @__NL80211_STA_INFO_AFTER_LAST: internal * @NL80211_STA_INFO_MAX: highest possible station info attribute */ @@ -3184,6 +3220,7 @@ enum nl80211_sta_info { NL80211_STA_INFO_CONNECTED_TO_GATE, NL80211_STA_INFO_TX_DURATION, NL80211_STA_INFO_AIRTIME_WEIGHT, + NL80211_STA_INFO_AIRTIME_LINK_METRIC, /* keep last */ __NL80211_STA_INFO_AFTER_LAST, @@ -3638,6 +3675,14 @@ enum nl80211_reg_rule_attr { * value as specified by &struct nl80211_bss_select_rssi_adjust. * @NL80211_SCHED_SCAN_MATCH_ATTR_BSSID: BSSID to be used for matching * (this cannot be used together with SSID). + * @NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI: Nested attribute that carries the + * band specific minimum rssi thresholds for the bands defined in + * enum nl80211_band. The minimum rssi threshold value(s32) specific to a + * band shall be encapsulated in attribute with type value equals to one + * of the NL80211_BAND_* defined in enum nl80211_band. For example, the + * minimum rssi threshold value for 2.4GHZ band shall be encapsulated + * within an attribute of type NL80211_BAND_2GHZ. And one or more of such + * attributes will be nested within this attribute. * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter * attribute number currently defined * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use @@ -3650,6 +3695,7 @@ enum nl80211_sched_scan_match_attr { NL80211_SCHED_SCAN_MATCH_ATTR_RELATIVE_RSSI, NL80211_SCHED_SCAN_MATCH_ATTR_RSSI_ADJUST, NL80211_SCHED_SCAN_MATCH_ATTR_BSSID, + NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI, /* keep last */ __NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST, @@ -4135,6 +4181,27 @@ enum nl80211_channel_type { }; /** + * enum nl80211_key_mode - Key mode + * + * @NL80211_KEY_RX_TX: (Default) + * Key can be used for Rx and Tx immediately + * + * The following modes can only be selected for unicast keys and when the + * driver supports @NL80211_EXT_FEATURE_EXT_KEY_ID: + * + * @NL80211_KEY_NO_TX: Only allowed in combination with @NL80211_CMD_NEW_KEY: + * Unicast key can only be used for Rx, Tx not allowed, yet + * @NL80211_KEY_SET_TX: Only allowed in combination with @NL80211_CMD_SET_KEY: + * The unicast key identified by idx and mac is cleared for Tx and becomes + * the preferred Tx key for the station. + */ +enum nl80211_key_mode { + NL80211_KEY_RX_TX, + NL80211_KEY_NO_TX, + NL80211_KEY_SET_TX +}; + +/** * enum nl80211_chan_width - channel width definitions * * These values are used with the %NL80211_ATTR_CHANNEL_WIDTH @@ -4377,6 +4444,9 @@ enum nl80211_key_default_types { * @NL80211_KEY_DEFAULT_TYPES: A nested attribute containing flags * attributes, specifying what a key should be set as default as. * See &enum nl80211_key_default_types. + * @NL80211_KEY_MODE: the mode from enum nl80211_key_mode. + * Defaults to @NL80211_KEY_RX_TX. + * * @__NL80211_KEY_AFTER_LAST: internal * @NL80211_KEY_MAX: highest key attribute */ @@ -4390,6 +4460,7 @@ enum nl80211_key_attributes { NL80211_KEY_DEFAULT_MGMT, NL80211_KEY_TYPE, NL80211_KEY_DEFAULT_TYPES, + NL80211_KEY_MODE, /* keep last */ __NL80211_KEY_AFTER_LAST, @@ -5335,6 +5406,8 @@ enum nl80211_feature_flags { * able to rekey an in-use key correctly. Userspace must not rekey PTK keys * if this flag is not set. Ignoring this can leak clear text packets and/or * freeze the connection. + * @NL80211_EXT_FEATURE_EXT_KEY_ID: Driver supports "Extended Key ID for + * Individually Addressed Frames" from IEEE802.11-2016. * * @NL80211_EXT_FEATURE_AIRTIME_FAIRNESS: Driver supports getting airtime * fairness for transmitted packets and has enabled airtime fairness @@ -5343,6 +5416,12 @@ enum nl80211_feature_flags { * @NL80211_EXT_FEATURE_AP_PMKSA_CACHING: Driver/device supports PMKSA caching * (set/del PMKSA operations) in AP mode. * + * @NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD: Driver supports + * filtering of sched scan results using band specific RSSI thresholds. + * + * @NL80211_EXT_FEATURE_STA_TX_PWR: This driver supports controlling tx power + * to a station. + * * @NUM_NL80211_EXT_FEATURES: number of extended features. * @MAX_NL80211_EXT_FEATURES: highest extended feature index. */ @@ -5384,6 +5463,9 @@ enum nl80211_ext_feature_index { NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS, NL80211_EXT_FEATURE_AP_PMKSA_CACHING, + NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD, + NL80211_EXT_FEATURE_EXT_KEY_ID, + NL80211_EXT_FEATURE_STA_TX_PWR, /* add new features before the definition below */ NUM_NL80211_EXT_FEATURES, |
