Accumulative patch from commit 4abc0424ef4bde2ea4fb1ba1c18619c7bc36eb02
4abc042 P2P: Automatic channel selection at re-invocation of persistent GO
8f39528 P2P: Modify wait time in INVITE state based on Tx status of INV-REQ
e112764 nl80211: Use NL80211_ATTR_PEER_AID to set TDLS peer AID
f8a5fd4 Synchronize with wireless-testing.git include/uapi/linux/nl80211.h
9b1693a WPS: Allow Device Password Id changes between PIN methods
1ba51ec nl80211: Add debug print for set_supp_port operation
add9b7a nl80211: Ignore deauth/disassoc event from old AP
eb4737f Fix ESS_DISASSOC ctrl_iface command parser
b54c9ff FT: Fix TKIP group key configuration in FT protocol
e78aaca Stop TKIP countermeasures on FLUSH command
3cb953e Do not set driver MAC ACL unless driver supports this
3c4ca36 hostapd: Support MAC address based access control list
Change-Id: I0250e483c2992e6da8b2d1a323b7e3b8a73f9608
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index c27544b..0f92b18 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -906,6 +906,8 @@
#define WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING 0x00000008
unsigned int probe_resp_offloads;
+ unsigned int max_acl_mac_addrs;
+
/**
* extended_capa - extended capabilities in driver/device
*
@@ -966,6 +968,16 @@
int bandwidth;
};
+struct mac_address {
+ u8 addr[ETH_ALEN];
+};
+
+struct hostapd_acl_params {
+ u8 acl_policy;
+ unsigned int num_mac_acl;
+ struct mac_address mac_acl[0];
+};
+
enum wpa_driver_if_type {
/**
* WPA_IF_STATION - Station mode interface
@@ -1596,6 +1608,16 @@
int (*set_ap)(void *priv, struct wpa_driver_ap_params *params);
/**
+ * set_acl - Set ACL in AP mode
+ * @priv: Private driver interface data
+ * @params: Parameters to configure ACL
+ * Returns: 0 on success, -1 on failure
+ *
+ * This is used only for the drivers which support MAC address ACL.
+ */
+ int (*set_acl)(void *priv, struct hostapd_acl_params *params);
+
+ /**
* hapd_init - Initialize driver interface (hostapd only)
* @hapd: Pointer to hostapd context
* @params: Configuration for the driver wrapper
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 3d16330..cbc80e3 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -225,7 +225,9 @@
struct nl_cb *nl_cb;
u8 auth_bssid[ETH_ALEN];
+ u8 auth_attempt_bssid[ETH_ALEN];
u8 bssid[ETH_ALEN];
+ u8 prev_bssid[ETH_ALEN];
int associated;
u8 ssid[32];
size_t ssid_len;
@@ -376,6 +378,15 @@
}
+static void nl80211_mark_disconnected(struct wpa_driver_nl80211_data *drv)
+{
+ if (drv->associated)
+ os_memcpy(drv->prev_bssid, drv->bssid, ETH_ALEN);
+ drv->associated = 0;
+ os_memset(drv->bssid, 0, ETH_ALEN);
+}
+
+
struct nl80211_bss_info_arg {
struct wpa_driver_nl80211_data *drv;
struct wpa_scan_results *res;
@@ -1053,6 +1064,7 @@
}
os_memcpy(drv->auth_bssid, mgmt->sa, ETH_ALEN);
+ os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
os_memset(&event, 0, sizeof(event));
os_memcpy(event.auth.peer, mgmt->sa, ETH_ALEN);
event.auth.auth_type = le_to_host16(mgmt->u.auth.auth_alg);
@@ -1132,6 +1144,7 @@
drv->associated = 1;
os_memcpy(drv->bssid, mgmt->sa, ETH_ALEN);
+ os_memcpy(drv->prev_bssid, mgmt->sa, ETH_ALEN);
os_memset(&event, 0, sizeof(event));
if (len > 24 + sizeof(mgmt->u.assoc_resp)) {
@@ -1183,8 +1196,10 @@
}
drv->associated = 1;
- if (addr)
+ if (addr) {
os_memcpy(drv->bssid, nla_data(addr), ETH_ALEN);
+ os_memcpy(drv->prev_bssid, drv->bssid, ETH_ALEN);
+ }
if (req_ie) {
event.assoc_info.req_ies = nla_data(req_ie);
@@ -1231,7 +1246,7 @@
}
wpa_printf(MSG_DEBUG, "nl80211: Disconnect event");
- drv->associated = 0;
+ nl80211_mark_disconnected(drv);
os_memset(&data, 0, sizeof(data));
if (reason)
data.deauth_info.reason_code = nla_get_u16(reason);
@@ -1400,6 +1415,22 @@
if (len >= 24) {
bssid = mgmt->bssid;
+ if ((drv->capa.flags & WPA_DRIVER_FLAGS_SME) &&
+ !drv->associated &&
+ os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0 &&
+ os_memcmp(bssid, drv->auth_attempt_bssid, ETH_ALEN) != 0 &&
+ os_memcmp(bssid, drv->prev_bssid, ETH_ALEN) == 0) {
+ /*
+ * Avoid issues with some roaming cases where
+ * disconnection event for the old AP may show up after
+ * we have started connection with the new AP.
+ */
+ wpa_printf(MSG_DEBUG, "nl80211: Ignore deauth/disassoc event from old AP " MACSTR " when already authenticating with " MACSTR,
+ MAC2STR(bssid),
+ MAC2STR(drv->auth_attempt_bssid));
+ return;
+ }
+
if (drv->associated != 0 &&
os_memcmp(bssid, drv->bssid, ETH_ALEN) != 0 &&
os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0) {
@@ -1415,7 +1446,7 @@
}
}
- drv->associated = 0;
+ nl80211_mark_disconnected(drv);
os_memset(&event, 0, sizeof(event));
/* Note: Same offset for Reason Code in both frame subtypes */
@@ -2877,6 +2908,10 @@
capa->max_match_sets =
nla_get_u8(tb[NL80211_ATTR_MAX_MATCH_SETS]);
+ if (tb[NL80211_ATTR_MAC_ACL_MAX])
+ capa->max_acl_mac_addrs =
+ nla_get_u8(tb[NL80211_ATTR_MAC_ACL_MAX]);
+
wiphy_info_supported_iftypes(info, tb[NL80211_ATTR_SUPPORTED_IFTYPES]);
wiphy_info_iface_comb(info, tb[NL80211_ATTR_INTERFACE_COMBINATIONS]);
wiphy_info_supp_cmds(info, tb[NL80211_ATTR_SUPPORTED_COMMANDS]);
@@ -4841,7 +4876,7 @@
int reason_code)
{
wpa_printf(MSG_DEBUG, "%s(reason_code=%d)", __func__, reason_code);
- drv->associated = 0;
+ nl80211_mark_disconnected(drv);
drv->ignore_next_local_disconnect = 0;
/* Disconnect command doesn't need BSSID - it uses cached value */
return wpa_driver_nl80211_mlme(drv, NULL, NL80211_CMD_DISCONNECT,
@@ -4857,7 +4892,7 @@
return wpa_driver_nl80211_disconnect(drv, reason_code);
wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)",
__func__, MAC2STR(addr), reason_code);
- drv->associated = 0;
+ nl80211_mark_disconnected(drv);
if (drv->nlmode == NL80211_IFTYPE_ADHOC)
return nl80211_leave_ibss(drv);
return wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE,
@@ -4925,8 +4960,12 @@
is_retry = drv->retry_auth;
drv->retry_auth = 0;
- drv->associated = 0;
+ nl80211_mark_disconnected(drv);
os_memset(drv->auth_bssid, 0, ETH_ALEN);
+ if (params->bssid)
+ os_memcpy(drv->auth_attempt_bssid, params->bssid, ETH_ALEN);
+ else
+ os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
/* FIX: IBSS mode */
nlmode = params->p2p ?
NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;
@@ -5837,6 +5876,60 @@
}
+static int wpa_driver_nl80211_set_acl(void *priv,
+ struct hostapd_acl_params *params)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ struct nlattr *acl;
+ unsigned int i;
+ int ret = 0;
+
+ if (!(drv->capa.max_acl_mac_addrs))
+ return -ENOTSUP;
+
+ if (params->num_mac_acl > drv->capa.max_acl_mac_addrs)
+ return -ENOTSUP;
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -ENOMEM;
+
+ wpa_printf(MSG_DEBUG, "nl80211: Set %s ACL (num_mac_acl=%u)",
+ params->acl_policy ? "Accept" : "Deny", params->num_mac_acl);
+
+ nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_MAC_ACL);
+
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+
+ NLA_PUT_U32(msg, NL80211_ATTR_ACL_POLICY, params->acl_policy ?
+ NL80211_ACL_POLICY_DENY_UNLESS_LISTED :
+ NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED);
+
+ acl = nla_nest_start(msg, NL80211_ATTR_MAC_ADDRS);
+ if (acl == NULL)
+ goto nla_put_failure;
+
+ for (i = 0; i < params->num_mac_acl; i++)
+ NLA_PUT(msg, i + 1, ETH_ALEN, params->mac_acl[i].addr);
+
+ nla_nest_end(msg, acl);
+
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ msg = NULL;
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "nl80211: Failed to set MAC ACL: %d (%s)",
+ ret, strerror(-ret));
+ }
+
+nla_put_failure:
+ nlmsg_free(msg);
+
+ return ret;
+}
+
+
static int wpa_driver_nl80211_set_ap(void *priv,
struct wpa_driver_ap_params *params)
{
@@ -6172,6 +6265,9 @@
params->listen_interval);
NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL,
params->listen_interval);
+ } else if (params->aid && (params->flags & WPA_STA_TDLS_PEER)) {
+ wpa_printf(MSG_DEBUG, " * peer_aid=%u", params->aid);
+ NLA_PUT_U16(msg, NL80211_ATTR_PEER_AID, params->aid);
}
if (params->ht_capabilities) {
wpa_hexdump(MSG_DEBUG, " * ht_capabilities",
@@ -7444,7 +7540,7 @@
return wpa_driver_nl80211_connect(drv, params);
}
- drv->associated = 0;
+ nl80211_mark_disconnected(drv);
msg = nlmsg_alloc();
if (!msg)
@@ -7758,6 +7854,9 @@
struct nl_msg *msg;
struct nl80211_sta_flag_update upd;
+ wpa_printf(MSG_DEBUG, "nl80211: Set supplicant port %sauthorized for "
+ MACSTR, authorized ? "" : "un", MAC2STR(drv->bssid));
+
msg = nlmsg_alloc();
if (!msg)
return -ENOMEM;
@@ -9936,6 +10035,7 @@
.set_supp_port = wpa_driver_nl80211_set_supp_port,
.set_country = wpa_driver_nl80211_set_country,
.set_ap = wpa_driver_nl80211_set_ap,
+ .set_acl = wpa_driver_nl80211_set_acl,
.if_add = wpa_driver_nl80211_if_add,
.if_remove = driver_nl80211_if_remove,
.send_mlme = driver_nl80211_send_mlme,
diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
index d1e48b5..32b060e 100644
--- a/src/drivers/nl80211_copy.h
+++ b/src/drivers/nl80211_copy.h
@@ -27,6 +27,8 @@
#include <linux/types.h>
+#define NL80211_GENL_NAME "nl80211"
+
/**
* DOC: Station handling
*
@@ -1429,6 +1431,11 @@
* @NL80211_ATTR_MAX_CRIT_PROT_DURATION: duration in milliseconds in which
* the connection should have increased reliability (u16).
*
+ * @NL80211_ATTR_PEER_AID: Association ID for the peer TDLS station (u16).
+ * This is similar to @NL80211_ATTR_STA_AID but with a difference of being
+ * allowed to be used with the first @NL80211_CMD_SET_STATION command to
+ * update a TDLS peer STA entry.
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1727,6 +1734,8 @@
NL80211_ATTR_CRIT_PROT_ID,
NL80211_ATTR_MAX_CRIT_PROT_DURATION,
+ NL80211_ATTR_PEER_AID,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -1991,6 +2000,10 @@
* @NL80211_STA_INFO_PEER_PM: peer mesh STA link-specific power mode
* @NL80211_STA_INFO_NONPEER_PM: neighbor mesh STA power save mode towards
* non-peer STA
+ * @NL80211_STA_INFO_CHAIN_SIGNAL: per-chain signal strength of last PPDU
+ * Contains a nested array of signal strength attributes (u8, dBm)
+ * @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average
+ * Same format as NL80211_STA_INFO_CHAIN_SIGNAL.
* @__NL80211_STA_INFO_AFTER_LAST: internal
* @NL80211_STA_INFO_MAX: highest possible station info attribute
*/
@@ -2020,6 +2033,8 @@
NL80211_STA_INFO_NONPEER_PM,
NL80211_STA_INFO_RX_BYTES64,
NL80211_STA_INFO_TX_BYTES64,
+ NL80211_STA_INFO_CHAIN_SIGNAL,
+ NL80211_STA_INFO_CHAIN_SIGNAL_AVG,
/* keep last */
__NL80211_STA_INFO_AFTER_LAST,
@@ -2637,6 +2652,10 @@
* @NL80211_MESH_SETUP_USERSPACE_MPM: Enable this option if userspace will
* implement an MPM which handles peer allocation and state.
*
+ * @NL80211_MESH_SETUP_AUTH_PROTOCOL: Inform the kernel of the authentication
+ * method (u8, as defined in IEEE 8.4.2.100.6, e.g. 0x1 for SAE).
+ * Default is no authentication method required.
+ *
* @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number
*
* @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use
@@ -2650,6 +2669,7 @@
NL80211_MESH_SETUP_USERSPACE_AMPE,
NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC,
NL80211_MESH_SETUP_USERSPACE_MPM,
+ NL80211_MESH_SETUP_AUTH_PROTOCOL,
/* keep last */
__NL80211_MESH_SETUP_ATTR_AFTER_LAST,