CHROMIUMOS: mesh: Add debug dialog token IE to MPM action frames

This commit adds a vendor IE (OUI f4:f5:e8, feature id 2) which will
append an unique, monotonically increasing "Dialog Token" in the Mesh
peer peer link management action frames. The receiver of such action
frames prints the frame id to assist debugging protocol transaction.

BUG=b:27135961
TEST=Manually run on Whirlwind two node setup. Also verified action
frame content with sniffer.

Change-Id: I5893e158bbcb9a363764d0f111e164aa9cad1b69
Reviewed-on: https://chromium-review.googlesource.com/339085
Commit-Ready: Zhihong Yu <zhihongyu@chromium.org>
Tested-by: Zhihong Yu <zhihongyu@chromium.org>
Reviewed-by: Srinivasa duvvuri <sduvvuri@chromium.org>
Reviewed-by: John Walker <walker@google.com>
diff --git a/src/common/google-vendor.h b/src/common/google-vendor.h
new file mode 100644
index 0000000..d14c682
--- /dev/null
+++ b/src/common/google-vendor.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016 Google, Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GOOGLE_VENDOR_H
+#define GOOGLE_VENDOR_H
+
+#include <utils/common.h>
+
+/*
+ * This file defines some of the attributes used along with Google OUI
+ * f4:f5:e8.
+ */
+
+#define OUI_GOOGLE 0xF4F5E8 /* Google */
+
+#define VENDOR_GOOGLE_DEBUG_DIALOG_TOKEN_TYPE	0x02
+
+/*
+ * GOogle Debug Dialog Token Information Element
+ */
+struct google_debug_dialog_token_ie {
+	/* Element ID: 221 (0xdd); Length: 8 */
+	/* required fields for debug dialog token */
+	u8 oui[3]; /* f4:f5:e8 */
+	u8 oui_type; /* 1 */
+	le32 dialog_token;
+} STRUCT_PACKED;
+
+#endif /* GOOGLE_VENDOR_H */
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index d07a316..c53fb32 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -12,6 +12,7 @@
 #include "defs.h"
 #include "wpa_common.h"
 #include "qca-vendor.h"
+#include "google-vendor.h"
 #include "ieee802_11_defs.h"
 #include "ieee802_11_common.h"
 
@@ -162,6 +163,21 @@
 		}
 		break;
 
+	case OUI_GOOGLE:
+		switch(pos[3]) {
+		case VENDOR_GOOGLE_DEBUG_DIALOG_TOKEN_TYPE:
+			elems->google_debug_dialog_token = pos;
+			elems->google_debug_dialog_token_len = elen;
+			break;
+		default:
+			wpa_printf(MSG_EXCESSIVE, "Unknown Google "
+				"information element ignored "
+				"(type=%d len=%lu)",
+				pos[3], (unsigned long) elen);
+			return -1;
+		}
+		break;
+
 	default:
 		wpa_printf(MSG_EXCESSIVE, "unknown vendor specific "
 			   "information element ignored (vendor OUI "
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
index 55ce022..4b33586 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -59,6 +59,7 @@
 	const u8 *ampe;
 	const u8 *mic;
 	const u8 *pref_freq_list;
+	const u8 *google_debug_dialog_token;
 
 	u8 ssid_len;
 	u8 supp_rates_len;
@@ -88,6 +89,7 @@
 	u8 ampe_len;
 	u8 mic_len;
 	u8 pref_freq_list_len;
+	u8 google_debug_dialog_token_len;
 	struct mb_ies_info mb_ies;
 };
 
diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c
index 9664d97..85bf894 100644
--- a/wpa_supplicant/mesh_mpm.c
+++ b/wpa_supplicant/mesh_mpm.c
@@ -10,6 +10,7 @@
 
 #include "utils/common.h"
 #include "utils/eloop.h"
+#include "common/google-vendor.h"
 #include "common/ieee802_11_defs.h"
 #include "ap/hostapd.h"
 #include "ap/sta_info.h"
@@ -42,6 +43,13 @@
 	CLS_IGNR
 };
 
+static const char * const mplaction[] = {
+	[0] = "UNDEFINED",
+	[PLINK_OPEN] = "PLINK_OPEN",
+	[PLINK_CONFIRM] = "PLINK_CONFIRM",
+	[PLINK_CLOSE] = "PLINK_CLOSE",
+};
+
 static const char * const mplstate[] = {
 	[0] = "UNINITIALIZED",
 	[PLINK_LISTEN] = "LISTEN",
@@ -229,6 +237,7 @@
 		  2 + 32 + /* mesh ID */
 		  2 + 7 +  /* mesh config */
 		  2 + 23 + /* peering management */
+		  2 + 8 +  /* Debug Dialog Token */
 		  2 + 96 + /* AMPE */
 		  2 + 16;  /* MIC */
 #ifdef CONFIG_IEEE80211N
@@ -355,15 +364,24 @@
 	}
 #endif /* CONFIG_IEEE80211AC */
 
