Browse Source

P2P: Make unrecognized vendor elements available in P2P_PEER

This allows external programs to use vendor specific information from
P2P peers without wpa_supplicant having to be able to parse and
understand all such vendor specific elements.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
Jouni Malinen 10 years ago
parent
commit
71a0e395b9
5 changed files with 71 additions and 2 deletions
  1. 1 0
      src/common/ieee802_11_defs.h
  2. 43 0
      src/p2p/p2p.c
  3. 8 0
      src/p2p/p2p.h
  4. 16 0
      wpa_supplicant/ctrl_iface.c
  5. 3 2
      wpa_supplicant/p2p_supplicant.c

+ 1 - 0
src/common/ieee802_11_defs.h

@@ -809,6 +809,7 @@ struct ieee80211_vht_operation {
 #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

+ 43 - 0
src/p2p/p2p.c

@@ -609,6 +609,46 @@ static void p2p_copy_wps_info(struct p2p_data *p2p, struct p2p_device *dev,
 }
 
 
+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()
@@ -757,6 +797,8 @@ int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq,
 
 	p2p_parse_free(&msg);
 
+	p2p_update_peer_vendor_elems(dev, ies, ies_len);
+
 	if (dev->flags & P2P_DEV_REPORTED)
 		return 0;
 
@@ -826,6 +868,7 @@ static void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev)
 	}
 
 	wpabuf_free(dev->info.wfd_subelems);
+	wpabuf_free(dev->info.vendor_elems);
 	wpabuf_free(dev->go_neg_conf);
 
 	os_free(dev);

+ 8 - 0
src/p2p/p2p.h

@@ -230,6 +230,14 @@ struct p2p_peer_info {
 	 * 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 {

+ 16 - 0
wpa_supplicant/ctrl_iface.c

@@ -4715,6 +4715,22 @@ static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd,
 		return pos - buf;
 	pos += res;
 
+	if (info->vendor_elems) {
+		res = os_snprintf(pos, end - pos, "vendor_elems=");
+		if (res < 0 || res >= end - pos)
+			return pos - buf;
+		pos += res;
+
+		pos += wpa_snprintf_hex(pos, end - pos,
+					wpabuf_head(info->vendor_elems),
+					wpabuf_len(info->vendor_elems));
+
+		res = os_snprintf(pos, end - pos, "\n");
+		if (res < 0 || res >= end - pos)
+			return pos - buf;
+		pos += res;
+	}
+
 	return pos - buf;
 }
 

+ 3 - 2
wpa_supplicant/p2p_supplicant.c

@@ -1693,14 +1693,15 @@ static void wpas_dev_found(void *ctx, const u8 *addr,
 	wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_DEVICE_FOUND MACSTR
 		       " p2p_dev_addr=" MACSTR
 		       " pri_dev_type=%s name='%s' config_methods=0x%x "
-		       "dev_capab=0x%x group_capab=0x%x%s%s",
+		       "dev_capab=0x%x group_capab=0x%x%s%s%s",
 		       MAC2STR(addr), MAC2STR(info->p2p_device_addr),
 		       wps_dev_type_bin2str(info->pri_dev_type, devtype,
 					    sizeof(devtype)),
 		       info->device_name, info->config_methods,
 		       info->dev_capab, info->group_capab,
 		       wfd_dev_info_hex ? " wfd_dev_info=0x" : "",
-		       wfd_dev_info_hex ? wfd_dev_info_hex : "");
+		       wfd_dev_info_hex ? wfd_dev_info_hex : "",
+		       info->vendor_elems ? " vendor_elems=1" : "");
 
 	os_free(wfd_dev_info_hex);
 #endif /* CONFIG_NO_STDOUT_DEBUG */