Browse Source

P2P: Keep track of peer WPS vendor extensions

Make the P2P code keep track of WPS vendor extensions received from
peers so they can be exposed via DBus later.

Signed-off-by: Jean-Michel Bachot <jean-michelx.bachot@linux.intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Jean-Michel Bachot 14 years ago
parent
commit
6f2c060711
7 changed files with 63 additions and 4 deletions
  1. 22 0
      src/p2p/p2p.c
  2. 2 0
      src/p2p/p2p.h
  3. 2 0
      src/p2p/p2p_i.h
  4. 8 0
      src/p2p/p2p_parse.c
  5. 4 0
      src/wps/wps.h
  6. 21 4
      src/wps/wps_attr_parse.c
  7. 4 0
      src/wps/wps_i.h

+ 22 - 0
src/p2p/p2p.c

@@ -431,6 +431,7 @@ int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq, int level,
 	struct p2p_device *dev;
 	struct p2p_message msg;
 	const u8 *p2p_dev_addr;
+	int i;
 
 	os_memset(&msg, 0, sizeof(msg));
 	if (p2p_parse_ies(ies, ies_len, &msg)) {
@@ -522,6 +523,20 @@ int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq, int level,
 			msg.wps_sec_dev_type_list_len;
 	}
 
+	for (i = 0; i < P2P_MAX_PEER_WPS_VENDOR_EXT; i++) {
+		wpabuf_free(dev->info.wps_vendor_ext[i]);
+		dev->info.wps_vendor_ext[i] = NULL;
+	}
+
+	for (i = 0; i < P2P_MAX_PEER_WPS_VENDOR_EXT; i++) {
+		if (msg.wps_vendor_ext[i] == NULL)
+			break;
+		dev->info.wps_vendor_ext[i] = wpabuf_alloc_copy(
+			msg.wps_vendor_ext[i], msg.wps_vendor_ext_len[i]);
+		if (dev->info.wps_vendor_ext[i] == NULL)
+			break;
+	}
+
 	if (msg.capability) {
 		dev->info.dev_capab = msg.capability[0];
 		dev->info.group_capab = msg.capability[1];
@@ -562,6 +577,8 @@ int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq, int level,
 
 static void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev)
 {
+	int i;
+
 	if (p2p->go_neg_peer == dev)
 		p2p->go_neg_peer = NULL;
 	if (p2p->invite_peer == dev)
@@ -573,6 +590,11 @@ static void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev)
 
 	p2p->cfg->dev_lost(p2p->cfg->cb_ctx, dev->info.p2p_device_addr);
 
+	for (i = 0; i < P2P_MAX_PEER_WPS_VENDOR_EXT; i++) {
+		wpabuf_free(dev->info.wps_vendor_ext[i]);
+		dev->info.wps_vendor_ext[i] = NULL;
+	}
+
 	os_free(dev);
 }
 

+ 2 - 0
src/p2p/p2p.h

@@ -186,6 +186,8 @@ struct p2p_peer_info {
 	 */
 	size_t wps_sec_dev_type_list_len;
 
+#define P2P_MAX_PEER_WPS_VENDOR_EXT 10
+	struct wpabuf *wps_vendor_ext[P2P_MAX_PEER_WPS_VENDOR_EXT];
 };
 
 /**

+ 2 - 0
src/p2p/p2p_i.h

@@ -445,6 +445,8 @@ struct p2p_message {
 	const u8 *wps_pri_dev_type;
 	const u8 *wps_sec_dev_type_list;
 	size_t wps_sec_dev_type_list_len;
+	const u8 *wps_vendor_ext[P2P_MAX_WPS_VENDOR_EXTENSIONS];
+	size_t wps_vendor_ext_len[P2P_MAX_WPS_VENDOR_EXTENSIONS];
 
 	/* DS Parameter Set IE */
 	const u8 *ds_params;

+ 8 - 0
src/p2p/p2p_parse.c