+	/* IE: Google Debug Dialog Token */
+	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
+	wpabuf_put_u8(buf, 8);
+	wpabuf_put_be32(buf, (OUI_GOOGLE << 8) | VENDOR_GOOGLE_DEBUG_DIALOG_TOKEN_TYPE);
+	wpabuf_put_le32(buf, wpa_s->google_debug_dialog_token);
+
 	if (ampe && mesh_rsn_protect_frame(wpa_s->mesh_rsn, sta, cat, buf)) {
 		wpa_msg(wpa_s, MSG_INFO,
 			"Mesh MPM: failed to add AMPE and MIC IE");
 		goto fail;
 	}
 
-	wpa_printf(MSG_INFO, "Mesh MPM: Sending peering frame type %d to "
-		MACSTR " (my_lid=0x%x peer_lid=0x%x)",
-		type, MAC2STR(sta->addr), sta->my_lid, sta->peer_lid);
+	wpa_printf(MSG_INFO, "Mesh MPM: Sending peering frame type %d (%s) to "
+		MACSTR " (my_lid=0x%x peer_lid=0x%x) (Debug Dialog Token: %u)",
+		type, mplaction[type], MAC2STR(sta->addr), sta->my_lid, sta->peer_lid,
+		wpa_s->google_debug_dialog_token);
+	wpa_s->google_debug_dialog_token++;
+
 	ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0,
 				  sta->addr, wpa_s->own_addr, wpa_s->own_addr,
 				  wpabuf_head(buf), wpabuf_len(buf), 0);
@@ -912,6 +930,7 @@
 	enum plink_event event;
 	struct ieee802_11_elems elems;
 	struct mesh_peer_mgmt_ie peer_mgmt_ie;
+	u32 google_debug_dialog_token = 0;
 	const u8 *ies;
 	size_t ie_len;
 	int ret;
@@ -955,6 +974,16 @@
 		wpa_printf(MSG_DEBUG, "MPM: Failed to parse PLINK IEs");
 		return;
 	}
+	if (elems.google_debug_dialog_token) {
+		if (elems.google_debug_dialog_token_len != sizeof(struct google_debug_dialog_token_ie)) {
+			wpa_printf(MSG_INFO, "MPM: Incorrect size of Debug Dialog Token IE %d",
+				elems.google_debug_dialog_token_len);
+		} else {
+			google_debug_dialog_token = WPA_GET_LE32(elems.google_debug_dialog_token + 4);
+			wpa_printf(MSG_INFO, "MPM: Received %s, Debug Dialog Token: %u",
+				mplaction[action_field], google_debug_dialog_token);
+		}
+	}
 	if (!elems.peer_mgmt) {
 		wpa_printf(MSG_DEBUG,
 			   "MPM: No Mesh Peering Management element");
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index fbe1cd9..44ac26e 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -31,6 +31,7 @@
 #include "common/version.h"
 #include "rsn_supp/preauth.h"
 #include "rsn_supp/pmksa_cache.h"
+#include "common/google-vendor.h"
 #include "common/wpa_ctrl.h"
 #include "common/ieee802_11_defs.h"
 #include "common/hw_features_common.h"
@@ -4536,6 +4537,17 @@
 
 	wpas_rrm_reset(wpa_s);
 
+	/*
+	 * Initialize Google Debug Dialog Token to a random start value, which is
+	 * increased monotonically everytime it's embedded in a management frame.
+	 */
+	if (os_get_random((u8 *) &wpa_s->google_debug_dialog_token,
+		sizeof(wpa_s->google_debug_dialog_token)) < 0) {
+		wpa_s->google_debug_dialog_token = 0;
+	}
+	wpa_printf(MSG_INFO, "MPM: Debug Dialog Token initialized %u (0x%x)",
+		wpa_s->google_debug_dialog_token, wpa_s->google_debug_dialog_token);
+
 	return 0;
 }
 
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index f14e83d..47d1a39 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -998,6 +998,8 @@
 	const struct wpabuf *fst_ies;
 	struct wpabuf *received_mb_ies;
 #endif /* CONFIG_FST */
+
+	u32 google_debug_dialog_token;
 };