From Jouni Malinen via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8711 Wi...
authorAlexis La Goutte <alexis.lagoutte@gmail.com>
Mon, 27 May 2013 16:20:29 +0000 (16:20 -0000)
committerAlexis La Goutte <alexis.lagoutte@gmail.com>
Mon, 27 May 2013 16:20:29 +0000 (16:20 -0000)
The attached patch adds initial support for dissecting Wi-Fi Display information element

svn path=/trunk/; revision=49593

epan/CMakeLists.txt
epan/dissectors/Makefile.common
epan/dissectors/packet-ieee80211.c
epan/dissectors/packet-ieee80211.h
epan/dissectors/packet-wifi-display.c [new file with mode: 0644]
epan/dissectors/packet-wifi-p2p.c

index 415e0eb84fd8ec0f9f7b03dafc15b05c2800edec..4cfd40eb2a5181f9e9281228a23913c98792896a 100644 (file)
@@ -1252,6 +1252,7 @@ set(DISSECTOR_SRC
        dissectors/packet-websocket.c
        dissectors/packet-wfleet-hdlc.c
        dissectors/packet-who.c
+       dissectors/packet-wifi-display.c
        dissectors/packet-wifi-p2p.c
        dissectors/packet-windows-common.c
        dissectors/packet-winsrepl.c
index 7929a7d4a6053813794b07003755ce241150ec35..b2b68c1ac67d65051b4a903c2d467cb6462616ee 100644 (file)
@@ -1174,6 +1174,7 @@ DISSECTOR_SRC = \
        packet-websocket.c      \
        packet-wfleet-hdlc.c    \
        packet-who.c            \
+       packet-wifi-display.c   \
        packet-wifi-p2p.c       \
        packet-windows-common.c \
        packet-winsrepl.c       \
index 4f0ea00c207c4192eec82b9a85b0f28efc142fa8..73171282ab9d2f5ca8cb9d02b24bba95d4be1b43 100644 (file)
@@ -805,6 +805,7 @@ static value_string_ext tag_num_vals_ext = VALUE_STRING_EXT_INIT(tag_num_vals);
 
 /* WFA vendor specific subtypes */
 #define WFA_SUBTYPE_P2P 9
+#define WFA_SUBTYPE_WIFI_DISPLAY 10
 #define WFA_SUBTYPE_HS20_INDICATION 16
 #define WFA_SUBTYPE_HS20_ANQP 17
 
@@ -8013,6 +8014,10 @@ dissect_vendor_ie_wfa(packet_info *pinfo, proto_item *item, tvbuff_t *tag_tvb)
     dissect_wifi_p2p_ie(pinfo, item, tag_tvb, 4, tag_len - 4);
     proto_item_append_text(item, ": P2P");
     break;
+  case WFA_SUBTYPE_WIFI_DISPLAY:
+    dissect_wifi_display_ie(pinfo, item, tag_tvb, 4, tag_len - 4);
+    proto_item_append_text(item, ": Wi-Fi Display");
+    break;
   case WFA_SUBTYPE_HS20_INDICATION:
     dissect_hs20_indication(item, tag_tvb, 4);
     proto_item_append_text(item, ": Hotspot 2.0 Indication");
index 3abb7a514c428802cb204fde1f3b0805ea07cb83..b9f0d3be8c76c474148941f13a71e25db5341bb9 100644 (file)
@@ -43,6 +43,9 @@ void capture_wlancap(const guchar *, int, int, packet_counts *);
 void ieee_80211_add_tagged_parameters (tvbuff_t * tvb, int offset,
        packet_info * pinfo, proto_tree * tree, int tagged_parameters_len, int ftype);
 
+void dissect_wifi_display_ie(packet_info *pinfo, proto_tree *tree,
+                            tvbuff_t *tvb, int offset, gint size);
+
 #define MAX_SSID_LEN    32
 #define MAX_PROTECT_LEN 10
 
diff --git a/epan/dissectors/packet-wifi-display.c b/epan/dissectors/packet-wifi-display.c
new file mode 100644 (file)
index 0000000..56d8eb7
--- /dev/null
@@ -0,0 +1,548 @@
+/* packet-wifi-display.c
+ *
+ * Wi-Fi Display
+ *
+ * Copyright 2011-2013 Qualcomm Atheros, Inc.
+ *
+ * $Id$
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+# include "config.h"
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/expert.h>
+
+#include "packet-ieee80211.h"
+
+static int proto_wifi_display = -1;
+
+static int hf_wfd_subelem_id = -1;
+static int hf_wfd_subelem_len = -1;
+
+static int hf_wfd_subelem_dev_info_type = -1;
+static int hf_wfd_subelem_dev_info_coupled_sink_source = -1;
+static int hf_wfd_subelem_dev_info_coupled_sink_sink = -1;
+static int hf_wfd_subelem_dev_info_available = -1;
+static int hf_wfd_subelem_dev_info_wsd = -1;
+static int hf_wfd_subelem_dev_info_pc = -1;
+static int hf_wfd_subelem_dev_info_content_protection = -1;
+static int hf_wfd_subelem_dev_info_time_sync = -1;
+static int hf_wfd_subelem_dev_info_control_port = -1;
+static int hf_wfd_subelem_dev_info_max_throughput = -1;
+static int hf_wfd_subelem_dev_info_audio_unsupp_pri_sink = -1;
+static int hf_wfd_subelem_dev_info_audio_only_supp_source = -1;
+static int hf_wfd_subelem_dev_info_tdls_persistent_group = -1;
+static int hf_wfd_subelem_dev_info_tdls_persistent_group_reinvoke = -1;
+static int hf_wfd_subelem_dev_info_reserved = -1;
+
+static int hf_wfd_subelem_assoc_bssid = -1;
+
+static int hf_wfd_subelem_coupled_sink_status_bitmap = -1;
+static int hf_wfd_subelem_coupled_sink_reserved = -1;
+static int hf_wfd_subelem_coupled_sink_mac_addr = -1;
+
+static int hf_wfd_subelem_session_descr_len = -1;
+static int hf_wfd_subelem_session_dev_addr = -1;
+static int hf_wfd_subelem_session_assoc_bssid = -1;
+static int hf_wfd_subelem_session_dev_info_type = -1;
+static int hf_wfd_subelem_session_dev_info_coupled_sink_source = -1;
+static int hf_wfd_subelem_session_dev_info_coupled_sink_sink = -1;
+static int hf_wfd_subelem_session_dev_info_available = -1;
+static int hf_wfd_subelem_session_dev_info_wsd = -1;
+static int hf_wfd_subelem_session_dev_info_pc = -1;
+static int hf_wfd_subelem_session_dev_info_content_protection = -1;
+static int hf_wfd_subelem_session_dev_info_time_sync = -1;
+static int hf_wfd_subelem_session_dev_info_audio_unsupp_pri_sink = -1;
+static int hf_wfd_subelem_session_dev_info_audio_only_supp_source = -1;
+static int hf_wfd_subelem_session_dev_info_tdls_persistent_group = -1;
+static int hf_wfd_subelem_session_dev_info_tdls_persistent_group_reinvoke = -1;
+static int hf_wfd_subelem_session_dev_info_reserved = -1;
+static int hf_wfd_subelem_session_dev_info_max_throughput = -1;
+static int hf_wfd_subelem_session_coupled_sink_status_bitmap = -1;
+static int hf_wfd_subelem_session_coupled_sink_reserved = -1;
+static int hf_wfd_subelem_session_coupled_sink_addr = -1;
+
+static gint ett_wfd_subelem = -1;
+static gint ett_wfd_dev_info_descr = -1;
+
+
+enum wifi_display_subelem {
+  WFD_SUBELEM_DEVICE_INFO = 0,
+  WFD_SUBELEM_ASSOCIATED_BSSID = 1,
+  WFD_SUBELEM_AUDIO_FORMATS = 2,
+  WFD_SUBELEM_VIDEO_FORMATS = 3,
+  WFD_SUBELEM_3D_VIDEO_FORMATS = 4,
+  WFD_SUBELEM_CONTENT_PROTECTION = 5,
+  WFD_SUBELEM_COUPLED_SINK = 6,
+  WFD_SUBELEM_EXT_CAPAB = 7,
+  WFD_SUBELEM_LOCAL_IP_ADDRESS = 8,
+  WFD_SUBELEM_SESSION_INFO = 9,
+  WFD_SUBELEM_ALT_MAC_ADDR = 10
+};
+
+static const value_string wfd_subelem_ids[] = {
+  { WFD_SUBELEM_DEVICE_INFO, "WFD Device Information" },
+  { WFD_SUBELEM_ASSOCIATED_BSSID, "Associated BSSID" },
+  { WFD_SUBELEM_AUDIO_FORMATS, "WFD Audio Formats" },
+  { WFD_SUBELEM_VIDEO_FORMATS, "WFD Video Formats" },
+  { WFD_SUBELEM_3D_VIDEO_FORMATS, "WFD 3D Video Formats" },
+  { WFD_SUBELEM_CONTENT_PROTECTION, "WFD Content Protection" },
+  { WFD_SUBELEM_COUPLED_SINK, "Coupled Sink Information" },
+  { WFD_SUBELEM_EXT_CAPAB, "WFD Extended Capability" },
+  { WFD_SUBELEM_LOCAL_IP_ADDRESS, "Local IP Address" },
+  { WFD_SUBELEM_SESSION_INFO, "WFD Session Information" },
+  { WFD_SUBELEM_ALT_MAC_ADDR, "Alternative MAC Address" },
+  { 0, NULL }
+};
+
+
+static const value_string wfd_dev_info_types[] = {
+  { 0, "WFD source" },
+  { 1, "WFD primary sink" },
+  { 2, "WFD secondary sink" },
+  { 3, "WFD source/primary sink" },
+  { 0, NULL }
+};
+
+static const value_string wfd_dev_info_avail[] = {
+  { 0, "Not available for WFD Session" },
+  { 1, "Available for WFD Session" },
+  { 0, NULL }
+};
+
+static const value_string wfd_dev_info_pc[] = {
+  { 0, "P2P" },
+  { 1, "TDLS" },
+  { 0, NULL }
+};
+
+static const value_string wfd_coupled_sink_status_bitmap[] = {
+  { 0, "Not coupled/Available for Coupling" },
+  { 1, "Coupled" },
+  { 2, "Teardown Coupling" },
+  { 3, "Reserved" },
+  { 0, NULL }
+};
+
+static void
+dissect_wfd_subelem_device_info(proto_tree *tree, tvbuff_t *tvb, int offset)
+{
+  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_type,
+                      tvb, offset, 2, ENC_BIG_ENDIAN);
+  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_coupled_sink_source,
+                      tvb, offset, 2, ENC_BIG_ENDIAN);
+  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_coupled_sink_sink,
+                      tvb, offset, 2, ENC_BIG_ENDIAN);
+  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_available,
+                      tvb, offset, 2, ENC_BIG_ENDIAN);
+  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_wsd,
+                      tvb, offset, 2, ENC_BIG_ENDIAN);
+  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_pc,
+                      tvb, offset, 2, ENC_BIG_ENDIAN);
+  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_content_protection,
+                      tvb, offset, 2, ENC_BIG_ENDIAN);
+  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_time_sync,
+                      tvb, offset, 2, ENC_BIG_ENDIAN);
+  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_audio_unsupp_pri_sink,
+                      tvb, offset, 2, ENC_BIG_ENDIAN);
+  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_audio_only_supp_source,
+                      tvb, offset, 2, ENC_BIG_ENDIAN);
+  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_tdls_persistent_group,
+                      tvb, offset, 2, ENC_BIG_ENDIAN);
+  proto_tree_add_item(tree,
+                      hf_wfd_subelem_dev_info_tdls_persistent_group_reinvoke,
+                      tvb, offset, 2, ENC_BIG_ENDIAN);
+  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_reserved,
+                      tvb, offset, 2, ENC_BIG_ENDIAN);
+  offset += 2;
+
+  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_control_port,
+                      tvb, offset, 2, ENC_BIG_ENDIAN);
+  offset += 2;
+
+  proto_tree_add_item(tree, hf_wfd_subelem_dev_info_max_throughput,
+                      tvb, offset, 2, ENC_BIG_ENDIAN);
+}
+
+static void
+dissect_wfd_subelem_associated_bssid(packet_info *pinfo, proto_tree *tree,
+                                     tvbuff_t *tvb, int offset, int len)
+{
+  if (len < 6) {
+    expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR,
+                           "Too short Wi-Fi Display Associated BSSID");
+    return;
+  }
+  proto_tree_add_item(tree, hf_wfd_subelem_assoc_bssid, tvb, offset, 6, ENC_NA);
+}
+
+static void
+dissect_wfd_subelem_coupled_sink(packet_info *pinfo, proto_tree *tree,
+                                 tvbuff_t *tvb, int offset, int len)
+{
+  if (len < 1) {
+    expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR,
+                           "Too short Wi-Fi Display Coupled Sink");
+    return;
+  }
+  proto_tree_add_item(tree, hf_wfd_subelem_coupled_sink_status_bitmap,
+                      tvb, offset, 1, ENC_BIG_ENDIAN);
+  proto_tree_add_item(tree, hf_wfd_subelem_coupled_sink_reserved,
+                      tvb, offset, 1, ENC_BIG_ENDIAN);
+  if (len < 1 + 6) {
+    expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR,
+                           "Too short Wi-Fi Display Coupled Sink");
+    return;
+  }
+  proto_tree_add_item(tree, hf_wfd_subelem_coupled_sink_mac_addr, tvb,
+                      offset + 1, 6, ENC_NA);
+}
+
+static void
+dissect_wfd_subelem_session_info(packet_info *pinfo, proto_tree *tree,
+                                 tvbuff_t *tvb, int offset, guint8 len)
+{
+  int end = offset + len, next;
+  proto_item *item;
+  proto_tree *descr;
+
+  while (offset < end) {
+    guint8 dlen = tvb_get_guint8(tvb, offset);
+    if (offset + 1 + dlen > end || dlen < 23) {
+      expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR,
+                             "Invalid WFD Device Info Descriptor");
+      break;
+    }
+    next = offset + 1 + dlen;
+
+    item = proto_tree_add_text(tree, tvb, offset, 1 + dlen,
+                               "WFD Device Info Descriptor");
+    descr = proto_item_add_subtree(item, ett_wfd_dev_info_descr);
+
+    proto_tree_add_item(descr, hf_wfd_subelem_session_descr_len,
+                        tvb, offset, 1, ENC_BIG_ENDIAN);
+    offset++;
+
+    proto_tree_add_item(descr, hf_wfd_subelem_session_dev_addr, tvb, offset, 6,
+                        ENC_NA);
+    proto_item_append_text(descr, ": %s", tvb_ether_to_str(tvb, offset));
+    offset += 6;
+
+    proto_tree_add_item(descr, hf_wfd_subelem_session_assoc_bssid,
+                        tvb, offset, 6, ENC_NA);
+    offset += 6;
+
+    proto_tree_add_item(descr, hf_wfd_subelem_session_dev_info_type,
+                        tvb, offset, 2, ENC_BIG_ENDIAN);
+    proto_tree_add_item(descr,
+                        hf_wfd_subelem_session_dev_info_coupled_sink_source,
+                        tvb, offset, 2, ENC_BIG_ENDIAN);
+    proto_tree_add_item(descr,
+                        hf_wfd_subelem_session_dev_info_coupled_sink_sink,
+                        tvb, offset, 2, ENC_BIG_ENDIAN);
+    proto_tree_add_item(descr, hf_wfd_subelem_session_dev_info_available,
+                        tvb, offset, 2, ENC_BIG_ENDIAN);
+    proto_tree_add_item(descr, hf_wfd_subelem_session_dev_info_wsd,
+                        tvb, offset, 2, ENC_BIG_ENDIAN);
+    proto_tree_add_item(descr, hf_wfd_subelem_session_dev_info_pc,
+                        tvb, offset, 2, ENC_BIG_ENDIAN);
+    proto_tree_add_item(descr,
+                        hf_wfd_subelem_session_dev_info_content_protection,
+                        tvb, offset, 2, ENC_BIG_ENDIAN);
+    proto_tree_add_item(descr, hf_wfd_subelem_session_dev_info_time_sync,
+                        tvb, offset, 2, ENC_BIG_ENDIAN);
+    proto_tree_add_item(tree,
+                        hf_wfd_subelem_session_dev_info_audio_unsupp_pri_sink,
+                        tvb, offset, 2, ENC_BIG_ENDIAN);
+    proto_tree_add_item(tree,
+                        hf_wfd_subelem_session_dev_info_audio_only_supp_source,
+                        tvb, offset, 2, ENC_BIG_ENDIAN);
+    proto_tree_add_item(tree,
+                        hf_wfd_subelem_session_dev_info_tdls_persistent_group,
+                        tvb, offset, 2, ENC_BIG_ENDIAN);
+    proto_tree_add_item(tree,
+                        hf_wfd_subelem_session_dev_info_tdls_persistent_group_reinvoke,
+                        tvb, offset, 2, ENC_BIG_ENDIAN);
+    proto_tree_add_item(tree,
+                        hf_wfd_subelem_session_dev_info_reserved,
+                        tvb, offset, 2, ENC_BIG_ENDIAN);
+    offset += 2;
+
+    proto_tree_add_item(descr, hf_wfd_subelem_session_dev_info_max_throughput,
+                        tvb, offset, 2, ENC_BIG_ENDIAN);
+    offset += 2;
+
+    proto_tree_add_item(descr,
+                        hf_wfd_subelem_session_coupled_sink_status_bitmap,
+                        tvb, offset, 1, ENC_BIG_ENDIAN);
+    proto_tree_add_item(descr,
+                        hf_wfd_subelem_session_coupled_sink_reserved,
+                        tvb, offset, 1, ENC_BIG_ENDIAN);
+    offset++;
+
+    proto_tree_add_item(descr, hf_wfd_subelem_session_coupled_sink_addr,
+                        tvb, offset, 6, ENC_NA);
+    offset += 6;
+
+    if (offset < next) {
+      proto_tree_add_text(descr, tvb, offset, next - offset,
+                          "Extra info in the end of descriptor");
+    }
+
+    offset = next;
+  }
+}
+
+void dissect_wifi_display_ie(packet_info *pinfo, proto_tree *tree,
+                             tvbuff_t *tvb, int offset, gint size)
+{
+  int end = offset + size;
+  guint8 id;
+  guint16 len;
+  proto_tree *wfd_tree;
+  proto_item *subelem;
+
+  while (offset < end) {
+    if (end - offset < 2) {
+      expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR,
+                             "Packet too short for Wi-Fi Display subelement");
+      break;
+    }
+
+    id = tvb_get_guint8(tvb, offset);
+    len = tvb_get_ntohs(tvb, offset + 1);
+    subelem = proto_tree_add_text(tree, tvb, offset, 3 + len, "%s",
+                                  val_to_str(id, wfd_subelem_ids,
+                                             "Unknown subelement ID (%u)"));
+    if (offset + 3 + len > end) {
+      expert_add_info_format(pinfo, subelem, PI_MALFORMED, PI_ERROR,
+                             "Packet too short for Wi-Fi Display subelement "
+                             "payload");
+    }
+
+    wfd_tree = proto_item_add_subtree(subelem, ett_wfd_subelem);
+
+    proto_tree_add_item(wfd_tree, hf_wfd_subelem_id, tvb, offset, 1,
+                        ENC_BIG_ENDIAN);
+    offset++;
+    proto_tree_add_item(wfd_tree, hf_wfd_subelem_len, tvb, offset, 2,
+                        ENC_BIG_ENDIAN);
+    offset += 2;
+
+    switch (id) {
+    case WFD_SUBELEM_DEVICE_INFO:
+      dissect_wfd_subelem_device_info(wfd_tree, tvb, offset);
+      break;
+    case WFD_SUBELEM_ASSOCIATED_BSSID:
+      dissect_wfd_subelem_associated_bssid(pinfo, wfd_tree, tvb, offset, len);
+      break;
+    case WFD_SUBELEM_COUPLED_SINK:
+      dissect_wfd_subelem_coupled_sink(pinfo, wfd_tree, tvb, offset, len);
+      break;
+    case WFD_SUBELEM_SESSION_INFO:
+      dissect_wfd_subelem_session_info(pinfo, wfd_tree, tvb, offset, len);
+      break;
+    default:
+      proto_tree_add_text(wfd_tree, tvb, offset, len,
+                          "Unknown subelement payload");
+      break;
+    }
+
+    offset += len;
+  }
+}
+
+void
+proto_register_wifi_display(void)
+{
+  static hf_register_info hf[] = {
+    { &hf_wfd_subelem_id,
+      { "Subelement ID", "wifi_display.subelem.id",
+        FT_UINT8, BASE_DEC, VALS(wfd_subelem_ids), 0, NULL, HFILL }},
+    { &hf_wfd_subelem_len,
+      { "Length", "wifi_display.subelem.length",
+        FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
+    { &hf_wfd_subelem_dev_info_type,
+      { "Device type", "wifi_display.subelem.dev_info.type",
+        FT_UINT16, BASE_DEC, VALS(wfd_dev_info_types), 0x0003, NULL, HFILL }},
+    { &hf_wfd_subelem_dev_info_coupled_sink_source,
+      { "Coupled sink operation supported by WFD source",
+        "wifi_display.subelem.dev_info.coupled_sink_by_source",
+        FT_BOOLEAN, 16, NULL, 0x0004, NULL, HFILL }},
+    { &hf_wfd_subelem_dev_info_coupled_sink_sink,
+      { "Coupled sink operation supported by WFD sink",
+        "wifi_display.subelem.dev_info.coupled_sink_by_sink",
+        FT_BOOLEAN, 16, NULL, 0x0008, NULL, HFILL }},
+    { &hf_wfd_subelem_dev_info_available,
+      { "Available for WFD Session", "wifi_display.subelem.dev_info.available",
+        FT_UINT16, BASE_DEC, VALS(wfd_dev_info_avail), 0x0030, NULL, HFILL }},
+    { &hf_wfd_subelem_dev_info_wsd,
+      { "WFD Service Discovery", "wifi_display.subelem.dev_info.wsd",
+        FT_BOOLEAN, 16, NULL, 0x0040, NULL, HFILL }},
+    { &hf_wfd_subelem_dev_info_pc,
+      { "Preferred Connectivity", "wifi_display.subelem.dev_info.pc",
+        FT_UINT16, BASE_DEC, VALS(wfd_dev_info_pc), 0x0080, NULL, HFILL }},
+    { &hf_wfd_subelem_dev_info_content_protection,
+      { "Content Protection using HDCP2.0",
+        "wifi_display.subelem.dev_info.content_protection",
+        FT_BOOLEAN, 16, NULL, 0x0100, NULL, HFILL }},
+    { &hf_wfd_subelem_dev_info_time_sync,
+      { "Time Synchronization using 802.1AS",
+        "wifi_display.subelem.dev_info.time_sync",
+        FT_BOOLEAN, 16, NULL, 0x0200, NULL, HFILL }},
+    { &hf_wfd_subelem_dev_info_audio_unsupp_pri_sink,
+      { "Audio un-supported at Primary sink",
+        "wifi_display.subelem.session.audio_unsupp_pri_sink",
+        FT_BOOLEAN, 16, NULL, 0x0400, NULL, HFILL }},
+    { &hf_wfd_subelem_dev_info_audio_only_supp_source,
+      { "Audio only support af WFD source",
+        "wifi_display.subelem.session.audio_only_supp_source",
+        FT_BOOLEAN, 16, NULL, 0x0800, NULL, HFILL }},
+    { &hf_wfd_subelem_dev_info_tdls_persistent_group,
+      { "TDLS Persistent Group",
+        "wifi_display.subelem.session.tdls_persistent_group",
+        FT_BOOLEAN, 16, NULL, 0x1000, NULL, HFILL }},
+    { &hf_wfd_subelem_dev_info_tdls_persistent_group_reinvoke,
+      { "TDLS Persistent Group Re-invoke",
+        "wifi_display.subelem.session.tdls_persistent_group_reinvoke",
+        FT_BOOLEAN, 16, NULL, 0x2000, NULL, HFILL }},
+    { &hf_wfd_subelem_dev_info_reserved,
+      { "Reserved", "wifi_display.subelem.session.reserved",
+        FT_UINT16, BASE_DEC, NULL, 0xc000, NULL, HFILL }},
+    { &hf_wfd_subelem_dev_info_control_port,
+      { "Session Management Control Port",
+        "wifi_display.subelem.dev_info.control_port",
+        FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
+    { &hf_wfd_subelem_dev_info_max_throughput,
+      { "WFD Device Maximum Throughput (Mbps)",
+        "wifi_display.subelem.dev_info.max_throughput",
+        FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
+    { &hf_wfd_subelem_assoc_bssid,
+      { "Associated BSSID", "wifi_display.subelem.assoc_bssid.bssid",
+        FT_ETHER, BASE_NONE, NULL, 0, NULL, HFILL }},
+    { &hf_wfd_subelem_coupled_sink_status_bitmap,
+      { "Coupled Sink Status bitmap",
+        "wifi_display.subelem.coupled_sink.status",
+        FT_UINT8, BASE_DEC, VALS(wfd_coupled_sink_status_bitmap), 0x03,
+        NULL, HFILL }},
+    { &hf_wfd_subelem_coupled_sink_reserved,
+      { "Reserved", "wifi_display.subelem.coupled_sink.reserved",
+        FT_UINT8, BASE_DEC, NULL, 0xfc, NULL, HFILL }},
+    { &hf_wfd_subelem_coupled_sink_mac_addr,
+      { "Coupled Sink MAC Address",
+        "wifi_display.subelem.coupled_sink.mac_addr",
+        FT_ETHER, BASE_NONE, NULL, 0, NULL, HFILL }},
+    { &hf_wfd_subelem_session_descr_len,
+      { "Descriptor length",
+        "wifi_display.subelem.session.descr_len",
+        FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
+    { &hf_wfd_subelem_session_dev_addr,
+      { "Device address",
+        "wifi_display.subelem.session.device_address",
+        FT_ETHER, BASE_NONE, NULL, 0, NULL, HFILL }},
+    { &hf_wfd_subelem_session_assoc_bssid,
+      { "Associated BSSID",
+        "wifi_display.subelem.session.associated_bssid",
+        FT_ETHER, BASE_NONE, NULL, 0, NULL, HFILL }},
+    { &hf_wfd_subelem_session_dev_info_type,
+      { "Device type", "wifi_display.subelem.session.type",
+        FT_UINT16, BASE_DEC, VALS(wfd_dev_info_types), 0x0003, NULL, HFILL }},
+    { &hf_wfd_subelem_session_dev_info_coupled_sink_source,
+      { "Coupled sink operation supported by WFD source",
+        "wifi_display.subelem.session.coupled_sink_by_source",
+        FT_BOOLEAN, 16, NULL, 0x0004, NULL, HFILL }},
+    { &hf_wfd_subelem_session_dev_info_coupled_sink_sink,
+      { "Coupled sink operation supported by WFD sink",
+        "wifi_display.subelem.session.coupled_sink_by_sink",
+        FT_BOOLEAN, 16, NULL, 0x0008, NULL, HFILL }},
+    { &hf_wfd_subelem_session_dev_info_available,
+      { "Available for WFD Session", "wifi_display.subelem.session.available",
+        FT_UINT16, BASE_DEC, VALS(wfd_dev_info_avail), 0x0030, NULL, HFILL }},
+    { &hf_wfd_subelem_session_dev_info_wsd,
+      { "WFD Service Discovery", "wifi_display.subelem.session.wsd",
+        FT_BOOLEAN, 16, NULL, 0x0040, NULL, HFILL }},
+    { &hf_wfd_subelem_session_dev_info_pc,
+      { "Preferred Connectivity", "wifi_display.subelem.session.pc",
+        FT_UINT16, BASE_DEC, VALS(wfd_dev_info_pc), 0x0080, NULL, HFILL }},
+    { &hf_wfd_subelem_session_dev_info_content_protection,
+      { "Content Protection using HDCP2.0",
+        "wifi_display.subelem.session.content_protection",
+        FT_BOOLEAN, 16, NULL, 0x0100, NULL, HFILL }},
+    { &hf_wfd_subelem_session_dev_info_time_sync,
+      { "Time Synchronization using 802.1AS",
+        "wifi_display.subelem.session.time_sync",
+        FT_BOOLEAN, 16, NULL, 0x0200, NULL, HFILL }},
+    { &hf_wfd_subelem_session_dev_info_audio_unsupp_pri_sink,
+      { "Audio un-supported at Primary sink",
+        "wifi_display.subelem.session.audio_unsupp_pri_sink",
+        FT_BOOLEAN, 16, NULL, 0x0400, NULL, HFILL }},
+    { &hf_wfd_subelem_session_dev_info_audio_only_supp_source,
+      { "Audio only support af WFD source",
+        "wifi_display.subelem.session.audio_only_supp_source",
+        FT_BOOLEAN, 16, NULL, 0x0800, NULL, HFILL }},
+    { &hf_wfd_subelem_session_dev_info_tdls_persistent_group,
+      { "TDLS Persistent Group",
+        "wifi_display.subelem.session.tdls_persistent_group",
+        FT_BOOLEAN, 16, NULL, 0x1000, NULL, HFILL }},
+    { &hf_wfd_subelem_session_dev_info_tdls_persistent_group_reinvoke,
+      { "TDLS Persistent Group Re-invoke",
+        "wifi_display.subelem.session.tdls_persistent_group_reinvoke",
+        FT_BOOLEAN, 16, NULL, 0x2000, NULL, HFILL }},
+    { &hf_wfd_subelem_session_dev_info_reserved,
+      { "Reserved", "wifi_display.subelem.session.reserved",
+        FT_UINT16, BASE_DEC, NULL, 0xc000, NULL, HFILL }},
+    { &hf_wfd_subelem_session_dev_info_max_throughput,
+      { "WFD Device Maximum Throughput (Mbps)",
+        "wifi_display.subelem.session.max_throughput",
+        FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
+    { &hf_wfd_subelem_session_coupled_sink_status_bitmap,
+      { "Coupled Sink Status bitmap",
+        "wifi_display.subelem.session.coupled_sink_status",
+        FT_UINT8, BASE_DEC, VALS(wfd_coupled_sink_status_bitmap), 0x03,
+        NULL, HFILL }},
+    { &hf_wfd_subelem_session_coupled_sink_reserved,
+      { "Reserved", "wifi_display.subelem.session.coupled_sink.reserved",
+        FT_UINT8, BASE_DEC, NULL, 0xfc, NULL, HFILL }},
+    { &hf_wfd_subelem_session_coupled_sink_addr,
+      { "Coupled peer sink address",
+        "wifi_display.subelem.session.coupled_peer_sink_addr",
+        FT_ETHER, BASE_NONE, NULL, 0, NULL, HFILL }}
+  };
+  static gint *ett[] = {
+    &ett_wfd_subelem,
+    &ett_wfd_dev_info_descr
+  };
+
+  proto_wifi_display = proto_register_protocol("Wi-Fi Display", "WFD",
+                                               "wifi_display");
+  proto_register_field_array(proto_wifi_display, hf, array_length(hf));
+  proto_register_subtree_array(ett, array_length(ett));
+}
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 2
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=2 tabstop=8 expandtab:
+ * :indentSize=2:tabSize=8:noTabs=true:
+ */
index eb85b4bac452fb9f68044f3a315ebfbd962c9862..de04505ffdde627e21d89d3db8742640929e5fa7 100644 (file)
@@ -27,6 +27,7 @@
 #include <epan/packet.h>
 #include <epan/expert.h>
 
+#include "packet-ieee80211.h"
 #include "packet-wifi-p2p.h"
 
 enum {
@@ -212,6 +213,7 @@ static const value_string p2p_service_protocol_types[] = {
   { 1, "Bonjour" },
   { 2, "UPnP" },
   { 3, "WS-Discovery" },
+  { 4, "Wi-Fi Display" },
   { 0, NULL }
 };
 
@@ -1013,7 +1015,7 @@ void dissect_wifi_p2p_anqp(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb,
   while (tvb_length_remaining(tvb, offset) >= (request ? 4 : 5)) {
     guint16 len;
     proto_tree *tlv;
-    guint8 type, id;
+    guint8 type, id, sd_proto;
 
     len = tvb_get_letohs(tvb, offset);
     if (len < 2) {
@@ -1037,6 +1039,7 @@ void dissect_wifi_p2p_anqp(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb,
 
     proto_tree_add_item(tlv, hf_p2p_anqp_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
     offset += 2;
+    sd_proto = tvb_get_guint8(tvb, offset);
     proto_tree_add_item(tlv, hf_p2p_anqp_service_protocol_type, tvb,
                         offset, 1, ENC_BIG_ENDIAN);
     proto_tree_add_item(tlv, hf_p2p_anqp_service_transaction_id, tvb,
@@ -1049,6 +1052,8 @@ void dissect_wifi_p2p_anqp(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb,
                           offset + 2, 1, ENC_BIG_ENDIAN);
       proto_tree_add_item(tlv, hf_p2p_anqp_response_data, tvb,
                           offset + 3, len - 3, ENC_NA);
+      if (sd_proto == 4)
+        dissect_wifi_display_ie(pinfo, tlv, tvb, offset + 3, len - 3);
     }
     offset += len;
   }