aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Holthuis <jan.holthuis@ruhr-uni-bochum.de>2017-09-12 15:53:32 +0200
committerAnders Broman <a.broman58@gmail.com>2018-02-15 12:53:16 +0000
commit7ae954c7ac934ea5748b6d65f1c04e8c9b90e27f (patch)
tree1195dc9e81c6e7122ec9f3e8f3a915af0e33e34b
parenta660215deab1ce881e9066e0d89ba93445fff7bf (diff)
steam-ihs: Add dissector for the Steam IHS Discovery Protocol
This adds a dissector for the Steam In-Home Streaming Discovery Protocol by Valve Software. Useful documentation can be found at: https://codingrange.com/blog/steam-in-home-streaming-discovery-protocol Change-Id: I26a79e201cfb0aad0ca702ac962e1e7b1b541517 Reviewed-on: https://code.wireshark.org/review/23615 Petri-Dish: Alexis La Goutte <alexis.lagoutte@gmail.com> Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman <a.broman58@gmail.com>
-rw-r--r--docbook/release-notes.asciidoc1
-rw-r--r--epan/dissectors/CMakeLists.txt1
-rw-r--r--epan/dissectors/Makefile.am1
-rw-r--r--epan/dissectors/packet-steam-ihs-discovery.c1476
4 files changed, 1479 insertions, 0 deletions
diff --git a/docbook/release-notes.asciidoc b/docbook/release-notes.asciidoc
index 20265c6cc8..61d1a42630 100644
--- a/docbook/release-notes.asciidoc
+++ b/docbook/release-notes.asciidoc
@@ -103,6 +103,7 @@ Protobuf (Protocol Buffers)
QUIC (IETF)
SolarEdge monitoring protocol
Session Multiplex Protocol
+Steam In-Home Streaming Discovery Protocol
Tibia
TWAMP and OWAMP
Wi-Fi Device Provisioning Protocol
diff --git a/epan/dissectors/CMakeLists.txt b/epan/dissectors/CMakeLists.txt
index 43fc4650ab..74393aef3e 100644
--- a/epan/dissectors/CMakeLists.txt
+++ b/epan/dissectors/CMakeLists.txt
@@ -1670,6 +1670,7 @@ set(DISSECTOR_SRC
${CMAKE_CURRENT_SOURCE_DIR}/packet-starteam.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-stat-notify.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-stat.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/packet-steam-ihs-discovery.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-stt.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-stun.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-sua.c
diff --git a/epan/dissectors/Makefile.am b/epan/dissectors/Makefile.am
index 7163b4c225..a6aecd496a 100644
--- a/epan/dissectors/Makefile.am
+++ b/epan/dissectors/Makefile.am
@@ -1292,6 +1292,7 @@ DISSECTOR_SRC = \
packet-starteam.c \
packet-stat-notify.c \
packet-stat.c \
+ packet-steam-ihs-discovery.c \
packet-stt.c \
packet-stun.c \
packet-sua.c \
diff --git a/epan/dissectors/packet-steam-ihs-discovery.c b/epan/dissectors/packet-steam-ihs-discovery.c
new file mode 100644
index 0000000000..e085406885
--- /dev/null
+++ b/epan/dissectors/packet-steam-ihs-discovery.c
@@ -0,0 +1,1476 @@
+/* packet-steam_ihs_discovery.c
+ * Routines for Steam In-Home Streaming Discovery Protocol dissection
+ * Copyright 2017, Jan Holthuis <jan.holthuis@ruhr-uni-bochum.de>
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * 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.
+ */
+
+/* Steam In-Home Streaming Discovery Protocol detects servers and negotiates
+ * connections to stream video games over the networks. It is used by
+ * Valve Software's Steam Client and Steam Link devices.
+ *
+ * Further Information:
+ * https://codingrange.com/blog/steam-in-home-streaming-discovery-protocol
+ * https://codingrange.com/blog/steam-in-home-streaming-control-protocol
+ */
+
+#include <config.h>
+
+#include <epan/packet.h> /* Should be first Wireshark include (other than config.h) */
+#include <epan/expert.h> /* Include only as needed */
+#include <epan/prefs.h> /* Include only as needed */
+
+/* Prototypes */
+/* (Required to prevent [-Wmissing-prototypes] warnings */
+void proto_reg_handoff_steam_ihs_discovery(void);
+void proto_register_steam_ihs_discovery(void);
+
+static int proto_steam_ihs_discovery = -1;
+
+static int hf_steam_ihs_discovery_signature = -1;
+static int hf_steam_ihs_discovery_header_length = -1;
+static int hf_steam_ihs_discovery_header_clientid = -1;
+static int hf_steam_ihs_discovery_header_msgtype = -1;
+static int hf_steam_ihs_discovery_header_instanceid = -1;
+static int hf_steam_ihs_discovery_body_length = -1;
+static int hf_steam_ihs_discovery_body_discovery_seqnum = -1;
+static int hf_steam_ihs_discovery_body_discovery_clientids = -1;
+static int hf_steam_ihs_discovery_body_status_version = -1;
+static int hf_steam_ihs_discovery_body_status_minversion = -1;
+static int hf_steam_ihs_discovery_body_status_connectport = -1;
+static int hf_steam_ihs_discovery_body_status_hostname = -1;
+static int hf_steam_ihs_discovery_body_status_enabledservices = -1;
+static int hf_steam_ihs_discovery_body_status_ostype = -1;
+static int hf_steam_ihs_discovery_body_status_is64bit = -1;
+static int hf_steam_ihs_discovery_body_status_euniverse = -1;
+static int hf_steam_ihs_discovery_body_status_timestamp = -1;
+static int hf_steam_ihs_discovery_body_status_screenlocked = -1;
+static int hf_steam_ihs_discovery_body_status_gamesrunning = -1;
+static int hf_steam_ihs_discovery_body_status_macaddresses = -1;
+static int hf_steam_ihs_discovery_body_status_user_steamid = -1;
+static int hf_steam_ihs_discovery_body_status_user_authkeyid = -1;
+static int hf_steam_ihs_discovery_body_authrequest_devicetoken = -1;
+static int hf_steam_ihs_discovery_body_authrequest_devicename = -1;
+static int hf_steam_ihs_discovery_body_authrequest_encryptedrequest = -1;
+static int hf_steam_ihs_discovery_body_authresponse_authresult = -1;
+static int hf_steam_ihs_discovery_body_streamingrequest_requestid = -1;
+static int hf_steam_ihs_discovery_body_streamingrequest_maximumresolutionx = -1;
+static int hf_steam_ihs_discovery_body_streamingrequest_maximumresolutiony = -1;
+static int hf_steam_ihs_discovery_body_streamingrequest_audiochannelcount = -1;
+static int hf_steam_ihs_discovery_body_streamingrequest_deviceversion = -1;
+static int hf_steam_ihs_discovery_body_streamingrequest_streamdesktop = -1;
+static int hf_steam_ihs_discovery_body_streamingrequest_devicetoken = -1;
+static int hf_steam_ihs_discovery_body_streamingrequest_pin = -1;
+static int hf_steam_ihs_discovery_body_streamingrequest_enablevideostreaming = -1;
+static int hf_steam_ihs_discovery_body_streamingrequest_enableaudiostreaming = -1;
+static int hf_steam_ihs_discovery_body_streamingrequest_enableinputstreaming = -1;
+static int hf_steam_ihs_discovery_body_streamingcancelrequest_requestid = -1;
+static int hf_steam_ihs_discovery_body_streamingresponse_requestid = -1;
+static int hf_steam_ihs_discovery_body_streamingresponse_result = -1;
+static int hf_steam_ihs_discovery_body_streamingresponse_port = -1;
+static int hf_steam_ihs_discovery_body_streamingresponse_encryptedsessionkey = -1;
+static int hf_steam_ihs_discovery_body_streamingresponse_virtualherelicenseddevicecount = -1;
+static int hf_steam_ihs_discovery_body_proofrequest_challenge = -1;
+static int hf_steam_ihs_discovery_body_proofresponse_response = -1;
+static int hf_steam_ihs_discovery_unknown_data = -1;
+static int hf_steam_ihs_discovery_unknown_number = -1;
+
+static const val64_string hf_steam_ihs_discovery_header_msgtype_strings[] = {
+ { 0, "Client Discovery" },
+ { 1, "Client Status" },
+ { 2, "Client Offline" },
+ { 3, "Device Authorization Request" },
+ { 4, "Device Authorization Response" },
+ { 5, "Device Streaming Request" },
+ { 6, "Device Streaming Response" },
+ { 7, "Device Proof Request" },
+ { 8, "Device Proof Response" },
+ { 9, "Device Authorization Cancel Request" },
+ { 10, "Device Streaming Cancel Request" },
+ { 0, NULL }
+};
+
+static const val64_string hf_steam_ihs_discovery_body_authresponse_authresult_strings[] = {
+ { 0, "Success" },
+ { 1, "Denied" },
+ { 2, "Not Logged In" },
+ { 3, "Offline" },
+ { 4, "Busy" },
+ { 5, "In Progress" },
+ { 6, "TimedOut" },
+ { 7, "Failed" },
+ { 8, "Canceled" },
+ { 0, NULL }
+};
+
+static const val64_string hf_steam_ihs_discovery_body_streamingresponse_result_strings[] = {
+ { 0, "Success" },
+ { 1, "Unauthorized" },
+ { 2, "Screen Locked" },
+ { 3, "Failed" },
+ { 4, "Busy" },
+ { 5, "In Progress" },
+ { 6, "Canceled" },
+ { 7, "Drivers Not Installed" },
+ { 8, "Disabled" },
+ { 9, "Broadcasting Active" },
+ { 10, "VR Active" },
+ { 11, "PIN Required" },
+ { 0, NULL }
+};
+
+static expert_field ei_steam_ihs_discovery_unknown_data = EI_INIT;
+static expert_field ei_steam_ihs_discovery_unknown_number = EI_INIT;
+static expert_field ei_steam_ihs_discovery_unknown_lengthdelimited = EI_INIT;
+static expert_field ei_steam_ihs_discovery_invalid_wiretype = EI_INIT;
+static expert_field ei_steam_ihs_discovery_invalid_length = EI_INIT;
+
+#define STEAM_IHS_DISCOVERY_UDP_PORT 27036
+static guint udp_port_pref = STEAM_IHS_DISCOVERY_UDP_PORT;
+
+/* Initialize the subtree pointers */
+static gint ett_steam_ihs_discovery = -1;
+static gint ett_steam_ihs_discovery_body_status_user = -1;
+
+#define STEAM_IHS_DISCOVERY_MIN_LENGTH 12
+#define STEAM_IHS_DISCOVERY_SIGNATURE_LENGTH 8
+#define STEAM_IHS_DISCOVERY_SIGNATURE_VALUE 0xFFFFFFFF214C5FA0
+
+/* Helper functions and structs for reading Protocol Buffers.
+ *
+ * Detailed information about protobuf message encoding can be found at:
+ * https://developers.google.com/protocol-buffers/docs/encoding#structure
+ */
+#define PROTOBUF_WIRETYPE_VARINT 0
+#define PROTOBUF_WIRETYPE_64BIT 1
+#define PROTOBUF_WIRETYPE_LENGTHDELIMITED 2
+#define PROTOBUF_WIRETYPE_32BIT 5
+
+static const char * const protobuf_wiretype_names[] = {"VarInt", "64-bit", "Length-delimited", "Start group", "End group", "32-bit"};
+static const char protobuf_wiretype_name_unknown[] = "Unknown";
+
+static const char* protobuf_get_wiretype_name(guint8 wire_type) {
+ if (wire_type <= 5) {
+ return protobuf_wiretype_names[wire_type];
+ }
+ return protobuf_wiretype_name_unknown;
+}
+
+static gint64
+get_varint64(tvbuff_t *tvb, gint offset, gint bytes_left, gint* len)
+{
+ guint8 b;
+ gint64 result = 0;
+ *len = 0;
+ while ((*len) < bytes_left) {
+ b = tvb_get_guint8(tvb, offset+(*len));
+ result |= ((gint64)b & 0x7f) << ((*len)*7);
+ (*len)++;
+ if ((b & 0x80) == 0) {
+ break;
+ }
+ }
+ return result;
+}
+
+typedef struct {
+ tvbuff_t *tvb;
+ gint offset;
+ gint bytes_left;
+} protobuf_desc_t;
+
+typedef struct {
+ guint64 value;
+ guint64 field_number;
+ guint8 wire_type;
+} protobuf_tag_t;
+
+static void
+protobuf_seek_forward(protobuf_desc_t* pb, gint len)
+{
+ pb->offset += len;
+ pb->bytes_left -= len;
+}
+
+static gint
+protobuf_iter_next(protobuf_desc_t* pb, protobuf_tag_t* tag)
+{
+ gint len;
+ if (pb->bytes_left <= 0) {
+ return 0;
+ }
+ tag->value = get_varint64(pb->tvb, pb->offset, pb->bytes_left, &len);
+ tag->field_number = tag->value >> 3;
+ tag->wire_type = tag->value & 0x7;
+ protobuf_seek_forward(pb, len);
+ return pb->bytes_left;
+}
+
+static gint
+protobuf_dissect_unknown_field(protobuf_desc_t *pb, protobuf_tag_t *tag, packet_info *pinfo, proto_tree *tree, proto_item** tiptr)
+{
+ gint len;
+ gint64 value;
+ proto_item* ti;
+
+ switch(tag->wire_type) {
+ case PROTOBUF_WIRETYPE_VARINT:
+ value = get_varint64(pb->tvb, pb->offset, pb->bytes_left, &len);
+ ti = proto_tree_add_uint64(tree, hf_steam_ihs_discovery_unknown_number, pb->tvb,
+ pb->offset, len, (guint64)value);
+ expert_add_info_format(pinfo, ti, &ei_steam_ihs_discovery_unknown_number, "Unknown numeric protobuf field (wire type %d = %s)", tag->wire_type, protobuf_get_wiretype_name(tag->wire_type));
+ break;
+ case PROTOBUF_WIRETYPE_64BIT:
+ len = 8;
+ ti = proto_tree_add_item(tree, hf_steam_ihs_discovery_unknown_number, pb->tvb, pb->offset+len, len, ENC_LITTLE_ENDIAN);
+ expert_add_info_format(pinfo, ti, &ei_steam_ihs_discovery_unknown_number, "Unknown numeric protobuf field (wire type %d = %s)", tag->wire_type, protobuf_get_wiretype_name(tag->wire_type));
+ break;
+ case PROTOBUF_WIRETYPE_LENGTHDELIMITED:
+ value = get_varint64(pb->tvb, pb->offset, pb->bytes_left, &len);
+ if((guint64)value > (guint64)(pb->bytes_left-len)) {
+ ti = proto_tree_add_item(tree, hf_steam_ihs_discovery_unknown_data, pb->tvb, pb->offset+len, pb->bytes_left-len, ENC_NA);
+ expert_add_info_format(pinfo, ti, &ei_steam_ihs_discovery_invalid_length, "Length-delimited field %"G_GUINT64_FORMAT" has length prefix %"G_GUINT64_FORMAT", but buffer is only %d bytes long.", tag->field_number, (guint64)value, (pb->bytes_left-len));
+ len = pb->bytes_left;
+ } else {
+ ti = proto_tree_add_item(tree, hf_steam_ihs_discovery_unknown_data, pb->tvb, pb->offset+len, (gint)value, ENC_NA);
+ len += (gint)value;
+ }
+ expert_add_info(pinfo, ti, &ei_steam_ihs_discovery_unknown_lengthdelimited);
+ break;
+ case PROTOBUF_WIRETYPE_32BIT:
+ len = 4;
+ ti = proto_tree_add_item(tree, hf_steam_ihs_discovery_unknown_number, pb->tvb, pb->offset+len, len, ENC_LITTLE_ENDIAN);
+ expert_add_info_format(pinfo, ti, &ei_steam_ihs_discovery_unknown_number, "Unknown numeric protobuf field (wire type %d = %s)", tag->wire_type, protobuf_get_wiretype_name(tag->wire_type));
+ break;
+ default:
+ len = pb->bytes_left;
+ ti = proto_tree_add_item(tree, hf_steam_ihs_discovery_unknown_data, pb->tvb, pb->offset, len, ENC_NA);
+ expert_add_info(pinfo, ti, &ei_steam_ihs_discovery_unknown_data);
+ break;
+ }
+ if(tiptr != NULL) {
+ *tiptr = ti;
+ }
+
+ return len;
+}
+
+static gint
+protobuf_verify_wiretype(protobuf_desc_t *pb, protobuf_tag_t *tag, packet_info *pinfo, proto_tree *tree, guint8 expected_wire_type)
+{
+ gint len;
+ gint64 len_prefix;
+ proto_item *ti = NULL;
+
+ if(expected_wire_type == tag->wire_type) {
+ if(expected_wire_type == PROTOBUF_WIRETYPE_LENGTHDELIMITED) {
+ len_prefix = get_varint64(pb->tvb, pb->offset, pb->bytes_left, &len);
+ if(len_prefix < 0 || len_prefix > G_MAXINT) {
+ ti = proto_tree_add_item(tree, hf_steam_ihs_discovery_unknown_data, pb->tvb, pb->offset+len, pb->bytes_left-len, ENC_NA);
+ expert_add_info_format(pinfo, ti, &ei_steam_ihs_discovery_invalid_length, "Length-delimited field %"G_GUINT64_FORMAT" has length prefix %"G_GINT64_FORMAT" outside valid range (0 <= x <= G_MAXINT).", tag->field_number, len_prefix);
+ return pb->bytes_left;
+ } else if(((gint)len_prefix) > (pb->bytes_left-len)) {
+ ti = proto_tree_add_item(tree, hf_steam_ihs_discovery_unknown_data, pb->tvb, pb->offset+len, pb->bytes_left-len, ENC_NA);
+ expert_add_info_format(pinfo, ti, &ei_steam_ihs_discovery_invalid_length, "Length-delimited field %"G_GUINT64_FORMAT" has length prefix %"G_GINT64_FORMAT", but buffer is only %d bytes long.", tag->field_number, len_prefix, (pb->bytes_left-len));
+ return pb->bytes_left;
+ }
+ }
+ return 0;
+ }
+ len = protobuf_dissect_unknown_field(pb, tag, pinfo, tree, &ti);
+
+ expert_add_info_format(pinfo, ti, &ei_steam_ihs_discovery_invalid_wiretype, "Expected wiretype %d (%s) for field %"G_GUINT64_FORMAT", but got %d (%s) instead.", expected_wire_type, protobuf_get_wiretype_name(expected_wire_type), tag->field_number, tag->wire_type, protobuf_get_wiretype_name(tag->wire_type));
+ return len;
+}
+
+/* The actual protocol-specific stuff */
+
+#define STEAMDISCOVER_FN_HEADER_CLIENTID 1
+#define STEAMDISCOVER_FN_HEADER_MSGTYPE 2
+#define STEAMDISCOVER_FN_HEADER_INSTANCEID 3
+
+#define STEAMDISCOVER_FN_DISCOVERY_SEQNUM 1
+#define STEAMDISCOVER_FN_DISCOVERY_CLIENTIDS 2
+
+#define STEAMDISCOVER_FN_STATUS_VERSION 1
+#define STEAMDISCOVER_FN_STATUS_MINVERSION 2
+#define STEAMDISCOVER_FN_STATUS_CONNECTPORT 3
+#define STEAMDISCOVER_FN_STATUS_HOSTNAME 4
+#define STEAMDISCOVER_FN_STATUS_ENABLEDSERVICES 6
+#define STEAMDISCOVER_FN_STATUS_OSTYPE 7
+#define STEAMDISCOVER_FN_STATUS_IS64BIT 8
+#define STEAMDISCOVER_FN_STATUS_USERS 9
+#define STEAMDISCOVER_FN_STATUS_EUNIVERSE 11
+#define STEAMDISCOVER_FN_STATUS_TIMESTAMP 12
+#define STEAMDISCOVER_FN_STATUS_SCREENLOCKED 13
+#define STEAMDISCOVER_FN_STATUS_GAMESRUNNING 14
+#define STEAMDISCOVER_FN_STATUS_MACADDRESSES 15
+#define STEAMDISCOVER_FN_STATUS_USER_STEAMID 1
+#define STEAMDISCOVER_FN_STATUS_USER_AUTHKEYID 2
+
+#define STEAMDISCOVER_FN_AUTHREQUEST_DEVICETOKEN 1
+#define STEAMDISCOVER_FN_AUTHREQUEST_DEVICENAME 2
+#define STEAMDISCOVER_FN_AUTHREQUEST_ENCRYPTEDREQUEST 3
+
+#define STEAMDISCOVER_FN_AUTHRESPONSE_AUTHRESULT 1
+
+#define STEAMDISCOVER_FN_STREAMINGREQUEST_REQUESTID 1
+#define STEAMDISCOVER_FN_STREAMINGREQUEST_MAXIMUMRESOLUTIONX 2
+#define STEAMDISCOVER_FN_STREAMINGREQUEST_MAXIMUMRESOLUTIONY 3
+#define STEAMDISCOVER_FN_STREAMINGREQUEST_AUDIOCHANNELCOUNT 4
+#define STEAMDISCOVER_FN_STREAMINGREQUEST_DEVICEVERSION 5
+#define STEAMDISCOVER_FN_STREAMINGREQUEST_STREAMDESKTOP 6
+#define STEAMDISCOVER_FN_STREAMINGREQUEST_DEVICETOKEN 7
+#define STEAMDISCOVER_FN_STREAMINGREQUEST_PIN 8
+#define STEAMDISCOVER_FN_STREAMINGREQUEST_ENABLEVIDEOSTREAMING 9
+#define STEAMDISCOVER_FN_STREAMINGREQUEST_ENABLEAUDIOSTREAMING 10
+#define STEAMDISCOVER_FN_STREAMINGREQUEST_ENABLEINPUTSTREAMING 11
+
+#define STEAMDISCOVER_FN_STREAMINGCANCELREQUEST_REQUESTID 1
+
+#define STEAMDISCOVER_FN_STREAMINGRESPONSE_REQUESTID 1
+#define STEAMDISCOVER_FN_STREAMINGRESPONSE_RESULT 2
+#define STEAMDISCOVER_FN_STREAMINGRESPONSE_PORT 3
+#define STEAMDISCOVER_FN_STREAMINGRESPONSE_ENCRYPTEDSESSIONKEY 4
+#define STEAMDISCOVER_FN_STREAMINGRESPONSE_VIRTUALHERELICENSEDDEVICECOUNT 5
+
+#define STEAMDISCOVER_FN_PROOFREQUEST_CHALLENGE 1
+#define STEAMDISCOVER_FN_PROOFRESPONSE_RESPONSE 1
+
+#define STEAMDISCOVER_MSGTYPE_CLIENTBROADCASTMSGDISCOVERY 0
+#define STEAMDISCOVER_MSGTYPE_CLIENTBROADCASTMSGSTATUS 1
+#define STEAMDISCOVER_MSGTYPE_CLIENTBROADCASTMSGOFFLINE 2
+#define STEAMDISCOVER_MSGTYPE_DEVICEAUTHORIZATIONREQUEST 3
+#define STEAMDISCOVER_MSGTYPE_DEVICEAUTHORIZATIONRESPONSE 4
+#define STEAMDISCOVER_MSGTYPE_DEVICESTREAMINGREQUEST 5
+#define STEAMDISCOVER_MSGTYPE_DEVICESTREAMINGRESPONSE 6
+#define STEAMDISCOVER_MSGTYPE_DEVICEPROOFREQUEST 7
+#define STEAMDISCOVER_MSGTYPE_DEVICEPROOFRESPONSE 8
+#define STEAMDISCOVER_MSGTYPE_DEVICEAUTHORIZATIONCANCELREQUEST 9
+#define STEAMDISCOVER_MSGTYPE_DEVICESTREAMINGCANCELREQUEST 10
+#define STEAMDISCOVER_MSGTYPES_MAX 10
+
+#define STEAMDISCOVER_ENSURE_WIRETYPE(X) if((len = protobuf_verify_wiretype(&pb, &tag, pinfo, tree, X))) break;
+
+/* Dissect the header section of a packet. The header is a
+ * CMsgRemoteClientBroadcastHeader protobuf message.
+ *
+ * enum ERemoteClientBroadcastMsg {
+ * k_ERemoteClientBroadcastMsgDiscovery = 0;
+ * k_ERemoteClientBroadcastMsgStatus = 1;
+ * k_ERemoteClientBroadcastMsgOffline = 2;
+ * k_ERemoteDeviceAuthorizationRequest = 3;
+ * k_ERemoteDeviceAuthorizationResponse = 4;
+ * k_ERemoteDeviceStreamingRequest = 5;
+ * k_ERemoteDeviceStreamingResponse = 6;
+ * k_ERemoteDeviceProofRequest = 7;
+ * k_ERemoteDeviceProofResponse = 8;
+ * k_ERemoteDeviceAuthorizationCancelRequest = 9;
+ * k_ERemoteDeviceStreamingCancelRequest = 10;
+ * }
+ *
+ * message CMsgRemoteClientBroadcastHeader {
+ * optional uint64 client_id = 1;
+ * optional ERemoteClientBroadcastMsg msg_type = 2;
+ * optional uint64 instance_id = 3;
+ * }
+ */
+static gint64
+steamdiscover_dissect_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gint offset, gint bytes_left)
+{
+ gint len;
+ gint64 value;
+ gint64 msg_type = -1;
+ protobuf_desc_t pb = { tvb, offset, bytes_left };
+ protobuf_tag_t tag = { 0, 0, 0 };
+ while (protobuf_iter_next(&pb, &tag)) {
+ switch(tag.field_number) {
+ case STEAMDISCOVER_FN_HEADER_CLIENTID:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_uint64(tree, hf_steam_ihs_discovery_header_clientid, pb.tvb,
+ pb.offset, len, (guint64)value);
+ break;
+ case STEAMDISCOVER_FN_HEADER_MSGTYPE:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ msg_type = value;
+ proto_tree_add_uint64(tree, hf_steam_ihs_discovery_header_msgtype, pb.tvb,
+ pb.offset, len, (guint64)value);
+ break;
+ case STEAMDISCOVER_FN_HEADER_INSTANCEID:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_uint64(tree, hf_steam_ihs_discovery_header_instanceid, pb.tvb,
+ pb.offset, len, (guint64)value);
+ break;
+ default:
+ len = protobuf_dissect_unknown_field(&pb, &tag, pinfo, tree, NULL);
+ break;
+ }
+ protobuf_seek_forward(&pb, len);
+ }
+ return msg_type;
+}
+
+/* Dissect a CMsgRemoteClientBroadcastDiscovery protobuf message body.
+ *
+ * message CMsgRemoteClientBroadcastDiscovery {
+ * optional uint32 seq_num = 1;
+ * repeated uint64 client_ids = 2;
+ * }
+ */
+static void
+steamdiscover_dissect_body_discovery(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gint offset, gint bytes_left)
+{
+ gint len;
+ gint64 value;
+ protobuf_desc_t pb = { tvb, offset, bytes_left };
+ protobuf_tag_t tag = { 0, 0, 0 };
+ while (protobuf_iter_next(&pb, &tag)) {
+ switch(tag.field_number) {
+ case STEAMDISCOVER_FN_DISCOVERY_SEQNUM:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_uint(tree, hf_steam_ihs_discovery_body_discovery_seqnum, pb.tvb,
+ pb.offset, len, (guint32)value);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Seq=%"G_GUINT32_FORMAT, (guint32)value);
+ break;
+ case STEAMDISCOVER_FN_DISCOVERY_CLIENTIDS:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_uint64(tree, hf_steam_ihs_discovery_body_discovery_clientids, pb.tvb,
+ pb.offset, len, value);
+ break;
+ default:
+ len = protobuf_dissect_unknown_field(&pb, &tag, pinfo, tree, NULL);
+ break;
+ }
+ protobuf_seek_forward(&pb, len);
+ }
+}
+
+/* Dissect a CMsgRemoteClientBroadcastStatus protobuf message body.
+ *
+ * message CMsgRemoteClientBroadcastStatus {
+ * message User {
+ * optional fixed64 steamid = 1;
+ * optional uint32 auth_key_id = 2;
+ * }
+ * optional int32 version = 1;
+ * optional int32 min_version = 2;
+ * optional uint32 connect_port = 3;
+ * optional string hostname = 4;
+ * optional uint32 enabled_services = 6;
+ * optional int32 ostype = 7 [default = 0];
+ * optional bool is64bit = 8 [default = false];
+ * repeated CMsgRemoteClientBroadcastStatus.User users = 9;
+ * optional int32 euniverse = 11;
+ * optional uint32 timestamp = 12;
+ * optional bool screen_locked = 13;
+ * optional bool games_running = 14;
+ * repeated string mac_addresses = 15;
+ * optional uint32 download_lan_peer_group = 16;
+ * optional bool broadcasting_active = 17;
+ * optional bool vr_active = 18;
+ * }
+ */
+static void
+steamdiscover_dissect_body_status(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gint offset, gint bytes_left)
+{
+ gint64 value;
+ gint len;
+ gint len2;
+ protobuf_desc_t pb = { tvb, offset, bytes_left };
+ protobuf_desc_t pb2 = { tvb, 0, 0 };
+ protobuf_tag_t tag = { 0, 0, 0 };
+ wmem_allocator_t* strpool;
+ guint8 *hostname;
+ strpool = wmem_allocator_new(WMEM_ALLOCATOR_SIMPLE);
+ nstime_t timestamp;
+ proto_tree *user_tree;
+ proto_item *user_it;
+ while (protobuf_iter_next(&pb, &tag)) {
+ switch(tag.field_number) {
+ case STEAMDISCOVER_FN_STATUS_VERSION:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_int(tree, hf_steam_ihs_discovery_body_status_version, pb.tvb,
+ pb.offset, len, (gint32)value);
+ break;
+ case STEAMDISCOVER_FN_STATUS_MINVERSION:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_int(tree, hf_steam_ihs_discovery_body_status_minversion, pb.tvb,
+ pb.offset, len, (gint32)value);
+ break;
+ case STEAMDISCOVER_FN_STATUS_CONNECTPORT:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_uint(tree, hf_steam_ihs_discovery_body_status_connectport, pb.tvb,
+ pb.offset, len, (guint32)value);
+ break;
+ case STEAMDISCOVER_FN_STATUS_HOSTNAME:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_LENGTHDELIMITED);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_item(tree, hf_steam_ihs_discovery_body_status_hostname, pb.tvb,
+ pb.offset+len, (gint)value, ENC_UTF_8|ENC_NA);
+ hostname = tvb_get_string_enc(strpool, pb.tvb, pb.offset+len, (gint)value, ENC_UTF_8);
+ if(hostname && strlen(hostname)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s from %s", hf_steam_ihs_discovery_header_msgtype_strings[STEAMDISCOVER_MSGTYPE_CLIENTBROADCASTMSGSTATUS].strptr, hostname);
+ }
+ len += (gint)value;
+ break;
+ case STEAMDISCOVER_FN_STATUS_ENABLEDSERVICES:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_uint(tree, hf_steam_ihs_discovery_body_status_enabledservices, pb.tvb,
+ pb.offset, len, (guint32)value);
+ break;
+ case STEAMDISCOVER_FN_STATUS_OSTYPE:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_int(tree, hf_steam_ihs_discovery_body_status_ostype, pb.tvb,
+ pb.offset, len, (gint32)value);
+ break;
+ case STEAMDISCOVER_FN_STATUS_IS64BIT:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_boolean(tree, hf_steam_ihs_discovery_body_status_is64bit, pb.tvb,
+ pb.offset, len, (gint32)value);
+ break;
+ case STEAMDISCOVER_FN_STATUS_USERS:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_LENGTHDELIMITED);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ pb2.offset = pb.offset+len;
+ pb2.bytes_left = (gint)value;
+ len += (gint)value;
+ user_tree = proto_tree_add_subtree(tree, pb.tvb, pb.offset, len, ett_steam_ihs_discovery_body_status_user, &user_it, "User");
+ while (protobuf_iter_next(&pb2, &tag)) {
+ switch(tag.field_number) {
+ case STEAMDISCOVER_FN_STATUS_USER_STEAMID:
+ if((len2 = protobuf_verify_wiretype(&pb2, &tag, pinfo, user_tree, PROTOBUF_WIRETYPE_64BIT))) break;
+ len2 = 8;
+ value = tvb_get_letoh64(pb2.tvb, pb2.offset);
+ proto_tree_add_uint64(user_tree, hf_steam_ihs_discovery_body_status_user_steamid, pb2.tvb,
+ pb2.offset, len2, (guint64)value);
+ proto_item_append_text(user_it, ", Steam ID: %"G_GUINT64_FORMAT, (guint64)value);
+ break;
+ case STEAMDISCOVER_FN_STATUS_USER_AUTHKEYID:
+ if((len2 = protobuf_verify_wiretype(&pb2, &tag, pinfo, user_tree, PROTOBUF_WIRETYPE_VARINT))) break;
+ value = get_varint64(pb2.tvb, pb2.offset, pb2.bytes_left, &len2);
+ proto_tree_add_uint(user_tree, hf_steam_ihs_discovery_body_status_user_authkeyid, pb2.tvb,
+ pb2.offset, len2, (guint32)value);
+ proto_item_append_text(user_it, ", Auth Key ID: %"G_GUINT32_FORMAT, (guint32)value);
+ break;
+ default:
+ len2 = protobuf_dissect_unknown_field(&pb2, &tag, pinfo, tree, NULL);
+ break;
+ }
+ protobuf_seek_forward(&pb2, len2);
+ }
+ break;
+ case STEAMDISCOVER_FN_STATUS_EUNIVERSE:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_int(tree, hf_steam_ihs_discovery_body_status_euniverse, pb.tvb,
+ pb.offset, len, (gint32)value);
+ break;
+ case STEAMDISCOVER_FN_STATUS_TIMESTAMP:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ timestamp.secs = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_time(tree, hf_steam_ihs_discovery_body_status_timestamp, pb.tvb,
+ pb.offset, len, &timestamp);
+ break;
+ case STEAMDISCOVER_FN_STATUS_SCREENLOCKED:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_boolean(tree, hf_steam_ihs_discovery_body_status_screenlocked, pb.tvb,
+ pb.offset, len, (gint32)value);
+ break;
+ case STEAMDISCOVER_FN_STATUS_GAMESRUNNING:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_boolean(tree, hf_steam_ihs_discovery_body_status_gamesrunning, pb.tvb,
+ pb.offset, len, (gint32)value);
+ break;
+ case STEAMDISCOVER_FN_STATUS_MACADDRESSES:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_LENGTHDELIMITED);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_item(tree, hf_steam_ihs_discovery_body_status_macaddresses, pb.tvb,
+ pb.offset+len, (gint)value, ENC_UTF_8|ENC_NA);
+ len += (gint)value;
+ break;
+ default:
+ len = protobuf_dissect_unknown_field(&pb, &tag, pinfo, tree, NULL);
+ break;
+ }
+ protobuf_seek_forward(&pb, len);
+ }
+ wmem_destroy_allocator(strpool);
+}
+
+/* Dissect a CMsgRemoteDeviceAuthorizationRequest protobuf message body.
+ *
+ * message CMsgRemoteDeviceAuthorizationRequest {
+ * message CKeyEscrow_Ticket {
+ * optional bytes password = 1;
+ * optional uint64 identifier = 2;
+ * optional bytes payload = 3;
+ * optional uint32 timestamp = 4;
+ * optional CMsgRemoteDeviceAuthorizationRequest.EKeyEscrowUsage usage = 5;
+ * optional string device_name = 6;
+ * optional string device_model = 7;
+ * optional string device_serial = 8;
+ * optional uint32 device_provisioning_id = 9;
+ * }
+ * enum EKeyEscrowUsage {
+ * k_EKeyEscrowUsageStreamingDevice = 0;
+ * }
+ * required bytes device_token = 1;
+ * optional string device_name = 2;
+ * required bytes encrypted_request = 3;
+ * }
+ */
+static void
+steamdiscover_dissect_body_authrequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gint offset, gint bytes_left)
+{
+ guint len;
+ gint64 value;
+ protobuf_desc_t pb = { tvb, offset, bytes_left };
+ protobuf_tag_t tag = { 0, 0, 0 };
+ wmem_allocator_t *strpool;
+ strpool = wmem_allocator_new(WMEM_ALLOCATOR_SIMPLE);
+ guint8* devicename;
+ while (protobuf_iter_next(&pb, &tag)) {
+ switch(tag.field_number) {
+ case STEAMDISCOVER_FN_AUTHREQUEST_DEVICETOKEN:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_LENGTHDELIMITED);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_item(tree, hf_steam_ihs_discovery_body_authrequest_devicetoken, pb.tvb,
+ pb.offset+len, (gint)value, ENC_NA);
+ len += (gint)value;
+ break;
+ case STEAMDISCOVER_FN_AUTHREQUEST_DEVICENAME:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_LENGTHDELIMITED);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_item(tree, hf_steam_ihs_discovery_body_authrequest_devicename, pb.tvb,
+ pb.offset+len, (gint)value, ENC_UTF_8|ENC_NA);
+ devicename = tvb_get_string_enc(strpool, pb.tvb, pb.offset+len, (gint)value, ENC_UTF_8);
+ if (devicename && strlen(devicename)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, " from %s", devicename);
+ }
+ len += (gint)value;
+ break;
+ case STEAMDISCOVER_FN_AUTHREQUEST_ENCRYPTEDREQUEST:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_LENGTHDELIMITED);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_item(tree, hf_steam_ihs_discovery_body_authrequest_encryptedrequest, pb.tvb,
+ pb.offset+len, (gint)value, ENC_NA);
+ len += (gint)value;
+ break;
+ default:
+ len = protobuf_dissect_unknown_field(&pb, &tag, pinfo, tree, NULL);
+ break;
+ }
+ protobuf_seek_forward(&pb, len);
+ }
+ wmem_destroy_allocator(strpool);
+}
+
+/* Dissect a CMsgRemoteDeviceAuthorizationResponse protobuf message body.
+ *
+ * message CMsgRemoteDeviceAuthorizationResponse {
+ * required ERemoteDeviceAuthorizationResult result = 1;
+ * }
+ */
+static void
+steamdiscover_dissect_body_authresponse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gint offset, gint bytes_left)
+{
+ gint len;
+ gint64 value;
+ protobuf_desc_t pb = { tvb, offset, bytes_left };
+ protobuf_tag_t tag = { 0, 0, 0 };
+ while (protobuf_iter_next(&pb, &tag)) {
+ switch(tag.field_number) {
+ case STEAMDISCOVER_FN_AUTHRESPONSE_AUTHRESULT:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_uint64(tree, hf_steam_ihs_discovery_body_authresponse_authresult, pb.tvb,
+ pb.offset, len, (guint64)value);
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s Result=%"G_GUINT64_FORMAT"(%s)", hf_steam_ihs_discovery_header_msgtype_strings[STEAMDISCOVER_MSGTYPE_DEVICEAUTHORIZATIONRESPONSE].strptr,
+ (guint64)value, val64_to_str_const((guint64)value, hf_steam_ihs_discovery_body_authresponse_authresult_strings, "Unknown"));
+ break;
+ default:
+ len = protobuf_dissect_unknown_field(&pb, &tag, pinfo, tree, NULL);
+ break;
+ }
+ protobuf_seek_forward(&pb, len);
+ }
+}
+
+/* Dissect a CMsgRemoteDeviceStreamingRequest protobuf message body.
+ *
+ * message CMsgRemoteDeviceStreamingRequest {
+ * required uint32 request_id = 1;
+ * optional int32 maximum_resolution_x = 2;
+ * optional int32 maximum_resolution_y = 3;
+ * optional int32 audio_channel_count = 4 [default = 2];
+ * optional string device_version = 5;
+ * optional bool stream_desktop = 6;
+ * optional bytes device_token = 7;
+ * optional bytes pin = 8;
+ * optional bool enable_video_streaming = 9 [default = true];
+ * optional bool enable_audio_streaming = 10 [default = true];
+ * optional bool enable_input_streaming = 11 [default = true];
+ * }
+ */
+static void
+steamdiscover_dissect_body_streamingrequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gint offset, gint bytes_left)
+{
+ gint len;
+ gint64 value;
+ protobuf_desc_t pb = { tvb, offset, bytes_left };
+ protobuf_tag_t tag = { 0, 0, 0 };
+ while (protobuf_iter_next(&pb, &tag)) {
+ switch(tag.field_number) {
+ case STEAMDISCOVER_FN_STREAMINGREQUEST_REQUESTID:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_uint(tree, hf_steam_ihs_discovery_body_streamingrequest_requestid, pb.tvb,
+ pb.offset, len, (guint32)value);
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s ID=%08x", hf_steam_ihs_discovery_header_msgtype_strings[STEAMDISCOVER_MSGTYPE_DEVICESTREAMINGREQUEST].strptr, (guint32)value);
+ break;
+ case STEAMDISCOVER_FN_STREAMINGREQUEST_MAXIMUMRESOLUTIONX:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_int(tree, hf_steam_ihs_discovery_body_streamingrequest_maximumresolutionx, pb.tvb,
+ pb.offset, len, (gint32)value);
+ break;
+ case STEAMDISCOVER_FN_STREAMINGREQUEST_MAXIMUMRESOLUTIONY:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_int(tree, hf_steam_ihs_discovery_body_streamingrequest_maximumresolutiony, pb.tvb,
+ pb.offset, len, (gint32)value);
+ break;
+ case STEAMDISCOVER_FN_STREAMINGREQUEST_AUDIOCHANNELCOUNT:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_int(tree, hf_steam_ihs_discovery_body_streamingrequest_audiochannelcount, pb.tvb,
+ pb.offset, len, (gint32)value);
+ break;
+ case STEAMDISCOVER_FN_STREAMINGREQUEST_DEVICEVERSION:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_LENGTHDELIMITED);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_item(tree, hf_steam_ihs_discovery_body_streamingrequest_deviceversion, pb.tvb, pb.offset+len, (gint)value, ENC_UTF_8|ENC_NA);
+ len += (gint)value;
+ break;
+ case STEAMDISCOVER_FN_STREAMINGREQUEST_STREAMDESKTOP:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_boolean(tree, hf_steam_ihs_discovery_body_streamingrequest_streamdesktop, pb.tvb,
+ pb.offset, len, (gint32)value);
+ break;
+ case STEAMDISCOVER_FN_STREAMINGREQUEST_DEVICETOKEN:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_LENGTHDELIMITED);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_item(tree, hf_steam_ihs_discovery_body_streamingrequest_devicetoken, pb.tvb, pb.offset+len, (gint)value, ENC_NA);
+ len += (gint)value;
+ break;
+ case STEAMDISCOVER_FN_STREAMINGREQUEST_PIN:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_LENGTHDELIMITED);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_item(tree, hf_steam_ihs_discovery_body_streamingrequest_pin, pb.tvb, pb.offset+len, (gint)value, ENC_NA);
+ len += (gint)value;
+ break;
+ case STEAMDISCOVER_FN_STREAMINGREQUEST_ENABLEVIDEOSTREAMING:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_boolean(tree, hf_steam_ihs_discovery_body_streamingrequest_enablevideostreaming, pb.tvb,
+ pb.offset, len, (gint32)value);
+ break;
+ case STEAMDISCOVER_FN_STREAMINGREQUEST_ENABLEAUDIOSTREAMING:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_boolean(tree, hf_steam_ihs_discovery_body_streamingrequest_enableaudiostreaming, pb.tvb,
+ pb.offset, len, (gint32)value);
+ break;
+ case STEAMDISCOVER_FN_STREAMINGREQUEST_ENABLEINPUTSTREAMING:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_boolean(tree, hf_steam_ihs_discovery_body_streamingrequest_enableinputstreaming, pb.tvb,
+ pb.offset, len, (gint32)value);
+ break;
+ default:
+ len = protobuf_dissect_unknown_field(&pb, &tag, pinfo, tree, NULL);
+ break;
+ }
+ protobuf_seek_forward(&pb, len);
+ }
+}
+
+/* Dissect a CMsgRemoteDeviceStreamingCancelRequest protobuf message body.
+ *
+ * message CMsgRemoteDeviceStreamingCancelRequest {
+ * required uint32 request_id = 1;
+ * }
+ */
+static void
+steamdiscover_dissect_body_streamingcancelrequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gint offset, gint bytes_left)
+{
+ guint len;
+ gint64 value;
+ protobuf_desc_t pb = { tvb, offset, bytes_left };
+ protobuf_tag_t tag = { 0, 0, 0 };
+ while (protobuf_iter_next(&pb, &tag)) {
+ switch(tag.field_number) {
+ case STEAMDISCOVER_FN_STREAMINGCANCELREQUEST_REQUESTID:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_uint(tree, hf_steam_ihs_discovery_body_streamingcancelrequest_requestid, pb.tvb,
+ pb.offset, len, (guint32)value);
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s, ID=%08x", hf_steam_ihs_discovery_header_msgtype_strings[STEAMDISCOVER_MSGTYPE_DEVICESTREAMINGCANCELREQUEST].strptr, (guint32)value);
+ break;
+ default:
+ len = protobuf_dissect_unknown_field(&pb, &tag, pinfo, tree, NULL);
+ break;
+ }
+ protobuf_seek_forward(&pb, len);
+ }
+}
+
+/* Dissect a CMsgRemoteDeviceStreamingResponse protobuf message body.
+ *
+ * enum ERemoteDeviceStreamingResult {
+ * k_ERemoteDeviceStreamingSuccess = 0;
+ * k_ERemoteDeviceStreamingUnauthorized = 1;
+ * k_ERemoteDeviceStreamingScreenLocked = 2;
+ * k_ERemoteDeviceStreamingFailed = 3;
+ * k_ERemoteDeviceStreamingBusy = 4;
+ * k_ERemoteDeviceStreamingInProgress = 5;
+ * k_ERemoteDeviceStreamingCanceled = 6;
+ * k_ERemoteDeviceStreamingDriversNotInstalled = 7;
+ * k_ERemoteDeviceStreamingDisabled = 8;
+ * k_ERemoteDeviceStreamingBroadcastingActive = 9;
+ * k_ERemoteDeviceStreamingVRActive = 10;
+ * k_ERemoteDeviceStreamingPINRequired = 11;
+ * }
+ *
+ * message CMsgRemoteDeviceStreamingResponse {
+ * required uint32 request_id = 1;
+ * required ERemoteDeviceStreamingResult result = 2;
+ * optional uint32 port = 3;
+ * optional bytes encrypted_session_key = 4;
+ * optional int32 virtualhere_licensed_device_count_OBSOLETE = 5;
+ * }
+ */
+static void
+steamdiscover_dissect_body_streamingresponse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gint offset, gint bytes_left)
+{
+ guint len;
+ gint64 value;
+ protobuf_desc_t pb = { tvb, offset, bytes_left };
+ protobuf_tag_t tag = { 0, 0, 0 };
+ while (protobuf_iter_next(&pb, &tag)) {
+ switch(tag.field_number) {
+ case STEAMDISCOVER_FN_STREAMINGRESPONSE_REQUESTID:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_uint(tree, hf_steam_ihs_discovery_body_streamingresponse_requestid, pb.tvb,
+ pb.offset, len, (guint32)value);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " ID=%08x", (guint32)value);
+ break;
+ case STEAMDISCOVER_FN_STREAMINGRESPONSE_RESULT:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_uint64(tree, hf_steam_ihs_discovery_body_streamingresponse_result, pb.tvb,
+ pb.offset, len, (guint64)value);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Result=%"G_GUINT64_FORMAT"(%s)", (guint64)value, val64_to_str_const((guint64)value, hf_steam_ihs_discovery_body_streamingresponse_result_strings, "Unknown"));
+ break;
+ case STEAMDISCOVER_FN_STREAMINGRESPONSE_PORT:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_uint(tree, hf_steam_ihs_discovery_body_streamingresponse_port, pb.tvb,
+ pb.offset, len, (guint32)value);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Port=%"G_GUINT32_FORMAT, (guint32)value);
+ break;
+ case STEAMDISCOVER_FN_STREAMINGRESPONSE_ENCRYPTEDSESSIONKEY:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_LENGTHDELIMITED);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_item(tree, hf_steam_ihs_discovery_body_streamingresponse_encryptedsessionkey, pb.tvb, pb.offset+len, (gint)value, ENC_NA);
+ len += (gint)value;
+ break;
+ case STEAMDISCOVER_FN_STREAMINGRESPONSE_VIRTUALHERELICENSEDDEVICECOUNT:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_int(tree, hf_steam_ihs_discovery_body_streamingresponse_virtualherelicenseddevicecount, pb.tvb,
+ pb.offset, len, (gint32)value);
+ break;
+ default:
+ len = protobuf_dissect_unknown_field(&pb, &tag, pinfo, tree, NULL);
+ break;
+ }
+ protobuf_seek_forward(&pb, len);
+ }
+}
+
+/* Dissect a CMsgRemoteDeviceProofRequest protobuf message body.
+ *
+ * message CMsgRemoteDeviceProofRequest {
+ * required bytes challenge = 1;
+ * }
+ */
+static void
+steamdiscover_dissect_body_proofrequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gint offset, gint bytes_left)
+{
+ gint len;
+ gint64 value;
+ protobuf_desc_t pb = { tvb, offset, bytes_left };
+ protobuf_tag_t tag = { 0, 0, 0 };
+ while (protobuf_iter_next(&pb, &tag)) {
+ switch(tag.field_number) {
+ case STEAMDISCOVER_FN_PROOFREQUEST_CHALLENGE:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_LENGTHDELIMITED);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_item(tree, hf_steam_ihs_discovery_body_proofrequest_challenge, pb.tvb, pb.offset+len, (gint)value, ENC_NA);
+ len += (gint)value;
+ break;
+ default:
+ len = protobuf_dissect_unknown_field(&pb, &tag, pinfo, tree, NULL);
+ break;
+ }
+ protobuf_seek_forward(&pb, len);
+ }
+}
+
+/* Dissect a CMsgRemoteDeviceProofResponse protobuf message body.
+ *
+ * message CMsgRemoteDeviceProofResponse {
+ * required bytes response = 1;
+ * }
+ */
+static void
+steamdiscover_dissect_body_proofresponse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gint offset, gint bytes_left)
+{
+ gint len;
+ gint64 value;
+ protobuf_desc_t pb = { tvb, offset, bytes_left };
+ protobuf_tag_t tag = { 0, 0, 0 };
+ while (protobuf_iter_next(&pb, &tag)) {
+ switch(tag.field_number) {
+ case STEAMDISCOVER_FN_PROOFRESPONSE_RESPONSE:
+ STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_LENGTHDELIMITED);
+ value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
+ proto_tree_add_item(tree, hf_steam_ihs_discovery_body_proofresponse_response, pb.tvb, pb.offset+len, (gint)value, ENC_NA);
+ len += (gint)value;
+ break;
+ default:
+ len = protobuf_dissect_unknown_field(&pb, &tag, pinfo, tree, NULL);
+ break;
+ }
+ protobuf_seek_forward(&pb, len);
+ }
+}
+
+static void
+steamdiscover_dissect_body_unknown(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ gint offset, gint bytes_left)
+{
+ gint len;
+ protobuf_desc_t pb = { tvb, offset, bytes_left };
+ protobuf_tag_t tag = { 0, 0, 0 };
+ while (protobuf_iter_next(&pb, &tag)) {
+ len = protobuf_dissect_unknown_field(&pb, &tag, pinfo, tree, NULL);
+ protobuf_seek_forward(&pb, len);
+ }
+}
+
+/* Code to actually dissect the packets */
+static int
+dissect_steam_ihs_discovery(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ void *data _U_)
+{
+ /* Set up structures needed to add the protocol subtree and manage it */
+ proto_item *ti;
+ proto_tree *steam_ihs_discovery_tree;
+ /* Other misc. local variables. */
+ gint offset = 0;
+ gint header_length = 0;
+ gint body_length = 0;
+ gint total_length = 0;
+ gint64 msg_type;
+
+ /* Check that the packet is long enough for it to belong to us. */
+ if (tvb_reported_length(tvb) < STEAM_IHS_DISCOVERY_MIN_LENGTH)
+ return 0;
+
+ if (tvb_captured_length(tvb) < STEAM_IHS_DISCOVERY_MIN_LENGTH)
+ return 0;
+
+ /* Check if packet starts with the 8 byte signature value. */
+ if (tvb_get_ntoh64(tvb, 0) != STEAM_IHS_DISCOVERY_SIGNATURE_VALUE)
+ return 0;
+
+ /* Parse header and body lengths.
+ *
+ * A packet looks like this:
+ * 1. Signature Value (8 bytes)
+ * 2. Header length (4 bytes)
+ * 3. Header
+ * 4. Body length (4 bytes)
+ * 6. Body
+ * */
+ header_length = tvb_get_letohl(tvb, STEAM_IHS_DISCOVERY_SIGNATURE_LENGTH);
+ body_length = tvb_get_letohl(tvb, STEAM_IHS_DISCOVERY_SIGNATURE_LENGTH + 4 + header_length);
+ total_length = STEAM_IHS_DISCOVERY_SIGNATURE_LENGTH + 4 + header_length + 4 + body_length;
+
+ /* Check if expected and captured packet length are equal. */
+ if (tvb_reported_length(tvb) != (guint)total_length)
+ return 0;
+
+ if (tvb_captured_length(tvb) != (guint)total_length)
+ return 0;
+
+ /* Set the Protocol column to the constant string of steam_ihs_discovery */
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "STEAMDISCOVER");
+
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ /* create display subtree for the protocol */
+ ti = proto_tree_add_item(tree, proto_steam_ihs_discovery, tvb, 0, -1, ENC_NA);
+
+ steam_ihs_discovery_tree = proto_item_add_subtree(ti, ett_steam_ihs_discovery);
+
+ proto_tree_add_item(steam_ihs_discovery_tree, hf_steam_ihs_discovery_signature, tvb,
+ offset, STEAM_IHS_DISCOVERY_SIGNATURE_LENGTH, ENC_LITTLE_ENDIAN);
+ offset += STEAM_IHS_DISCOVERY_SIGNATURE_LENGTH;
+
+ proto_tree_add_item(steam_ihs_discovery_tree, hf_steam_ihs_discovery_header_length, tvb,
+ offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ msg_type = steamdiscover_dissect_header(tvb, pinfo, steam_ihs_discovery_tree, offset, header_length);
+
+ if ((0 <= msg_type) && (msg_type <= STEAMDISCOVER_MSGTYPES_MAX)) {
+ col_set_str(pinfo->cinfo, COL_INFO, hf_steam_ihs_discovery_header_msgtype_strings[msg_type].strptr);
+ } else {
+ col_set_str(pinfo->cinfo, COL_INFO, "Unknown Message");
+ }
+
+ offset += header_length;
+
+ proto_tree_add_item(steam_ihs_discovery_tree, hf_steam_ihs_discovery_body_length, tvb,
+ offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ switch(msg_type)
+ {
+ case STEAMDISCOVER_MSGTYPE_CLIENTBROADCASTMSGDISCOVERY:
+ steamdiscover_dissect_body_discovery(tvb, pinfo, steam_ihs_discovery_tree, offset, body_length);
+ break;
+ case STEAMDISCOVER_MSGTYPE_CLIENTBROADCASTMSGSTATUS:
+ steamdiscover_dissect_body_status(tvb, pinfo, steam_ihs_discovery_tree, offset, body_length);
+ break;
+ case STEAMDISCOVER_MSGTYPE_CLIENTBROADCASTMSGOFFLINE:
+ /* Message seems to have no body */
+ break;
+ case STEAMDISCOVER_MSGTYPE_DEVICEAUTHORIZATIONREQUEST:
+ steamdiscover_dissect_body_authrequest(tvb, pinfo, steam_ihs_discovery_tree, offset, body_length);
+ break;
+ case STEAMDISCOVER_MSGTYPE_DEVICEAUTHORIZATIONCANCELREQUEST:
+ /* Message seems to have no body */
+ break;
+ case STEAMDISCOVER_MSGTYPE_DEVICEAUTHORIZATIONRESPONSE:
+ steamdiscover_dissect_body_authresponse(tvb, pinfo, steam_ihs_discovery_tree, offset, body_length);
+ break;
+ case STEAMDISCOVER_MSGTYPE_DEVICESTREAMINGREQUEST:
+ steamdiscover_dissect_body_streamingrequest(tvb, pinfo, steam_ihs_discovery_tree, offset, body_length);
+ break;
+ case STEAMDISCOVER_MSGTYPE_DEVICESTREAMINGCANCELREQUEST:
+ steamdiscover_dissect_body_streamingcancelrequest(tvb, pinfo, steam_ihs_discovery_tree, offset, body_length);
+ break;
+ case STEAMDISCOVER_MSGTYPE_DEVICESTREAMINGRESPONSE:
+ steamdiscover_dissect_body_streamingresponse(tvb, pinfo, steam_ihs_discovery_tree, offset, body_length);
+ break;
+ case STEAMDISCOVER_MSGTYPE_DEVICEPROOFREQUEST:
+ steamdiscover_dissect_body_proofrequest(tvb, pinfo, steam_ihs_discovery_tree, offset, body_length);
+ break;
+ case STEAMDISCOVER_MSGTYPE_DEVICEPROOFRESPONSE:
+ steamdiscover_dissect_body_proofresponse(tvb, pinfo, steam_ihs_discovery_tree, offset, body_length);
+ break;
+ default:
+ steamdiscover_dissect_body_unknown(tvb, pinfo, steam_ihs_discovery_tree, offset, body_length);
+ break;
+ }
+
+ return tvb_captured_length(tvb);
+}
+
+/* Register the protocol with Wireshark. */
+void
+proto_register_steam_ihs_discovery(void)
+{
+ module_t *steam_ihs_discovery_module;
+ expert_module_t *expert_steam_ihs_discovery;
+
+ static hf_register_info hf[] = {
+ /* Non-protobuf header fields */
+ { &hf_steam_ihs_discovery_signature,
+ { "Signature", "steam_ihs_discovery.signature",
+ FT_UINT64, BASE_HEX, NULL, 0,
+ "Every packet of the Steam In-Home Streaming Discovery Protocol begins with this signature.", HFILL }
+ },
+ { &hf_steam_ihs_discovery_header_length,
+ { "Header Length", "steam_ihs_discovery.header_length",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_length,
+ { "Body Length", "steam_ihs_discovery.body_length",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_unknown_data,
+ { "Unknown Data", "steam_ihs_discovery.unknown_data",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_unknown_number,
+ { "Unknown Number", "steam_ihs_discovery.unknown_number",
+ FT_UINT64, BASE_DEC_HEX, NULL, 0,
+ NULL, HFILL }
+ },
+ /* CMsgRemoteClientBroadcastHeader */
+ { &hf_steam_ihs_discovery_header_clientid,
+ { "Client ID", "steam_ihs_discovery.header_client_id",
+ FT_UINT64, BASE_DEC_HEX, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_header_msgtype,
+ { "Message Type", "steam_ihs_discovery.header_msg_type",
+ FT_UINT64, BASE_DEC|BASE_VAL64_STRING, VALS64(hf_steam_ihs_discovery_header_msgtype_strings), 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_header_instanceid,
+ { "Instance ID", "steam_ihs_discovery.header_instance_id",
+ FT_UINT64, BASE_DEC_HEX, NULL, 0,
+ NULL, HFILL }
+ },
+ /* CMsgRemoteClientBroadcastDiscovery message */
+ { &hf_steam_ihs_discovery_body_discovery_seqnum,
+ { "Sequence Number", "steam_ihs_discovery.body_discovery_seqnum",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_discovery_clientids,
+ { "Client IDs", "steam_ihs_discovery.body_discovery_clientids",
+ FT_UINT64, BASE_HEX, NULL, 0,
+ NULL, HFILL }
+ },
+ /* CMsgRemoteClientBroadcastStatus message */
+ { &hf_steam_ihs_discovery_body_status_version,
+ { "Version", "steam_ihs_discovery.body_status_version",
+ FT_INT32, BASE_DEC, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_status_minversion,
+ { "Minimum Version", "steam_ihs_discovery.body_status_minversion",
+ FT_INT32, BASE_DEC, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_status_connectport,
+ { "Connect Port", "steam_ihs_discovery.body_status_connectport",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_status_hostname,
+ { "Hostname", "steam_ihs_discovery.body_status_hostname",
+ FT_STRING, STR_UNICODE, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_status_enabledservices,
+ { "Enabled Services", "steam_ihs_discovery.body_status_enabledservices",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_status_ostype,
+ { "OS Type", "steam_ihs_discovery.body_status_ostype",
+ FT_INT32, BASE_DEC, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_status_is64bit,
+ { "Is 64 Bit", "steam_ihs_discovery.body_status_is64bit",
+ FT_BOOLEAN, BASE_NONE, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_status_euniverse,
+ { "EUniverse", "steam_ihs_discovery.body_status_euniverse",
+ FT_INT32, BASE_DEC, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_status_timestamp,
+ { "Timestamp", "steam_ihs_discovery.body_status_timestamp",
+ FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_status_screenlocked,
+ { "Screen Locked", "steam_ihs_discovery.body_status_screenlocked",
+ FT_BOOLEAN, BASE_NONE, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_status_gamesrunning,
+ { "Games Running", "steam_ihs_discovery.body_status_gamesrunning",
+ FT_BOOLEAN, BASE_NONE, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_status_macaddresses,
+ { "MAC Addresses", "steam_ihs_discovery.body_status_macaddresses",
+ FT_STRING, STR_ASCII, NULL, 0,
+ NULL, HFILL }
+ },
+ /* CMsgRemoteClientBroadcastStatus.User */
+ { &hf_steam_ihs_discovery_body_status_user_steamid,
+ { "Steam ID", "steam_ihs_discovery.body_status_user_steamid",
+ FT_UINT64, BASE_DEC, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_status_user_authkeyid,
+ { "Auth Key ID", "steam_ihs_discovery.body_status_user_authkeyid",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ NULL, HFILL }
+ },
+ /* CMsgRemoteDeviceAuthorizationRequest */
+ { &hf_steam_ihs_discovery_body_authrequest_devicetoken,
+ { "Device Token", "steam_ihs_discovery.body_authrequest_devicetoken",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_authrequest_devicename,
+ { "Device Name", "steam_ihs_discovery.body_authrequest_devicename",
+ FT_STRING, STR_UNICODE, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_authrequest_encryptedrequest,
+ { "Encrypted Request", "steam_ihs_discovery.body_authrequest_encryptedrequest",
+ FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0,
+ NULL, HFILL }
+ },
+ /* CMsgRemoteDeviceAuthorizationResponse */
+ { &hf_steam_ihs_discovery_body_authresponse_authresult,
+ { "Result", "steam_ihs_discovery.body_authresponse_authresult",
+ FT_UINT64, BASE_DEC|BASE_VAL64_STRING, VALS64(hf_steam_ihs_discovery_body_authresponse_authresult_strings), 0,
+ NULL, HFILL }
+ },
+ /* CMsgRemoteDeviceStreamingRequest */
+ { &hf_steam_ihs_discovery_body_streamingrequest_requestid,
+ { "Request ID", "steam_ihs_discovery.body_streamingrequest_requestid",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_streamingrequest_maximumresolutionx,
+ { "Maximum Resolution X", "steam_ihs_discovery.body_streamingrequest_maximumresolutionx",
+ FT_INT32, BASE_DEC, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_streamingrequest_maximumresolutiony,
+ { "Maximum Resolution Y", "steam_ihs_discovery.body_streamingrequest_maximumresolutiony",
+ FT_INT32, BASE_DEC, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_streamingrequest_audiochannelcount,
+ { "Audio Channel Count", "steam_ihs_discovery.body_streamingrequest_audiochannelcount",
+ FT_INT32, BASE_DEC, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_streamingrequest_deviceversion,
+ { "Device Version", "steam_ihs_discovery.body_streamingrequest_deviceversion",
+ FT_STRING, STR_UNICODE, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_streamingrequest_streamdesktop,
+ { "Stream Desktop", "steam_ihs_discovery.body_streamingrequest_streamdesktop",
+ FT_BOOLEAN, BASE_NONE, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_streamingrequest_devicetoken,
+ { "Device Token", "steam_ihs_discovery.body_streamingrequest_devicetoken",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_streamingrequest_pin,
+ { "PIN", "steam_ihs_discovery.body_streamingrequest_pin",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_streamingrequest_enablevideostreaming,
+ { "Enable Video Streaming", "steam_ihs_discovery.body_streamingrequest_enablevideostreaming",
+ FT_BOOLEAN, BASE_NONE, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_streamingrequest_enableaudiostreaming,
+ { "Enable Audio Streaming", "steam_ihs_discovery.body_streamingrequest_enableaudiostreaming",
+ FT_BOOLEAN, BASE_NONE, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_streamingrequest_enableinputstreaming,
+ { "Enable Input Streaming", "steam_ihs_discovery.body_streamingrequest_enableinputstreaming",
+ FT_BOOLEAN, BASE_NONE, NULL, 0,
+ NULL, HFILL }
+ },
+ /* CMsgRemoteDeviceStreamingCancelRequest */
+ { &hf_steam_ihs_discovery_body_streamingcancelrequest_requestid,
+ { "Request ID", "steam_ihs_discovery.body_streamingcancelrequest_requestid",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ NULL, HFILL }
+ },
+ /* CMsgRemoteDeviceStreamingResponse */
+ { &hf_steam_ihs_discovery_body_streamingresponse_requestid,
+ { "Request ID", "steam_ihs_discovery.body_streamingresponse_requestid",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_streamingresponse_result,
+ { "Result", "steam_ihs_discovery.body_streamingresponse_result",
+ FT_UINT64, BASE_DEC|BASE_VAL64_STRING, VALS64(hf_steam_ihs_discovery_body_streamingresponse_result_strings), 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_streamingresponse_port,
+ { "Port", "steam_ihs_discovery.body_streamingresponse_port",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_streamingresponse_encryptedsessionkey,
+ { "Encrypted Session Key", "steam_ihs_discovery.body_streamingresponse_encryptedsessionkey",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ NULL, HFILL }
+ },
+ { &hf_steam_ihs_discovery_body_streamingresponse_virtualherelicenseddevicecount,
+ { "VirtualHere Licensed Device Count", "steam_ihs_discovery.body_streamingresponse_virtualherelicenseddevicecount",
+ FT_INT32, BASE_DEC, NULL, 0,
+ NULL, HFILL }
+ },
+ /* CMsgRemoteDeviceProofRequest */
+ { &hf_steam_ihs_discovery_body_proofrequest_challenge,
+ { "Challenge", "steam_ihs_discovery.body_proofrequest_challenge",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ NULL, HFILL }
+ },
+ /* CMsgRemoteDeviceProofResponse */
+ { &hf_steam_ihs_discovery_body_proofresponse_response,
+ { "Reponse", "steam_ihs_discovery.body_proofresponse_response",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ NULL, HFILL }
+ }
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_steam_ihs_discovery,
+ &ett_steam_ihs_discovery_body_status_user
+ };
+
+ /* Setup protocol expert items */
+ static ei_register_info ei[] = {
+ { &ei_steam_ihs_discovery_unknown_data,
+ { "steam_ihs_discovery.unknowndata", PI_UNDECODED, PI_WARN,
+ "Unknown data section", EXPFILL }
+ },
+ { &ei_steam_ihs_discovery_unknown_number,
+ { "steam_ihs_discovery.unknownnumber", PI_UNDECODED, PI_WARN,
+ "Unknown numeric protobuf field", EXPFILL }
+ },
+ { &ei_steam_ihs_discovery_unknown_lengthdelimited,
+ { "steam_ihs_discovery.unknownlengthdelimited", PI_UNDECODED, PI_WARN,
+ "Unknown length-delimited protobuf field", EXPFILL }
+ },
+ { &ei_steam_ihs_discovery_invalid_wiretype,
+ { "steam_ihs_discovery.invalid_wiretype", PI_MALFORMED, PI_ERROR,
+ "Unexpected wire type", EXPFILL }
+ },
+ { &ei_steam_ihs_discovery_invalid_length,
+ { "steam_ihs_discovery.invalid_length", PI_MALFORMED, PI_ERROR,
+ "Length-delimited field has invalid length", EXPFILL }
+ }
+ };
+
+ /* Register the protocol name and description */
+ proto_steam_ihs_discovery = proto_register_protocol("Steam In-Home Streaming Discovery Protocol",
+ "Steam IHS Discovery", "steam_ihs_discovery");
+
+ /* Required function calls to register the header fields and subtrees */
+ proto_register_field_array(proto_steam_ihs_discovery, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* Required function calls to register expert items */
+ expert_steam_ihs_discovery = expert_register_protocol(proto_steam_ihs_discovery);
+ expert_register_field_array(expert_steam_ihs_discovery, ei, array_length(ei));
+
+ /* Register a preferences module. */
+ steam_ihs_discovery_module = prefs_register_protocol(proto_steam_ihs_discovery,
+ proto_reg_handoff_steam_ihs_discovery);
+
+ /* Register an example port preference */
+ prefs_register_uint_preference(steam_ihs_discovery_module, "udp.port", "steam_ihs_discovery UDP Port",
+ " Steam IHS Discovery UDP port if other than the default",
+ 10, &udp_port_pref);
+}
+
+void
+proto_reg_handoff_steam_ihs_discovery(void)
+{
+ static gboolean initialized = FALSE;
+ static dissector_handle_t steam_ihs_discovery_handle;
+ static int current_port;
+
+ if (!initialized) {
+ steam_ihs_discovery_handle = create_dissector_handle(dissect_steam_ihs_discovery,
+ proto_steam_ihs_discovery);
+ initialized = TRUE;
+
+ } else {
+ dissector_delete_uint("udp.port", current_port, steam_ihs_discovery_handle);
+ }
+
+ current_port = udp_port_pref;
+
+ dissector_add_uint("udp.port", current_port, steam_ihs_discovery_handle);
+}
+
+/*
+ * Editor modelines - https://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */