Cumulative patch from commit 6d00ab04302df257cb3092b2b31b4eac42e77569
6d00ab0 nl80211: Ensure nl_preq unregistration on driver deinit
71a0e39 P2P: Make unrecognized vendor elements available in P2P_PEER
86bd36f Add generic mechanism for adding vendor elements into frames
Change-Id: I392072a37d8dbfc92769082b60f052f7095466b6
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index b8e9254..6de71e9 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -809,6 +809,7 @@
#define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs)
* 00:50:F2 */
#define WPA_IE_VENDOR_TYPE 0x0050f201
+#define WMM_IE_VENDOR_TYPE 0x0050f202
#define WPS_IE_VENDOR_TYPE 0x0050f204
#define OUI_WFA 0x506f9a
#define P2P_IE_VENDOR_TYPE 0x506f9a09
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index 534bc99..d91594e 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -239,6 +239,25 @@
#define WPA_BSS_MASK_DELIM BIT(17)
+/* VENDOR_ELEM_* frame id values */
+enum wpa_vendor_elem_frame {
+ VENDOR_ELEM_PROBE_REQ_P2P = 0,
+ VENDOR_ELEM_PROBE_RESP_P2P = 1,
+ VENDOR_ELEM_PROBE_RESP_P2P_GO = 2,
+ VENDOR_ELEM_BEACON_P2P_GO = 3,
+ VENDOR_ELEM_P2P_PD_REQ = 4,
+ VENDOR_ELEM_P2P_PD_RESP = 5,
+ VENDOR_ELEM_P2P_GO_NEG_REQ = 6,
+ VENDOR_ELEM_P2P_GO_NEG_RESP = 7,
+ VENDOR_ELEM_P2P_GO_NEG_CONF = 8,
+ VENDOR_ELEM_P2P_INV_REQ = 9,
+ VENDOR_ELEM_P2P_INV_RESP = 10,
+ VENDOR_ELEM_P2P_ASSOC_REQ = 11,
+ VENDOR_ELEM_P2P_ASSOC_RESP = 12,
+ NUM_VENDOR_ELEM_FRAMES
+};
+
+
/* wpa_supplicant/hostapd control interface access */
/**
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 4d5da94..683123b 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -10566,7 +10566,7 @@
if (!report) {
if (bss->nl_preq && drv->device_ap_sme &&
- is_ap_interface(drv->nlmode)) {
+ is_ap_interface(drv->nlmode) && !bss->in_deinit) {
/*
* Do not disable Probe Request reporting that was
* enabled in nl80211_setup_ap().
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 48f3aa6..565cbdb 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -12,6 +12,7 @@
#include "eloop.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
+#include "common/wpa_ctrl.h"
#include "wps/wps_i.h"
#include "p2p_i.h"
#include "p2p.h"
@@ -608,6 +609,46 @@
}
+static void p2p_update_peer_vendor_elems(struct p2p_device *dev, const u8 *ies,
+ size_t ies_len)
+{
+ const u8 *pos, *end;
+ u8 id, len;
+
+ wpabuf_free(dev->info.vendor_elems);
+ dev->info.vendor_elems = NULL;
+
+ end = ies + ies_len;
+
+ for (pos = ies; pos + 1 < end; pos += len) {
+ id = *pos++;
+ len = *pos++;
+
+ if (pos + len > end)
+ break;
+
+ if (id != WLAN_EID_VENDOR_SPECIFIC || len < 3)
+ continue;
+
+ if (len >= 4) {
+ u32 type = WPA_GET_BE32(pos);
+
+ if (type == WPA_IE_VENDOR_TYPE ||
+ type == WMM_IE_VENDOR_TYPE ||
+ type == WPS_IE_VENDOR_TYPE ||
+ type == P2P_IE_VENDOR_TYPE ||
+ type == WFD_IE_VENDOR_TYPE)
+ continue;
+ }
+
+ /* Unknown vendor element - make raw IE data available */
+ if (wpabuf_resize(&dev->info.vendor_elems, 2 + len) < 0)
+ break;
+ wpabuf_put_data(dev->info.vendor_elems, pos - 2, 2 + len);
+ }
+}
+
+
/**
* p2p_add_device - Add peer entries based on scan results or P2P frames
* @p2p: P2P module context from p2p_init()
@@ -756,6 +797,8 @@
p2p_parse_free(&msg);
+ p2p_update_peer_vendor_elems(dev, ies, ies_len);
+
if (dev->flags & P2P_DEV_REPORTED)
return 0;
@@ -825,6 +868,7 @@
}
wpabuf_free(dev->info.wfd_subelems);
+ wpabuf_free(dev->info.vendor_elems);
wpabuf_free(dev->go_neg_conf);
os_free(dev);
@@ -1957,6 +2001,9 @@
extra = wpabuf_len(p2p->wfd_ie_probe_resp);
#endif /* CONFIG_WIFI_DISPLAY */
+ if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_PROBE_RESP_P2P])
+ extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_PROBE_RESP_P2P]);
+
buf = wpabuf_alloc(1000 + extra);
if (buf == NULL)
return NULL;
@@ -1977,6 +2024,10 @@
wpabuf_put_buf(buf, p2p->wfd_ie_probe_resp);
#endif /* CONFIG_WIFI_DISPLAY */
+ if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_PROBE_RESP_P2P])
+ wpabuf_put_buf(buf,
+ p2p->vendor_elem[VENDOR_ELEM_PROBE_RESP_P2P]);
+
/* P2P IE */
len = p2p_buf_add_ie_hdr(buf);
p2p_buf_add_capability(buf, p2p->dev_capab &
@@ -2252,6 +2303,9 @@
extra = wpabuf_len(p2p->wfd_ie_assoc_req);
#endif /* CONFIG_WIFI_DISPLAY */
+ if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_REQ])
+ extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_REQ]);
+
/*
* (Re)Association Request - P2P IE
* P2P Capability attribute (shall be present)
@@ -2267,6 +2321,10 @@
wpabuf_put_buf(tmp, p2p->wfd_ie_assoc_req);
#endif /* CONFIG_WIFI_DISPLAY */
+ if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_REQ])
+ wpabuf_put_buf(tmp,
+ p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_REQ]);
+
peer = bssid ? p2p_get_device(p2p, bssid) : NULL;
lpos = p2p_buf_add_ie_hdr(tmp);
@@ -2854,6 +2912,10 @@
wpabuf_put_buf(ies, p2p->wfd_ie_probe_req);
#endif /* CONFIG_WIFI_DISPLAY */
+ if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_PROBE_REQ_P2P])
+ wpabuf_put_buf(ies,
+ p2p->vendor_elem[VENDOR_ELEM_PROBE_REQ_P2P]);
+
len = p2p_buf_add_ie_hdr(ies);
p2p_buf_add_capability(ies, p2p->dev_capab &
~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 0);
@@ -2880,6 +2942,10 @@
len += wpabuf_len(p2p->wfd_ie_probe_req);
#endif /* CONFIG_WIFI_DISPLAY */
+ if (p2p && p2p->vendor_elem &&
+ p2p->vendor_elem[VENDOR_ELEM_PROBE_REQ_P2P])
+ len += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_PROBE_REQ_P2P]);
+
return len;
}
@@ -4742,3 +4808,9 @@
p2p->cfg->passphrase_len = len;
return 0;
}
+
+
+void p2p_set_vendor_elems(struct p2p_data *p2p, struct wpabuf **vendor_elem)
+{
+ p2p->vendor_elem = vendor_elem;
+}
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 16500a8..dee79df 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -230,6 +230,14 @@
* wfd_subelems - Wi-Fi Display subelements from WFD IE(s)
*/
struct wpabuf *wfd_subelems;
+
+ /**
+ * vendor_elems - Unrecognized vendor elements
+ *
+ * This buffer includes any other vendor element than P2P, WPS, and WFD
+ * IE(s) from the frame that was used to discover the peer.
+ */
+ struct wpabuf *vendor_elems;
};
enum p2p_prov_disc_status {
@@ -1995,4 +2003,6 @@
void *user_data),
void *user_data);
+void p2p_set_vendor_elems(struct p2p_data *p2p, struct wpabuf **vendor_elem);
+
#endif /* P2P_H */
diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c
index f24fe23..bd7a2cf 100644
--- a/src/p2p/p2p_go_neg.c
+++ b/src/p2p/p2p_go_neg.c
@@ -10,6 +10,7 @@
#include "common.h"
#include "common/ieee802_11_defs.h"
+#include "common/wpa_ctrl.h"
#include "wps/wps_defs.h"
#include "p2p_i.h"
#include "p2p.h"
@@ -142,6 +143,9 @@
extra = wpabuf_len(p2p->wfd_ie_go_neg);
#endif /* CONFIG_WIFI_DISPLAY */
+ if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_REQ])
+ extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_REQ]);
+
buf = wpabuf_alloc(1000 + extra);
if (buf == NULL)
return NULL;
@@ -191,6 +195,9 @@
wpabuf_put_buf(buf, p2p->wfd_ie_go_neg);
#endif /* CONFIG_WIFI_DISPLAY */
+ if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_REQ])
+ wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_REQ]);
+
return buf;
}
@@ -268,6 +275,9 @@
extra = wpabuf_len(p2p->wfd_ie_go_neg);
#endif /* CONFIG_WIFI_DISPLAY */
+ if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_RESP])
+ extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_RESP]);
+
buf = wpabuf_alloc(1000 + extra);
if (buf == NULL)
return NULL;
@@ -336,6 +346,8 @@
wpabuf_put_buf(buf, p2p->wfd_ie_go_neg);
#endif /* CONFIG_WIFI_DISPLAY */
+ if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_RESP])
+ wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_RESP]);
return buf;
}
@@ -844,6 +856,9 @@
extra = wpabuf_len(p2p->wfd_ie_go_neg);
#endif /* CONFIG_WIFI_DISPLAY */
+ if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_CONF])
+ extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_CONF]);
+
buf = wpabuf_alloc(1000 + extra);
if (buf == NULL)
return NULL;
@@ -888,6 +903,9 @@
wpabuf_put_buf(buf, p2p->wfd_ie_go_neg);
#endif /* CONFIG_WIFI_DISPLAY */
+ if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_CONF])
+ wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_GO_NEG_CONF]);
+
return buf;
}
diff --git a/src/p2p/p2p_group.c b/src/p2p/p2p_group.c
index aa075bd..da8588a 100644
--- a/src/p2p/p2p_group.c
+++ b/src/p2p/p2p_group.c
@@ -11,6 +11,7 @@
#include "common.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
+#include "common/wpa_ctrl.h"
#include "wps/wps_defs.h"
#include "wps/wps_i.h"
#include "p2p_i.h"
@@ -214,6 +215,10 @@
extra = wpabuf_len(group->p2p->wfd_ie_beacon);
#endif /* CONFIG_WIFI_DISPLAY */
+ if (group->p2p->vendor_elem &&
+ group->p2p->vendor_elem[VENDOR_ELEM_BEACON_P2P_GO])
+ extra += wpabuf_len(group->p2p->vendor_elem[VENDOR_ELEM_BEACON_P2P_GO]);
+
ie = wpabuf_alloc(257 + extra);
if (ie == NULL)
return NULL;
@@ -223,6 +228,11 @@
wpabuf_put_buf(ie, group->p2p->wfd_ie_beacon);
#endif /* CONFIG_WIFI_DISPLAY */
+ if (group->p2p->vendor_elem &&
+ group->p2p->vendor_elem[VENDOR_ELEM_BEACON_P2P_GO])
+ wpabuf_put_buf(ie,
+ group->p2p->vendor_elem[VENDOR_ELEM_BEACON_P2P_GO]);
+
len = p2p_buf_add_ie_hdr(ie);
p2p_group_add_common_ies(group, ie);
p2p_buf_add_device_id(ie, group->p2p->cfg->dev_addr);
@@ -448,6 +458,13 @@
ie = p2p_group_encaps_probe_resp(p2p_subelems);
wpabuf_free(p2p_subelems);
+ if (group->p2p->vendor_elem &&
+ group->p2p->vendor_elem[VENDOR_ELEM_PROBE_RESP_P2P_GO]) {
+ struct wpabuf *extra;
+ extra = wpabuf_dup(group->p2p->vendor_elem[VENDOR_ELEM_PROBE_RESP_P2P_GO]);
+ ie = wpabuf_concat(extra, ie);
+ }
+
#ifdef CONFIG_WIFI_DISPLAY
if (group->wfd_ie) {
struct wpabuf *wfd = wpabuf_dup(group->wfd_ie);
@@ -634,6 +651,10 @@
extra = wpabuf_len(group->wfd_ie);
#endif /* CONFIG_WIFI_DISPLAY */
+ if (group->p2p->vendor_elem &&
+ group->p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_RESP])
+ extra += wpabuf_len(group->p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_RESP]);
+
/*
* (Re)Association Response - P2P IE
* Status attribute (shall be present when association request is
@@ -649,6 +670,11 @@
wpabuf_put_buf(resp, group->wfd_ie);
#endif /* CONFIG_WIFI_DISPLAY */
+ if (group->p2p->vendor_elem &&
+ group->p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_RESP])
+ wpabuf_put_buf(resp,
+ group->p2p->vendor_elem[VENDOR_ELEM_P2P_ASSOC_RESP]);
+
rlen = p2p_buf_add_ie_hdr(resp);
if (status != P2P_SC_SUCCESS)
p2p_buf_add_status(resp, status);
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index 39a927a..3b60582 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -499,6 +499,8 @@
#endif /* CONFIG_WIFI_DISPLAY */
u16 authorized_oob_dev_pw_id;
+
+ struct wpabuf **vendor_elem;
};
/**
diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c
index a36898e..ef01a66 100644
--- a/src/p2p/p2p_invitation.c
+++ b/src/p2p/p2p_invitation.c
@@ -10,6 +10,7 @@
#include "common.h"
#include "common/ieee802_11_defs.h"
+#include "common/wpa_ctrl.h"
#include "p2p_i.h"
#include "p2p.h"
@@ -45,6 +46,9 @@
extra = wpabuf_len(wfd_ie);
#endif /* CONFIG_WIFI_DISPLAY */
+ if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_INV_REQ])
+ extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_INV_REQ]);
+
buf = wpabuf_alloc(1000 + extra);
if (buf == NULL)
return NULL;
@@ -86,6 +90,9 @@
wpabuf_put_buf(buf, wfd_ie);
#endif /* CONFIG_WIFI_DISPLAY */
+ if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_INV_REQ])
+ wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_INV_REQ]);
+
if (dev_pw_id >= 0) {
/* WSC IE in Invitation Request for NFC static handover */
p2p_build_wps_ie(p2p, buf, dev_pw_id, 0);
diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c
index 68d79d2..e101367 100644
--- a/src/p2p/p2p_pd.c
+++ b/src/p2p/p2p_pd.c
@@ -10,6 +10,7 @@
#include "common.h"
#include "common/ieee802_11_defs.h"
+#include "common/wpa_ctrl.h"
#include "wps/wps_defs.h"
#include "p2p_i.h"
#include "p2p.h"
@@ -53,6 +54,9 @@
extra = wpabuf_len(p2p->wfd_ie_prov_disc_req);
#endif /* CONFIG_WIFI_DISPLAY */
+ if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ])
+ extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ]);
+
buf = wpabuf_alloc(1000 + extra);
if (buf == NULL)
return NULL;
@@ -77,6 +81,9 @@
wpabuf_put_buf(buf, p2p->wfd_ie_prov_disc_req);
#endif /* CONFIG_WIFI_DISPLAY */
+ if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ])
+ wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ]);
+
return buf;
}
@@ -111,6 +118,9 @@
extra = wpabuf_len(wfd_ie);
#endif /* CONFIG_WIFI_DISPLAY */
+ if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP])
+ extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP]);
+
buf = wpabuf_alloc(100 + extra);
if (buf == NULL)
return NULL;
@@ -125,6 +135,9 @@
wpabuf_put_buf(buf, wfd_ie);
#endif /* CONFIG_WIFI_DISPLAY */
+ if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP])
+ wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP]);
+
return buf;
}