@@ -328,6 +328,7 @@ int p2p_parse_p2p_ie(const struct wpabuf *buf, struct p2p_message *msg)
 static int p2p_parse_wps_ie(const struct wpabuf *buf, struct p2p_message *msg)
 {
 	struct wps_parse_attr attr;
+	int i;
 
 	wpa_printf(MSG_DEBUG, "P2P: Parsing WPS IE");
 	if (wps_parse_msg(buf, &attr))
@@ -358,6 +359,13 @@ static int p2p_parse_wps_ie(const struct wpabuf *buf, struct p2p_message *msg)
 		msg->wps_sec_dev_type_list_len = attr.sec_dev_type_list_len;
 	}
 
+	for (i = 0; i < P2P_MAX_PEER_WPS_VENDOR_EXT; i++) {
+		if (i >= P2P_MAX_WPS_VENDOR_EXTENSIONS)
+			break;
+		msg->wps_vendor_ext[i] = attr.vendor_ext[i];
+		msg->wps_vendor_ext_len[i] = attr.vendor_ext_len[i];
+	}
+
 	return 0;
 }
 

+ 4 - 0
src/wps/wps.h

@@ -66,6 +66,10 @@ struct wps_credential {
 #define WPS_SEC_DEV_TYPE_MAX_LEN 128
 /* maximum number of advertised WPS vendor extension attributes */
 #define MAX_WPS_VENDOR_EXTENSIONS 10
+/* maximum size of WPS Vendor extension attribute */
+#define WPS_MAX_VENDOR_EXT_LEN 1024
+/* maximum number of parsed WPS vendor extension attributes */
+#define MAX_WPS_PARSE_VENDOR_EXT 10
 
 /**
  * struct wps_device_data - WPS Device Data

+ 21 - 4
src/wps/wps_attr_parse.c

@@ -108,12 +108,29 @@ static int wps_parse_vendor_ext(struct wps_parse_attr *attr, const u8 *pos,
 	switch (vendor_id) {
 	case WPS_VENDOR_ID_WFA:
 		return wps_parse_vendor_ext_wfa(attr, pos + 3, len - 3);
-	default:
-		wpa_printf(MSG_MSGDUMP, "WPS: Skip unknown Vendor Extension "
-			   "(Vendor ID %u)", vendor_id);
-		break;
 	}
 
+	/* Handle unknown vendor extensions */
+
+	wpa_printf(MSG_MSGDUMP, "WPS: Unknown Vendor Extension (Vendor ID %u)",
+		   vendor_id);
+
+	if (len > WPS_MAX_VENDOR_EXT_LEN) {
+		wpa_printf(MSG_DEBUG, "WPS: Too long Vendor Extension (%u)",
+			   len);
+		return -1;
+	}
+
+	if (attr->num_vendor_ext > MAX_WPS_PARSE_VENDOR_EXT) {
+		wpa_printf(MSG_DEBUG, "WPS: Skipped Vendor Extension "
+			   "attribute (max %d vendor extensions)",
+			   MAX_WPS_PARSE_VENDOR_EXT);
+		return -1;
+	}
+	attr->vendor_ext[attr->num_vendor_ext] = pos;
+	attr->vendor_ext_len[attr->num_vendor_ext] = len;
+	attr->num_vendor_ext++;
+
 	return 0;
 }
 

+ 4 - 0
src/wps/wps_i.h

@@ -207,6 +207,10 @@ struct wps_parse_attr {
 #define MAX_REQ_DEV_TYPE_COUNT 10
 	const u8 *req_dev_type[MAX_REQ_DEV_TYPE_COUNT];
 	size_t num_req_dev_type;
+
+	const u8 *vendor_ext[MAX_WPS_PARSE_VENDOR_EXT];
+	size_t vendor_ext_len[MAX_WPS_PARSE_VENDOR_EXT];
+	size_t num_vendor_ext;
 };
 
 /* wps_common.c */