Cumulative patch from commit 01a025937c67f0eca6021d94b8ec3b144f8b1730
01a0259 WPS: Add support for 60 GHz band
0ef1e29 WPS: Fix shorter authentication timeout during no-SelReg iteration
3465176 nl80211: Verify that cipher suite conversion succeeds
a250722 Try to set PMK only with key mgmt offload support in the driver
4a7ce98 Make IPv6 NA multicast-to-unicast conversion configurable
9f390f4 Interworking: Fix network selection warning without SIM/USIM support
a0ad9e8 Remove WPA per-VLAN groups when no more stations remain
87b5b53 Make VLAN ID available in STA info over control interface
5678a2d P2P: Allow wpa_supplicant to start if social channels are not supported
209214b vlan: Move CONFIG_FULL_DYNAMIC_VLAN includes to proper places
a6da824 Do not use C++ reserved words as variable names
eaa3728 wpa_gui: Themed icon loader
9a3cb41 Fix wpa_priv (CONFIG_PRIVSEP=y) build
8b423ed Declare all read only data structures as const
fd4fb28 OpenSSL: Try to ensure we don't throw away the PIN unnecessarily
fabc6dd mesh: Retransmit the last Commit Message in the Committed state
068669f vlan: Verify RADIUS returned VLAN-ID and dynamic_vlan=required
5add410 WPS: Use shorter authentication timeout during no-SelReg iteration
e7d2034 WPS: Enforce five second minimum time before AP iteration
bd143cc Remove trailing whitespace from Makefile
74802c0 P2P: Do not create a P2P Device interface if P2P is disabled
579674e Document p2p_disabled option in wpa_supplicant.conf
8ea8a89 nl80211: Extend unique MAC address assignment for station iftype
Change-Id: I8bc8a63f37c0892b83376b9d5a5859827ae50554
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index cccbfab..c44f70d 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -819,9 +819,9 @@
if (full_config && bss->wps_state && bss->wpa &&
(!(bss->wpa & 2) ||
- !(bss->rsn_pairwise & WPA_CIPHER_CCMP))) {
+ !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)))) {
wpa_printf(MSG_INFO, "WPS: WPA/TKIP configuration without "
- "WPA2/CCMP forced WPS to be disabled");
+ "WPA2/CCMP/GCMP forced WPS to be disabled");
bss->wps_state = 0;
}
#endif /* CONFIG_WPS */
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 7b4a7ea..c3573a4 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -490,6 +490,7 @@
int osen;
int proxy_arp;
+ int na_mcast_to_ucast;
#ifdef CONFIG_HS20
int hs20;
int disable_dgaf;
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index 41ab988..60afcb0 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -153,6 +153,13 @@
}
#endif /* CONFIG_SAE */
+ if (sta->vlan_id > 0) {
+ res = os_snprintf(buf + len, buflen - len, "vlan_id=%d\n",
+ sta->vlan_id);
+ if (!os_snprintf_error(buflen - len, res))
+ len += res;
+ }
+
return len;
}
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 5b26558..9e7d70d 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -609,7 +609,7 @@
return WLAN_STATUS_SUCCESS;
sta->sae->sync++;
- ret = auth_sae_send_commit(hapd, sta, bssid, 1);
+ ret = auth_sae_send_commit(hapd, sta, bssid, 0);
if (ret)
return ret;
diff --git a/src/ap/ieee802_11_auth.c b/src/ap/ieee802_11_auth.c
index 56c3ce0..0238257 100644
--- a/src/ap/ieee802_11_auth.c
+++ b/src/ap/ieee802_11_auth.c
@@ -561,6 +561,19 @@
if (hapd->conf->wpa_psk_radius == PSK_RADIUS_REQUIRED &&
!cache->psk)
cache->accepted = HOSTAPD_ACL_REJECT;
+
+ if (cache->vlan_id &&
+ !hostapd_vlan_id_valid(hapd->conf->vlan, cache->vlan_id)) {
+ hostapd_logger(hapd, query->addr,
+ HOSTAPD_MODULE_RADIUS,
+ HOSTAPD_LEVEL_INFO,
+ "Invalid VLAN ID %d received from RADIUS server",
+ cache->vlan_id);
+ cache->vlan_id = 0;
+ }
+ if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_REQUIRED &&
+ !cache->vlan_id)
+ cache->accepted = HOSTAPD_ACL_REJECT;
} else
cache->accepted = HOSTAPD_ACL_REJECT;
cache->next = hapd->acl_cache;
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index 863a539..ef26834 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -1285,7 +1285,7 @@
struct sta_info *sta,
struct radius_msg *msg)
{
- u8 *class;
+ u8 *attr_class;
size_t class_len;
struct eapol_state_machine *sm = sta->eapol_sm;
int count, i;
@@ -1307,12 +1307,12 @@
nclass_count = 0;
- class = NULL;
+ attr_class = NULL;
for (i = 0; i < count; i++) {
do {
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CLASS,
- &class, &class_len,
- class) < 0) {
+ &attr_class, &class_len,
+ attr_class) < 0) {
i = count;
break;
}
@@ -1322,7 +1322,7 @@
if (nclass[nclass_count].data == NULL)
break;
- os_memcpy(nclass[nclass_count].data, class, class_len);
+ os_memcpy(nclass[nclass_count].data, attr_class, class_len);
nclass[nclass_count].len = class_len;
nclass_count++;
}
@@ -2342,9 +2342,9 @@
}
-static const char * bool_txt(Boolean bool)
+static const char * bool_txt(Boolean val)
{
- return bool ? "TRUE" : "FALSE";
+ return val ? "TRUE" : "FALSE";
}
diff --git a/src/ap/ndisc_snoop.c b/src/ap/ndisc_snoop.c
index b0d42dc..0adcc97 100644
--- a/src/ap/ndisc_snoop.c
+++ b/src/ap/ndisc_snoop.c
@@ -81,6 +81,18 @@
}
+static void ucast_to_stas(struct hostapd_data *hapd, const u8 *buf, size_t len)
+{
+ struct sta_info *sta;
+
+ for (sta = hapd->sta_list; sta; sta = sta->next) {
+ if (!(sta->flags & WLAN_STA_AUTHORIZED))
+ continue;
+ x_snoop_mcast_to_ucast_convert_send(hapd, sta, (u8 *) buf, len);
+ }
+}
+
+
static void handle_ndisc(void *ctx, const u8 *src_addr, const u8 *buf,
size_t len)
{
@@ -133,16 +145,12 @@
}
break;
case ROUTER_ADVERTISEMENT:
- if (!hapd->conf->disable_dgaf)
- return;
- /* fall through */
+ if (hapd->conf->disable_dgaf)
+ ucast_to_stas(hapd, buf, len);
+ break;
case NEIGHBOR_ADVERTISEMENT:
- for (sta = hapd->sta_list; sta; sta = sta->next) {
- if (!(sta->flags & WLAN_STA_AUTHORIZED))
- continue;
- x_snoop_mcast_to_ucast_convert_send(hapd, sta,
- (u8 *) buf, len);
- }
+ if (hapd->conf->na_mcast_to_ucast)
+ ucast_to_stas(hapd, buf, len);
break;
default:
break;
diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c
index baabbe3..b89a1f4 100644
--- a/src/ap/vlan_init.c
+++ b/src/ap/vlan_init.c
@@ -9,6 +9,13 @@
*/
#include "utils/includes.h"
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <linux/sockios.h>
+#include <linux/if_vlan.h>
+#include <linux/if_bridge.h>
+#endif /* CONFIG_FULL_DYNAMIC_VLAN */
#include "utils/common.h"
#include "hostapd.h"
@@ -20,12 +27,6 @@
#ifdef CONFIG_FULL_DYNAMIC_VLAN
-#include <net/if.h>
-#include <sys/ioctl.h>
-#include <linux/sockios.h>
-#include <linux/if_vlan.h>
-#include <linux/if_bridge.h>
-
#include "drivers/priv_netlink.h"
#include "utils/eloop.h"
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index b83b460..f23a57a 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -45,6 +45,12 @@
struct wpa_group *group);
static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
const u8 *pmk, struct wpa_ptk *ptk);
+static void wpa_group_free(struct wpa_authenticator *wpa_auth,
+ struct wpa_group *group);
+static void wpa_group_get(struct wpa_authenticator *wpa_auth,
+ struct wpa_group *group);
+static void wpa_group_put(struct wpa_authenticator *wpa_auth,
+ struct wpa_group *group);
static const u32 dot11RSNAConfigGroupUpdateCount = 4;
static const u32 dot11RSNAConfigPairwiseUpdateCount = 4;
@@ -262,15 +268,22 @@
static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_authenticator *wpa_auth = eloop_ctx;
- struct wpa_group *group;
+ struct wpa_group *group, *next;
wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "rekeying GTK");
- for (group = wpa_auth->group; group; group = group->next) {
+ group = wpa_auth->group;
+ while (group) {
+ wpa_group_get(wpa_auth, group);
+
group->GTKReKey = TRUE;
do {
group->changed = FALSE;
wpa_group_sm_step(wpa_auth, group);
} while (group->changed);
+
+ next = group->next;
+ wpa_group_put(wpa_auth, group);
+ group = next;
}
if (wpa_auth->conf.wpa_group_rekey) {
@@ -573,6 +586,7 @@
sm->wpa_auth = wpa_auth;
sm->group = wpa_auth->group;
+ wpa_group_get(sm->wpa_auth, sm->group);
return sm;
}
@@ -651,6 +665,7 @@
#endif /* CONFIG_IEEE80211R */
os_free(sm->last_rx_eapol_key);
os_free(sm->wpa_ie);
+ wpa_group_put(sm->wpa_auth, sm->group);
os_free(sm);
}
@@ -2994,9 +3009,9 @@
}
-static const char * wpa_bool_txt(int bool)
+static const char * wpa_bool_txt(int val)
{
- return bool ? "TRUE" : "FALSE";
+ return val ? "TRUE" : "FALSE";
}
@@ -3281,6 +3296,63 @@
}
+/*
+ * Remove and free the group from wpa_authenticator. This is triggered by a
+ * callback to make sure nobody is currently iterating the group list while it
+ * gets modified.
+ */
+static void wpa_group_free(struct wpa_authenticator *wpa_auth,
+ struct wpa_group *group)
+{
+ struct wpa_group *prev = wpa_auth->group;
+
+ wpa_printf(MSG_DEBUG, "WPA: Remove group state machine for VLAN-ID %d",
+ group->vlan_id);
+
+ while (prev) {
+ if (prev->next == group) {
+ /* This never frees the special first group as needed */
+ prev->next = group->next;
+ os_free(group);
+ break;
+ }
+ prev = prev->next;
+ }
+
+}
+
+
+/* Increase the reference counter for group */
+static void wpa_group_get(struct wpa_authenticator *wpa_auth,
+ struct wpa_group *group)
+{
+ /* Skip the special first group */
+ if (wpa_auth->group == group)
+ return;
+
+ group->references++;
+}
+
+
+/* Decrease the reference counter and maybe free the group */
+static void wpa_group_put(struct wpa_authenticator *wpa_auth,
+ struct wpa_group *group)
+{
+ /* Skip the special first group */
+ if (wpa_auth->group == group)
+ return;
+
+ group->references--;
+ if (group->references)
+ return;
+ wpa_group_free(wpa_auth, group);
+}
+
+
+/*
+ * Add a group that has its references counter set to zero. Caller needs to
+ * call wpa_group_get() on the return value to mark the entry in use.
+ */
static struct wpa_group *
wpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id)
{
@@ -3331,7 +3403,10 @@
wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR " to use group state "
"machine for VLAN ID %d", MAC2STR(sm->addr), vlan_id);
+ wpa_group_get(sm->wpa_auth, group);
+ wpa_group_put(sm->wpa_auth, sm->group);
sm->group = group;
+
return 0;
}
diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h
index 7b2cd3e..57b098f 100644
--- a/src/ap/wpa_auth_i.h
+++ b/src/ap/wpa_auth_i.h
@@ -169,6 +169,8 @@
u8 IGTK[2][WPA_IGTK_MAX_LEN];
int GN_igtk, GM_igtk;
#endif /* CONFIG_IEEE80211W */
+ /* Number of references except those in struct wpa_group->next */
+ unsigned int references;
};
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index 68eaeca..caed01e 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -347,8 +347,12 @@
bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
bss->wpa_pairwise = 0;
- if (cred->encr_type & WPS_ENCR_AES)
- bss->wpa_pairwise |= WPA_CIPHER_CCMP;
+ if (cred->encr_type & WPS_ENCR_AES) {
+ if (hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211AD)
+ bss->wpa_pairwise |= WPA_CIPHER_GCMP;
+ else
+ bss->wpa_pairwise |= WPA_CIPHER_CCMP;
+ }
if (cred->encr_type & WPS_ENCR_TKIP)
bss->wpa_pairwise |= WPA_CIPHER_TKIP;
bss->rsn_pairwise = bss->wpa_pairwise;
@@ -530,7 +534,11 @@
fprintf(nconf, "wpa_pairwise=");
prefix = "";
if (cred->encr_type & WPS_ENCR_AES) {
- fprintf(nconf, "CCMP");
+ if (hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211AD)
+ fprintf(nconf, "GCMP");
+ else
+ fprintf(nconf, "CCMP");
+
prefix = " ";
}
if (cred->encr_type & WPS_ENCR_TKIP) {
@@ -844,7 +852,9 @@
struct hostapd_data *hapd = ctx;
return hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ?
- WPS_RF_50GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */
+ WPS_RF_50GHZ :
+ hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211AD ?
+ WPS_RF_60GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */
}
@@ -1041,7 +1051,9 @@
} else {
wps->dev.rf_bands =
hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ?
- WPS_RF_50GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */
+ WPS_RF_50GHZ :
+ hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211AD ?
+ WPS_RF_60GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */
}
if (conf->wpa & WPA_PROTO_RSN) {