Cumulative patch from commit 905828fea4b95a6d48ce86e1b5272c25a618b3d8
905828f hostapd: Fix vht_capab 'Maximum A-MPDU Length Exponent' handling
89de64c ACS: Fix VHT80 segment picking
1f37483 DFS: Print error in case CAC fails
354c903 AP/GO interface teardown optimization
8bc4372 Use P2P_IE_VENDOR_TYPE more consistently
8714caa WPS: Parse Registrar Configuration Methods
6b9f7af nl80211: Extend the new vendor command for testing nl80211
3a94adb P2P: Do not start scan for P2P Device interfaces at driver init
aa10983 P2P: Do not initialize bgscan on P2P interfaces
819f096 nl80211: Fix RTM event handling for dynamic interfaces
54ac5aa config: Add bgscan option when saving global configuration
268043d bgscan: Do not initialize bgscan if disabled by user
adef894 nl80211: Add vendor command support
d0595b2 nl80211: Fix tearing down WDS STA interfaces
Change-Id: I6d49f445692b71a4cd324f517eba651518ee14bb
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/acs.c b/src/ap/acs.c
index f58b091..60b7580 100644
--- a/src/ap/acs.c
+++ b/src/ap/acs.c
@@ -367,6 +367,19 @@
}
+static int acs_usable_vht80_chan(struct hostapd_channel_data *chan)
+{
+ const int allowed[] = { 36, 52, 100, 116, 132, 149 };
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(allowed); i++)
+ if (chan->chan == allowed[i])
+ return 1;
+
+ return 0;
+}
+
+
static int acs_survey_is_sufficient(struct freq_survey *survey)
{
if (!(survey->filled & SURVEY_HAS_NF)) {
@@ -541,6 +554,15 @@
continue;
}
+ if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
+ iface->conf->ieee80211ac &&
+ iface->conf->vht_oper_chwidth == 1 &&
+ !acs_usable_vht80_chan(chan)) {
+ wpa_printf(MSG_DEBUG, "ACS: Channel %d: not allowed as primary channel for VHT80",
+ chan->chan);
+ continue;
+ }
+
factor = 0;
if (acs_usable_chan(chan))
factor = chan->interference_factor;
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index b8b260a..5ba48c9 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -767,8 +767,10 @@
vht_enabled, sec_channel_offset,
vht_oper_chwidth, center_segment0,
center_segment1,
- iface->current_mode->vht_capab))
+ iface->current_mode->vht_capab)) {
+ wpa_printf(MSG_ERROR, "Can't set freq params");
return -1;
+ }
res = hapd->driver->start_dfs_cac(hapd->drv_priv, &data);
if (!res)
diff --git a/src/ap/ap_mlme.c b/src/ap/ap_mlme.c
index a959694..a7129f1 100644
--- a/src/ap/ap_mlme.c
+++ b/src/ap/ap_mlme.c
@@ -16,6 +16,7 @@
#include "wpa_auth.h"
#include "sta_info.h"
#include "ap_mlme.h"
+#include "hostapd.h"
#ifndef CONFIG_NO_HOSTAPD_LOGGER
@@ -80,7 +81,8 @@
HOSTAPD_LEVEL_DEBUG,
"MLME-DEAUTHENTICATE.indication(" MACSTR ", %d)",
MAC2STR(sta->addr), reason_code);
- mlme_deletekeys_request(hapd, sta);
+ if (!hapd->iface->driver_ap_teardown)
+ mlme_deletekeys_request(hapd, sta);
}
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index 8c0cbab..c27cf3b 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -250,9 +250,8 @@
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
*pos++ = 4 + 3 + 1;
- WPA_PUT_BE24(pos, OUI_WFA);
- pos += 3;
- *pos++ = P2P_OUI_TYPE;
+ WPA_PUT_BE32(pos, P2P_IE_VENDOR_TYPE);
+ pos += 4;
*pos++ = P2P_ATTR_MINOR_REASON_CODE;
WPA_PUT_LE16(pos, 1);
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index 2b8b90f..92eda21 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -608,19 +608,25 @@
hostapd_set_state(iface, HAPD_IFACE_DFS);
wpa_printf(MSG_DEBUG, "DFS start CAC on %d MHz", iface->freq);
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START
- "freq=%d chan=%d sec_chan=%d",
+ "freq=%d chan=%d sec_chan=%d, width=%d, seg0=%d, seg1=%d",
iface->freq,
- iface->conf->channel, iface->conf->secondary_channel);
- if (hostapd_start_dfs_cac(iface, iface->conf->hw_mode,
- iface->freq,
- iface->conf->channel,
- iface->conf->ieee80211n,
- iface->conf->ieee80211ac,
- iface->conf->secondary_channel,
- iface->conf->vht_oper_chwidth,
- iface->conf->vht_oper_centr_freq_seg0_idx,
- iface->conf->vht_oper_centr_freq_seg1_idx)) {
- wpa_printf(MSG_DEBUG, "DFS start_dfs_cac() failed");
+ iface->conf->channel, iface->conf->secondary_channel,
+ iface->conf->vht_oper_chwidth,
+ iface->conf->vht_oper_centr_freq_seg0_idx,
+ iface->conf->vht_oper_centr_freq_seg1_idx);
+
+ res = hostapd_start_dfs_cac(iface, iface->conf->hw_mode,
+ iface->freq,
+ iface->conf->channel,
+ iface->conf->ieee80211n,
+ iface->conf->ieee80211ac,
+ iface->conf->secondary_channel,
+ iface->conf->vht_oper_chwidth,
+ iface->conf->vht_oper_centr_freq_seg0_idx,
+ iface->conf->vht_oper_centr_freq_seg1_idx);
+
+ if (res) {
+ wpa_printf(MSG_ERROR, "DFS start_dfs_cac() failed, %d", res);
return -1;
}
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index ad1c2d0..6ba6f98 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -350,7 +350,7 @@
static void hostapd_clear_wep(struct hostapd_data *hapd)
{
- if (hapd->drv_priv) {
+ if (hapd->drv_priv && !hapd->iface->driver_ap_teardown) {
hostapd_set_privacy(hapd, 0);
hostapd_broadcast_wep_clear(hapd);
}
@@ -401,11 +401,15 @@
if (hostapd_drv_none(hapd) || hapd->drv_priv == NULL)
return 0;
- wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "Flushing old station entries");
- if (hostapd_flush(hapd)) {
- wpa_msg(hapd->msg_ctx, MSG_WARNING, "Could not connect to "
- "kernel driver");
- ret = -1;
+ if (!hapd->iface->driver_ap_teardown) {
+ wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
+ "Flushing old station entries");
+
+ if (hostapd_flush(hapd)) {
+ wpa_msg(hapd->msg_ctx, MSG_WARNING,
+ "Could not connect to kernel driver");
+ ret = -1;
+ }
}
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "Deauthenticate all stations");
os_memset(addr, 0xff, ETH_ALEN);
@@ -1009,6 +1013,15 @@
struct hostapd_data *hapd = iface->bss[0];
size_t i;
+ /*
+ * It is possible that setup_interface() is called after the interface
+ * was disabled etc., in which case driver_ap_teardown is possibly set
+ * to 1. Clear it here so any other key/station deletion, which is not
+ * part of a teardown flow, would also call the relevant driver
+ * callbacks.
+ */
+ iface->driver_ap_teardown = 0;
+
if (!iface->phy[0]) {
const char *phy = hostapd_drv_get_radio_name(hapd);
if (phy) {
@@ -1627,7 +1640,11 @@
driver = hapd_iface->bss[0]->driver;
drv_priv = hapd_iface->bss[0]->drv_priv;
- /* whatever hostapd_interface_deinit does */
+ hapd_iface->driver_ap_teardown =
+ !!(hapd_iface->drv_flags &
+ WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
+
+ /* same as hostapd_interface_deinit without deinitializing ctrl-iface */
for (j = 0; j < hapd_iface->num_bss; j++) {
struct hostapd_data *hapd = hapd_iface->bss[j];
hostapd_free_stas(hapd);
@@ -1943,6 +1960,10 @@
return -1;
if (!os_strcmp(hapd_iface->conf->bss[0]->iface, buf)) {
wpa_printf(MSG_INFO, "Remove interface '%s'", buf);
+ hapd_iface->driver_ap_teardown =
+ !!(hapd_iface->drv_flags &
+ WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
+
hostapd_interface_deinit_free(hapd_iface);
k = i;
while (k < (interfaces->count - 1)) {
@@ -1955,8 +1976,12 @@
}
for (j = 0; j < hapd_iface->conf->num_bss; j++) {
- if (!os_strcmp(hapd_iface->conf->bss[j]->iface, buf))
+ if (!os_strcmp(hapd_iface->conf->bss[j]->iface, buf)) {
+ hapd_iface->driver_ap_teardown =
+ !(hapd_iface->drv_flags &
+ WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
return hostapd_remove_bss(hapd_iface, j);
+ }
}
}
return -1;
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 489ab16..be7df51 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -273,6 +273,12 @@
unsigned int wait_channel_update:1;
unsigned int cac_started:1;
+ /*
+ * When set, indicates that the driver will handle the AP
+ * teardown: delete global keys, station keys, and stations.
+ */
+ unsigned int driver_ap_teardown:1;
+
int num_ap; /* number of entries in ap_list */
struct ap_info *ap_list; /* AP info list head */
struct ap_info *ap_hash[STA_HASH_SIZE];
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index af1bc9b..28e92fd 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -764,7 +764,7 @@
VHT_CAP_CHECK(VHT_CAP_MU_BEAMFORMEE_CAPABLE);
VHT_CAP_CHECK(VHT_CAP_VHT_TXOP_PS);
VHT_CAP_CHECK(VHT_CAP_HTC_VHT);
- VHT_CAP_CHECK_MAX(VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT);
+ VHT_CAP_CHECK_MAX(VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX);
VHT_CAP_CHECK(VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB);
VHT_CAP_CHECK(VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB);
VHT_CAP_CHECK(VHT_CAP_RX_ANTENNA_PATTERN);
diff --git a/src/ap/p2p_hostapd.c b/src/ap/p2p_hostapd.c
index 795d313..9be640c 100644
--- a/src/ap/p2p_hostapd.c
+++ b/src/ap/p2p_hostapd.c
@@ -96,9 +96,8 @@
u8 bitmap;
*eid++ = WLAN_EID_VENDOR_SPECIFIC;
*eid++ = 4 + 3 + 1;
- WPA_PUT_BE24(eid, OUI_WFA);
- eid += 3;
- *eid++ = P2P_OUI_TYPE;
+ WPA_PUT_BE32(eid, P2P_IE_VENDOR_TYPE);
+ eid += 4;
*eid++ = P2P_ATTR_MANAGEABILITY;
WPA_PUT_LE16(eid, 1);
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index f7af088..0b90e3b 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -156,7 +156,8 @@
if (sta->flags & WLAN_STA_WDS)
hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0);
- if (!(sta->flags & WLAN_STA_PREAUTH))
+ if (!hapd->iface->driver_ap_teardown &&
+ !(sta->flags & WLAN_STA_PREAUTH))
hostapd_drv_sta_remove(hapd, sta->addr);
ap_sta_hash_del(hapd, sta);
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index cf4664f..dcee679 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -758,7 +758,14 @@
#define VHT_CAP_MU_BEAMFORMEE_CAPABLE ((u32) BIT(20))
#define VHT_CAP_VHT_TXOP_PS ((u32) BIT(21))
#define VHT_CAP_HTC_VHT ((u32) BIT(22))
-#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT ((u32) BIT(23) | \
+
+#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_1 ((u32) BIT(23))
+#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_2 ((u32) BIT(24))
+#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_3 ((u32) BIT(23) | BIT(24))
+#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_4 ((u32) BIT(25))
+#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_5 ((u32) BIT(23) | BIT(25))
+#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_6 ((u32) BIT(24) | BIT(25))
+#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX ((u32) BIT(23) | \
BIT(24) | BIT(25))
#define VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB ((u32) BIT(27))
#define VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB ((u32) BIT(26) | BIT(27))
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index d2aad24..6b6c0ef 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -914,7 +914,8 @@
#define WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE 0x00000400
/* This interface is P2P capable (P2P GO or P2P Client) */
#define WPA_DRIVER_FLAGS_P2P_CAPABLE 0x00000800
-/* unused: 0x00001000 */
+/* Driver supports station and key removal when stopping an AP */
+#define WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT 0x00001000
/*
* Driver uses the initial interface for P2P management interface and non-P2P
* purposes (e.g., connect to infra AP), but this interface cannot be used for
@@ -2520,6 +2521,30 @@
#endif /* ANDROID */
/**
+ * vendor_cmd - Execute vendor specific command
+ * @priv: Private driver interface data
+ * @vendor_id: Vendor id
+ * @subcmd: Vendor command id
+ * @data: Vendor command parameters (%NULL if no parameters)
+ * @data_len: Data length
+ * @buf: Return buffer (%NULL to ignore reply)
+ * Returns: 0 on success, negative (<0) on failure
+ *
+ * This function handles vendor specific commands that are passed to
+ * the driver/device. The command is identified by vendor id and
+ * command id. Parameters can be passed as argument to the command
+ * in the data buffer. Reply (if any) will be filled in the supplied
+ * return buffer.
+ *
+ * The exact driver behavior is driver interface and vendor specific. As
+ * an example, this will be converted to a vendor specific cfg80211
+ * command in case of the nl80211 driver interface.
+ */
+ int (*vendor_cmd)(void *priv, unsigned int vendor_id,
+ unsigned int subcmd, const u8 *data, size_t data_len,
+ struct wpabuf *buf);
+
+ /**
* set_rekey_info - Set rekey information
* @priv: Private driver interface data
* @kek: Current KEK
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index c509170..87c9661 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -1239,6 +1239,16 @@
drv->if_disabled = 1;
wpa_supplicant_event(drv->ctx,
EVENT_INTERFACE_DISABLED, NULL);
+
+ /*
+ * Try to get drv again, since it may be removed as
+ * part of the EVENT_INTERFACE_DISABLED handling for
+ * dynamic interfaces
+ */
+ drv = nl80211_find_drv(global, ifi->ifi_index,
+ buf, len);
+ if (!drv)
+ return;
}
}
@@ -3808,6 +3818,15 @@
drv->capa.flags |= WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE;
drv->capa.flags |= WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
+ /*
+ * As all cfg80211 drivers must support cases where the AP interface is
+ * removed without the knowledge of wpa_supplicant/hostapd, e.g., in
+ * case that the user space daemon has crashed, they must be able to
+ * cleanup all stations and key entries in the AP tear down flow. Thus,
+ * this flag can/should always be set for cfg80211 drivers.
+ */
+ drv->capa.flags |= WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT;
+
if (!info.device_ap_sme) {
drv->capa.flags |= WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS;
@@ -9431,8 +9450,8 @@
name);
i802_set_sta_vlan(priv, addr, bss->ifname, 0);
- return wpa_driver_nl80211_if_remove(priv, WPA_IF_AP_VLAN,
- name);
+ nl80211_remove_iface(drv, if_nametoindex(name));
+ return 0;
}
}
@@ -11710,6 +11729,106 @@
}
+#ifdef CONFIG_TESTING_OPTIONS
+static int cmd_reply_handler(struct nl_msg *msg, void *arg)
+{
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct wpabuf *buf = arg;
+
+ if (!buf)
+ return NL_SKIP;
+
+ if ((size_t) genlmsg_attrlen(gnlh, 0) > wpabuf_tailroom(buf)) {
+ wpa_printf(MSG_INFO, "nl80211: insufficient buffer space for reply");
+ return NL_SKIP;
+ }
+
+ wpabuf_put_data(buf, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0));
+
+ return NL_SKIP;
+}
+#endif /* CONFIG_TESTING_OPTIONS */
+
+
+static int vendor_reply_handler(struct nl_msg *msg, void *arg)
+{
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+ struct nlattr *nl_vendor_reply, *nl;
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct wpabuf *buf = arg;
+ int rem;
+
+ if (!buf)
+ return NL_SKIP;
+
+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+ nl_vendor_reply = tb[NL80211_ATTR_VENDOR_DATA];
+
+ if (!nl_vendor_reply)
+ return NL_SKIP;
+
+ if ((size_t) nla_len(nl_vendor_reply) > wpabuf_tailroom(buf)) {
+ wpa_printf(MSG_INFO, "nl80211: Vendor command: insufficient buffer space for reply");
+ return NL_SKIP;
+ }
+
+ nla_for_each_nested(nl, nl_vendor_reply, rem) {
+ wpabuf_put_data(buf, nla_data(nl), nla_len(nl));
+ }
+
+ return NL_SKIP;
+}
+
+
+static int nl80211_vendor_cmd(void *priv, unsigned int vendor_id,
+ unsigned int subcmd, const u8 *data,
+ size_t data_len, struct wpabuf *buf)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ int ret;
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -ENOMEM;
+
+#ifdef CONFIG_TESTING_OPTIONS
+ if (vendor_id == 0xffffffff) {
+ nl80211_cmd(drv, msg, 0, subcmd);
+ if (nlmsg_append(msg, (void *) data, data_len, NLMSG_ALIGNTO) <
+ 0)
+ goto nla_put_failure;
+ ret = send_and_recv_msgs(drv, msg, cmd_reply_handler, buf);
+ if (ret)
+ wpa_printf(MSG_DEBUG, "nl80211: command failed err=%d",
+ ret);
+ return ret;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+
+ nl80211_cmd(drv, msg, 0, NL80211_CMD_VENDOR);
+ if (nl80211_set_iface_id(msg, bss) < 0)
+ goto nla_put_failure;
+ NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_ID, vendor_id);
+ NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_SUBCMD, subcmd);
+ if (data)
+ NLA_PUT(msg, NL80211_ATTR_VENDOR_DATA, data_len, data);
+
+ ret = send_and_recv_msgs(drv, msg, vendor_reply_handler, buf);
+ if (ret)
+ wpa_printf(MSG_DEBUG, "nl80211: vendor command failed err=%d",
+ ret);
+ return ret;
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return -ENOBUFS;
+}
+
+
static int nl80211_set_qos_map(void *priv, const u8 *qos_map_set,
u8 qos_map_set_len)
{
@@ -11829,5 +11948,6 @@
#ifdef ANDROID
.driver_cmd = wpa_driver_nl80211_driver_cmd,
#endif /* ANDROID */
+ .vendor_cmd = nl80211_vendor_cmd,
.set_qos_map = nl80211_set_qos_map,
};
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 4b90989..c5bf41f 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -1660,20 +1660,15 @@
case WLAN_PA_VENDOR_SPECIFIC:
data++;
len--;
- if (len < 3)
+ if (len < 4)
return;
- if (WPA_GET_BE24(data) != OUI_WFA)
+ if (WPA_GET_BE32(data) != P2P_IE_VENDOR_TYPE)
return;
- data += 3;
- len -= 3;
- if (len < 1)
- return;
+ data += 4;
+ len -= 4;
- if (*data != P2P_OUI_TYPE)
- return;
-
- p2p_rx_p2p_action(p2p, sa, data + 1, len - 1, freq);
+ p2p_rx_p2p_action(p2p, sa, data, len, freq);
break;
case WLAN_PA_GAS_INITIAL_REQ:
p2p_rx_gas_initial_req(p2p, sa, data + 1, len - 1, freq);
@@ -1706,15 +1701,10 @@
if (len < 4)
return;
- if (WPA_GET_BE24(data) != OUI_WFA)
+ if (WPA_GET_BE32(data) != P2P_IE_VENDOR_TYPE)
return;
- data += 3;
- len -= 3;
-
- if (*data != P2P_OUI_TYPE)
- return;
- data++;
- len--;
+ data += 4;
+ len -= 4;
/* P2P action frame */
p2p_dbg(p2p, "RX P2P Action from " MACSTR, MAC2STR(sa));
diff --git a/src/p2p/p2p_build.c b/src/p2p/p2p_build.c
index 664fade..e9b683d 100644
--- a/src/p2p/p2p_build.c
+++ b/src/p2p/p2p_build.c
@@ -17,8 +17,7 @@
void p2p_buf_add_action_hdr(struct wpabuf *buf, u8 subtype, u8 dialog_token)
{
wpabuf_put_u8(buf, WLAN_ACTION_VENDOR_SPECIFIC);
- wpabuf_put_be24(buf, OUI_WFA);
- wpabuf_put_u8(buf, P2P_OUI_TYPE);
+ wpabuf_put_be32(buf, P2P_IE_VENDOR_TYPE);
wpabuf_put_u8(buf, subtype); /* OUI Subtype */
wpabuf_put_u8(buf, dialog_token);
@@ -31,8 +30,7 @@
{
wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
wpabuf_put_u8(buf, WLAN_PA_VENDOR_SPECIFIC);
- wpabuf_put_be24(buf, OUI_WFA);
- wpabuf_put_u8(buf, P2P_OUI_TYPE);
+ wpabuf_put_be32(buf, P2P_IE_VENDOR_TYPE);
wpabuf_put_u8(buf, subtype); /* OUI Subtype */
wpabuf_put_u8(buf, dialog_token);
@@ -47,8 +45,7 @@
/* P2P IE header */
wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
len = wpabuf_put(buf, 1); /* IE length to be filled */
- wpabuf_put_be24(buf, OUI_WFA);
- wpabuf_put_u8(buf, P2P_OUI_TYPE);
+ wpabuf_put_be32(buf, P2P_IE_VENDOR_TYPE);
wpa_printf(MSG_DEBUG, "P2P: * P2P IE header");
return len;
}
diff --git a/src/p2p/p2p_sd.c b/src/p2p/p2p_sd.c
index 26b9c2d..9df834c 100644
--- a/src/p2p/p2p_sd.c
+++ b/src/p2p/p2p_sd.c
@@ -171,8 +171,7 @@
/* ANQP Query Request Frame */
len_pos = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
- wpabuf_put_be24(buf, OUI_WFA);
- wpabuf_put_u8(buf, P2P_OUI_TYPE);
+ wpabuf_put_be32(buf, P2P_IE_VENDOR_TYPE);
wpabuf_put_le16(buf, update_indic); /* Service Update Indicator */
wpabuf_put_buf(buf, tlvs);
gas_anqp_set_element_len(buf, len_pos);
@@ -218,8 +217,7 @@
if (tlvs) {
/* ANQP Query Response Frame */
len_pos = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
- wpabuf_put_be24(buf, OUI_WFA);
- wpabuf_put_u8(buf, P2P_OUI_TYPE);
+ wpabuf_put_be32(buf, P2P_IE_VENDOR_TYPE);
/* Service Update Indicator */
wpabuf_put_le16(buf, update_indic);
wpabuf_put_buf(buf, tlvs);
@@ -250,8 +248,7 @@
/* ANQP Query Response Frame */
wpabuf_put_le16(buf, ANQP_VENDOR_SPECIFIC); /* Info ID */
wpabuf_put_le16(buf, 3 + 1 + 2 + total_len);
- wpabuf_put_be24(buf, OUI_WFA);
- wpabuf_put_u8(buf, P2P_OUI_TYPE);
+ wpabuf_put_be32(buf, P2P_IE_VENDOR_TYPE);
/* Service Update Indicator */
wpabuf_put_le16(buf, update_indic);
}
@@ -393,17 +390,12 @@
return;
}
- if (WPA_GET_BE24(pos) != OUI_WFA) {
- p2p_dbg(p2p, "Unsupported ANQP OUI %06x", WPA_GET_BE24(pos));
+ if (WPA_GET_BE32(pos) != P2P_IE_VENDOR_TYPE) {
+ p2p_dbg(p2p, "Unsupported ANQP vendor OUI-type %08x",
+ WPA_GET_BE32(pos));
return;
}
- pos += 3;
-
- if (*pos != P2P_OUI_TYPE) {
- p2p_dbg(p2p, "Unsupported ANQP vendor type %u", *pos);
- return;
- }
- pos++;
+ pos += 4;
if (pos + 2 > end)
return;
@@ -571,17 +563,12 @@
return;
}
- if (WPA_GET_BE24(pos) != OUI_WFA) {
- p2p_dbg(p2p, "Unsupported ANQP OUI %06x", WPA_GET_BE24(pos));
+ if (WPA_GET_BE32(pos) != P2P_IE_VENDOR_TYPE) {
+ p2p_dbg(p2p, "Unsupported ANQP vendor OUI-type %08x",
+ WPA_GET_BE32(pos));
return;
}
- pos += 3;
-
- if (*pos != P2P_OUI_TYPE) {
- p2p_dbg(p2p, "Unsupported ANQP vendor type %u", *pos);
- return;
- }
- pos++;
+ pos += 4;
if (pos + 2 > end)
return;
@@ -795,17 +782,12 @@
if (pos + 4 > end)
return;
- if (WPA_GET_BE24(pos) != OUI_WFA) {
- p2p_dbg(p2p, "Unsupported ANQP OUI %06x", WPA_GET_BE24(pos));
+ if (WPA_GET_BE32(pos) != P2P_IE_VENDOR_TYPE) {
+ p2p_dbg(p2p, "Unsupported ANQP vendor OUI-type %08x",
+ WPA_GET_BE32(pos));
return;
}
- pos += 3;
-
- if (*pos != P2P_OUI_TYPE) {
- p2p_dbg(p2p, "Unsupported ANQP vendor type %u", *pos);
- return;
- }
- pos++;
+ pos += 4;
if (pos + 2 > end)
return;
diff --git a/src/wps/wps_attr_parse.c b/src/wps/wps_attr_parse.c
index 1ebcfe9..40bc1ad 100644
--- a/src/wps/wps_attr_parse.c
+++ b/src/wps/wps_attr_parse.c
@@ -59,6 +59,14 @@
}
attr->settings_delay_time = pos;
break;
+ case WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS:
+ if (len != 2) {
+ wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Configuration Methods length %u",
+ len);
+ return -1;
+ }
+ attr->registrar_configuration_methods = pos;
+ break;
default:
wpa_printf(MSG_MSGDUMP, "WPS: Skipped unknown WFA Vendor "
"Extension subelement %u", id);
diff --git a/src/wps/wps_attr_parse.h b/src/wps/wps_attr_parse.h
index eeb08d1..82c4739 100644
--- a/src/wps/wps_attr_parse.h
+++ b/src/wps/wps_attr_parse.h
@@ -55,6 +55,7 @@
const u8 *network_key_shareable; /* 1 octet (Bool) */
const u8 *request_to_enroll; /* 1 octet (Bool) */
const u8 *ap_channel; /* 2 octets */
+ const u8 *registrar_configuration_methods; /* 2 octets */
/* variable length fields */
const u8 *manufacturer;
diff --git a/src/wps/wps_defs.h b/src/wps/wps_defs.h
index 6f8a49f..e125048 100644
--- a/src/wps/wps_defs.h
+++ b/src/wps/wps_defs.h
@@ -146,7 +146,8 @@
WFA_ELEM_AUTHORIZEDMACS = 0x01,
WFA_ELEM_NETWORK_KEY_SHAREABLE = 0x02,
WFA_ELEM_REQUEST_TO_ENROLL = 0x03,
- WFA_ELEM_SETTINGS_DELAY_TIME = 0x04
+ WFA_ELEM_SETTINGS_DELAY_TIME = 0x04,
+ WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS = 0x05
};
/* Device Password ID */