1 /* packet-steam_ihs_discovery.c
2 * Routines for Steam In-Home Streaming Discovery Protocol dissection
3 * Copyright 2017, Jan Holthuis <jan.holthuis@ruhr-uni-bochum.de>
4 *
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
12 /* Steam In-Home Streaming Discovery Protocol detects servers and negotiates
13 * connections to stream video games over the networks. It is used by
14 * Valve Software's Steam Client and Steam Link devices.
15 *
16 * Further Information:
17 * https://codingrange.com/blog/steam-in-home-streaming-discovery-protocol
18 * https://codingrange.com/blog/steam-in-home-streaming-control-protocol
19 */
20
21 #include <config.h>
22
23 #include <epan/packet.h> /* Should be first Wireshark include (other than config.h) */
24 #include <epan/expert.h> /* Include only as needed */
25 #include <epan/prefs.h> /* Include only as needed */
26
27 /* Prototypes */
28 /* (Required to prevent [-Wmissing-prototypes] warnings */
29 void proto_reg_handoff_steam_ihs_discovery(void);
30 void proto_register_steam_ihs_discovery(void);
31
32 static int proto_steam_ihs_discovery = -1;
33
34 static int hf_steam_ihs_discovery_signature = -1;
35 static int hf_steam_ihs_discovery_header_length = -1;
36 static int hf_steam_ihs_discovery_header_clientid = -1;
37 static int hf_steam_ihs_discovery_header_msgtype = -1;
38 static int hf_steam_ihs_discovery_header_instanceid = -1;
39 static int hf_steam_ihs_discovery_body_length = -1;
40 static int hf_steam_ihs_discovery_body_discovery_seqnum = -1;
41 static int hf_steam_ihs_discovery_body_discovery_clientids = -1;
42 static int hf_steam_ihs_discovery_body_status_version = -1;
43 static int hf_steam_ihs_discovery_body_status_minversion = -1;
44 static int hf_steam_ihs_discovery_body_status_connectport = -1;
45 static int hf_steam_ihs_discovery_body_status_hostname = -1;
46 static int hf_steam_ihs_discovery_body_status_enabledservices = -1;
47 static int hf_steam_ihs_discovery_body_status_ostype = -1;
48 static int hf_steam_ihs_discovery_body_status_is64bit = -1;
49 static int hf_steam_ihs_discovery_body_status_euniverse = -1;
50 static int hf_steam_ihs_discovery_body_status_timestamp = -1;
51 static int hf_steam_ihs_discovery_body_status_screenlocked = -1;
52 static int hf_steam_ihs_discovery_body_status_gamesrunning = -1;
53 static int hf_steam_ihs_discovery_body_status_macaddresses = -1;
54 static int hf_steam_ihs_discovery_body_status_user_steamid = -1;
55 static int hf_steam_ihs_discovery_body_status_user_authkeyid = -1;
56 static int hf_steam_ihs_discovery_body_authrequest_devicetoken = -1;
57 static int hf_steam_ihs_discovery_body_authrequest_devicename = -1;
58 static int hf_steam_ihs_discovery_body_authrequest_encryptedrequest = -1;
59 static int hf_steam_ihs_discovery_body_authresponse_authresult = -1;
60 static int hf_steam_ihs_discovery_body_streamingrequest_requestid = -1;
61 static int hf_steam_ihs_discovery_body_streamingrequest_maximumresolutionx = -1;
62 static int hf_steam_ihs_discovery_body_streamingrequest_maximumresolutiony = -1;
63 static int hf_steam_ihs_discovery_body_streamingrequest_audiochannelcount = -1;
64 static int hf_steam_ihs_discovery_body_streamingrequest_deviceversion = -1;
65 static int hf_steam_ihs_discovery_body_streamingrequest_streamdesktop = -1;
66 static int hf_steam_ihs_discovery_body_streamingrequest_devicetoken = -1;
67 static int hf_steam_ihs_discovery_body_streamingrequest_pin = -1;
68 static int hf_steam_ihs_discovery_body_streamingrequest_enablevideostreaming = -1;
69 static int hf_steam_ihs_discovery_body_streamingrequest_enableaudiostreaming = -1;
70 static int hf_steam_ihs_discovery_body_streamingrequest_enableinputstreaming = -1;
71 static int hf_steam_ihs_discovery_body_streamingcancelrequest_requestid = -1;
72 static int hf_steam_ihs_discovery_body_streamingresponse_requestid = -1;
73 static int hf_steam_ihs_discovery_body_streamingresponse_result = -1;
74 static int hf_steam_ihs_discovery_body_streamingresponse_port = -1;
75 static int hf_steam_ihs_discovery_body_streamingresponse_encryptedsessionkey = -1;
76 static int hf_steam_ihs_discovery_body_streamingresponse_virtualherelicenseddevicecount = -1;
77 static int hf_steam_ihs_discovery_body_proofrequest_challenge = -1;
78 static int hf_steam_ihs_discovery_body_proofresponse_response = -1;
79 static int hf_steam_ihs_discovery_unknown_data = -1;
80 static int hf_steam_ihs_discovery_unknown_number = -1;
81
82 static const val64_string hf_steam_ihs_discovery_header_msgtype_strings[] = {
83 { 0, "Client Discovery" },
84 { 1, "Client Status" },
85 { 2, "Client Offline" },
86 { 3, "Device Authorization Request" },
87 { 4, "Device Authorization Response" },
88 { 5, "Device Streaming Request" },
89 { 6, "Device Streaming Response" },
90 { 7, "Device Proof Request" },
91 { 8, "Device Proof Response" },
92 { 9, "Device Authorization Cancel Request" },
93 { 10, "Device Streaming Cancel Request" },
94 { 0, NULL }
95 };
96
97 static const val64_string hf_steam_ihs_discovery_body_authresponse_authresult_strings[] = {
98 { 0, "Success" },
99 { 1, "Denied" },
100 { 2, "Not Logged In" },
101 { 3, "Offline" },
102 { 4, "Busy" },
103 { 5, "In Progress" },
104 { 6, "TimedOut" },
105 { 7, "Failed" },
106 { 8, "Canceled" },
107 { 0, NULL }
108 };
109
110 static const val64_string hf_steam_ihs_discovery_body_streamingresponse_result_strings[] = {
111 { 0, "Success" },
112 { 1, "Unauthorized" },
113 { 2, "Screen Locked" },
114 { 3, "Failed" },
115 { 4, "Busy" },
116 { 5, "In Progress" },
117 { 6, "Canceled" },
118 { 7, "Drivers Not Installed" },
119 { 8, "Disabled" },
120 { 9, "Broadcasting Active" },
121 { 10, "VR Active" },
122 { 11, "PIN Required" },
123 { 0, NULL }
124 };
125
126 static expert_field ei_steam_ihs_discovery_unknown_data = EI_INIT;
127 static expert_field ei_steam_ihs_discovery_unknown_number = EI_INIT;
128 static expert_field ei_steam_ihs_discovery_unknown_lengthdelimited = EI_INIT;
129 static expert_field ei_steam_ihs_discovery_invalid_wiretype = EI_INIT;
130 static expert_field ei_steam_ihs_discovery_invalid_length = EI_INIT;
131
132 #define STEAM_IHS_DISCOVERY_UDP_PORT 27036
133 static guint udp_port_pref = STEAM_IHS_DISCOVERY_UDP_PORT;
134
135 /* Initialize the subtree pointers */
136 static gint ett_steam_ihs_discovery = -1;
137 static gint ett_steam_ihs_discovery_body_status_user = -1;
138
139 #define STEAM_IHS_DISCOVERY_MIN_LENGTH 12
140 #define STEAM_IHS_DISCOVERY_SIGNATURE_LENGTH 8
141 #define STEAM_IHS_DISCOVERY_SIGNATURE_VALUE 0xFFFFFFFF214C5FA0
142
143 /* Helper functions and structs for reading Protocol Buffers.
144 *
145 * Detailed information about protobuf message encoding can be found at:
146 * https://developers.google.com/protocol-buffers/docs/encoding#structure
147 */
148 #define PROTOBUF_WIRETYPE_VARINT 0
149 #define PROTOBUF_WIRETYPE_64BIT 1
150 #define PROTOBUF_WIRETYPE_LENGTHDELIMITED 2
151 #define PROTOBUF_WIRETYPE_32BIT 5
152
153 static const char * const protobuf_wiretype_names[] = {"VarInt", "64-bit", "Length-delimited", "Start group", "End group", "32-bit"};
154 static const char protobuf_wiretype_name_unknown[] = "Unknown";
155
protobuf_get_wiretype_name(guint8 wire_type)156 static const char* protobuf_get_wiretype_name(guint8 wire_type) {
157 if (wire_type <= 5) {
158 return protobuf_wiretype_names[wire_type];
159 }
160 return protobuf_wiretype_name_unknown;
161 }
162
163 static gint64
get_varint64(tvbuff_t * tvb,gint offset,gint bytes_left,gint * len)164 get_varint64(tvbuff_t *tvb, gint offset, gint bytes_left, gint* len)
165 {
166 guint8 b;
167 gint64 result = 0;
168 *len = 0;
169 while ((*len) < bytes_left) {
170 b = tvb_get_guint8(tvb, offset+(*len));
171 result |= ((gint64)b & 0x7f) << ((*len)*7);
172 (*len)++;
173 if ((b & 0x80) == 0) {
174 break;
175 }
176 }
177 return result;
178 }
179
180 typedef struct {
181 tvbuff_t *tvb;
182 gint offset;
183 gint bytes_left;
184 } protobuf_desc_t;
185
186 typedef struct {
187 guint64 value;
188 guint64 field_number;
189 guint8 wire_type;
190 } protobuf_tag_t;
191
192 static void
protobuf_seek_forward(protobuf_desc_t * pb,gint len)193 protobuf_seek_forward(protobuf_desc_t* pb, gint len)
194 {
195 pb->offset += len;
196 pb->bytes_left -= len;
197 }
198
199 static gint
protobuf_iter_next(protobuf_desc_t * pb,protobuf_tag_t * tag)200 protobuf_iter_next(protobuf_desc_t* pb, protobuf_tag_t* tag)
201 {
202 gint len;
203 if (pb->bytes_left <= 0) {
204 return 0;
205 }
206 tag->value = get_varint64(pb->tvb, pb->offset, pb->bytes_left, &len);
207 tag->field_number = tag->value >> 3;
208 tag->wire_type = tag->value & 0x7;
209 protobuf_seek_forward(pb, len);
210 return pb->bytes_left;
211 }
212
213 static gint
protobuf_dissect_unknown_field(protobuf_desc_t * pb,protobuf_tag_t * tag,packet_info * pinfo,proto_tree * tree,proto_item ** tiptr)214 protobuf_dissect_unknown_field(protobuf_desc_t *pb, protobuf_tag_t *tag, packet_info *pinfo, proto_tree *tree, proto_item** tiptr)
215 {
216 gint len;
217 gint64 value;
218 proto_item* ti;
219
220 switch(tag->wire_type) {
221 case PROTOBUF_WIRETYPE_VARINT:
222 value = get_varint64(pb->tvb, pb->offset, pb->bytes_left, &len);
223 ti = proto_tree_add_uint64(tree, hf_steam_ihs_discovery_unknown_number, pb->tvb,
224 pb->offset, len, (guint64)value);
225 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));
226 break;
227 case PROTOBUF_WIRETYPE_64BIT:
228 len = 8;
229 ti = proto_tree_add_item(tree, hf_steam_ihs_discovery_unknown_number, pb->tvb, pb->offset+len, len, ENC_LITTLE_ENDIAN);
230 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));
231 break;
232 case PROTOBUF_WIRETYPE_LENGTHDELIMITED:
233 value = get_varint64(pb->tvb, pb->offset, pb->bytes_left, &len);
234 if((guint64)value > (guint64)(pb->bytes_left-len)) {
235 ti = proto_tree_add_item(tree, hf_steam_ihs_discovery_unknown_data, pb->tvb, pb->offset+len, pb->bytes_left-len, ENC_NA);
236 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));
237 len = pb->bytes_left;
238 } else {
239 ti = proto_tree_add_item(tree, hf_steam_ihs_discovery_unknown_data, pb->tvb, pb->offset+len, (gint)value, ENC_NA);
240 len += (gint)value;
241 }
242 expert_add_info(pinfo, ti, &ei_steam_ihs_discovery_unknown_lengthdelimited);
243 break;
244 case PROTOBUF_WIRETYPE_32BIT:
245 len = 4;
246 ti = proto_tree_add_item(tree, hf_steam_ihs_discovery_unknown_number, pb->tvb, pb->offset+len, len, ENC_LITTLE_ENDIAN);
247 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));
248 break;
249 default:
250 len = pb->bytes_left;
251 ti = proto_tree_add_item(tree, hf_steam_ihs_discovery_unknown_data, pb->tvb, pb->offset, len, ENC_NA);
252 expert_add_info(pinfo, ti, &ei_steam_ihs_discovery_unknown_data);
253 break;
254 }
255 if(tiptr != NULL) {
256 *tiptr = ti;
257 }
258
259 return len;
260 }
261
262 static gint
protobuf_verify_wiretype(protobuf_desc_t * pb,protobuf_tag_t * tag,packet_info * pinfo,proto_tree * tree,guint8 expected_wire_type)263 protobuf_verify_wiretype(protobuf_desc_t *pb, protobuf_tag_t *tag, packet_info *pinfo, proto_tree *tree, guint8 expected_wire_type)
264 {
265 gint len;
266 gint64 len_prefix;
267 proto_item *ti = NULL;
268
269 if(expected_wire_type == tag->wire_type) {
270 if(expected_wire_type == PROTOBUF_WIRETYPE_LENGTHDELIMITED) {
271 len_prefix = get_varint64(pb->tvb, pb->offset, pb->bytes_left, &len);
272 if(len_prefix < 0 || len_prefix > G_MAXINT) {
273 ti = proto_tree_add_item(tree, hf_steam_ihs_discovery_unknown_data, pb->tvb, pb->offset+len, pb->bytes_left-len, ENC_NA);
274 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);
275 return pb->bytes_left;
276 } else if(((gint)len_prefix) > (pb->bytes_left-len)) {
277 ti = proto_tree_add_item(tree, hf_steam_ihs_discovery_unknown_data, pb->tvb, pb->offset+len, pb->bytes_left-len, ENC_NA);
278 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));
279 return pb->bytes_left;
280 }
281 }
282 return 0;
283 }
284 len = protobuf_dissect_unknown_field(pb, tag, pinfo, tree, &ti);
285
286 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));
287 return len;
288 }
289
290 /* The actual protocol-specific stuff */
291
292 #define STEAMDISCOVER_FN_HEADER_CLIENTID 1
293 #define STEAMDISCOVER_FN_HEADER_MSGTYPE 2
294 #define STEAMDISCOVER_FN_HEADER_INSTANCEID 3
295
296 #define STEAMDISCOVER_FN_DISCOVERY_SEQNUM 1
297 #define STEAMDISCOVER_FN_DISCOVERY_CLIENTIDS 2
298
299 #define STEAMDISCOVER_FN_STATUS_VERSION 1
300 #define STEAMDISCOVER_FN_STATUS_MINVERSION 2
301 #define STEAMDISCOVER_FN_STATUS_CONNECTPORT 3
302 #define STEAMDISCOVER_FN_STATUS_HOSTNAME 4
303 #define STEAMDISCOVER_FN_STATUS_ENABLEDSERVICES 6
304 #define STEAMDISCOVER_FN_STATUS_OSTYPE 7
305 #define STEAMDISCOVER_FN_STATUS_IS64BIT 8
306 #define STEAMDISCOVER_FN_STATUS_USERS 9
307 #define STEAMDISCOVER_FN_STATUS_EUNIVERSE 11
308 #define STEAMDISCOVER_FN_STATUS_TIMESTAMP 12
309 #define STEAMDISCOVER_FN_STATUS_SCREENLOCKED 13
310 #define STEAMDISCOVER_FN_STATUS_GAMESRUNNING 14
311 #define STEAMDISCOVER_FN_STATUS_MACADDRESSES 15
312 #define STEAMDISCOVER_FN_STATUS_USER_STEAMID 1
313 #define STEAMDISCOVER_FN_STATUS_USER_AUTHKEYID 2
314
315 #define STEAMDISCOVER_FN_AUTHREQUEST_DEVICETOKEN 1
316 #define STEAMDISCOVER_FN_AUTHREQUEST_DEVICENAME 2
317 #define STEAMDISCOVER_FN_AUTHREQUEST_ENCRYPTEDREQUEST 3
318
319 #define STEAMDISCOVER_FN_AUTHRESPONSE_AUTHRESULT 1
320
321 #define STEAMDISCOVER_FN_STREAMINGREQUEST_REQUESTID 1
322 #define STEAMDISCOVER_FN_STREAMINGREQUEST_MAXIMUMRESOLUTIONX 2
323 #define STEAMDISCOVER_FN_STREAMINGREQUEST_MAXIMUMRESOLUTIONY 3
324 #define STEAMDISCOVER_FN_STREAMINGREQUEST_AUDIOCHANNELCOUNT 4
325 #define STEAMDISCOVER_FN_STREAMINGREQUEST_DEVICEVERSION 5
326 #define STEAMDISCOVER_FN_STREAMINGREQUEST_STREAMDESKTOP 6
327 #define STEAMDISCOVER_FN_STREAMINGREQUEST_DEVICETOKEN 7
328 #define STEAMDISCOVER_FN_STREAMINGREQUEST_PIN 8
329 #define STEAMDISCOVER_FN_STREAMINGREQUEST_ENABLEVIDEOSTREAMING 9
330 #define STEAMDISCOVER_FN_STREAMINGREQUEST_ENABLEAUDIOSTREAMING 10
331 #define STEAMDISCOVER_FN_STREAMINGREQUEST_ENABLEINPUTSTREAMING 11
332
333 #define STEAMDISCOVER_FN_STREAMINGCANCELREQUEST_REQUESTID 1
334
335 #define STEAMDISCOVER_FN_STREAMINGRESPONSE_REQUESTID 1
336 #define STEAMDISCOVER_FN_STREAMINGRESPONSE_RESULT 2
337 #define STEAMDISCOVER_FN_STREAMINGRESPONSE_PORT 3
338 #define STEAMDISCOVER_FN_STREAMINGRESPONSE_ENCRYPTEDSESSIONKEY 4
339 #define STEAMDISCOVER_FN_STREAMINGRESPONSE_VIRTUALHERELICENSEDDEVICECOUNT 5
340
341 #define STEAMDISCOVER_FN_PROOFREQUEST_CHALLENGE 1
342 #define STEAMDISCOVER_FN_PROOFRESPONSE_RESPONSE 1
343
344 #define STEAMDISCOVER_MSGTYPE_CLIENTBROADCASTMSGDISCOVERY 0
345 #define STEAMDISCOVER_MSGTYPE_CLIENTBROADCASTMSGSTATUS 1
346 #define STEAMDISCOVER_MSGTYPE_CLIENTBROADCASTMSGOFFLINE 2
347 #define STEAMDISCOVER_MSGTYPE_DEVICEAUTHORIZATIONREQUEST 3
348 #define STEAMDISCOVER_MSGTYPE_DEVICEAUTHORIZATIONRESPONSE 4
349 #define STEAMDISCOVER_MSGTYPE_DEVICESTREAMINGREQUEST 5
350 #define STEAMDISCOVER_MSGTYPE_DEVICESTREAMINGRESPONSE 6
351 #define STEAMDISCOVER_MSGTYPE_DEVICEPROOFREQUEST 7
352 #define STEAMDISCOVER_MSGTYPE_DEVICEPROOFRESPONSE 8
353 #define STEAMDISCOVER_MSGTYPE_DEVICEAUTHORIZATIONCANCELREQUEST 9
354 #define STEAMDISCOVER_MSGTYPE_DEVICESTREAMINGCANCELREQUEST 10
355 #define STEAMDISCOVER_MSGTYPES_MAX 10
356
357 #define STEAMDISCOVER_ENSURE_WIRETYPE(X) if((len = protobuf_verify_wiretype(&pb, &tag, pinfo, tree, X))) break;
358
359 /* Dissect the header section of a packet. The header is a
360 * CMsgRemoteClientBroadcastHeader protobuf message.
361 *
362 * enum ERemoteClientBroadcastMsg {
363 * k_ERemoteClientBroadcastMsgDiscovery = 0;
364 * k_ERemoteClientBroadcastMsgStatus = 1;
365 * k_ERemoteClientBroadcastMsgOffline = 2;
366 * k_ERemoteDeviceAuthorizationRequest = 3;
367 * k_ERemoteDeviceAuthorizationResponse = 4;
368 * k_ERemoteDeviceStreamingRequest = 5;
369 * k_ERemoteDeviceStreamingResponse = 6;
370 * k_ERemoteDeviceProofRequest = 7;
371 * k_ERemoteDeviceProofResponse = 8;
372 * k_ERemoteDeviceAuthorizationCancelRequest = 9;
373 * k_ERemoteDeviceStreamingCancelRequest = 10;
374 * }
375 *
376 * message CMsgRemoteClientBroadcastHeader {
377 * optional uint64 client_id = 1;
378 * optional ERemoteClientBroadcastMsg msg_type = 2;
379 * optional uint64 instance_id = 3;
380 * }
381 */
382 static gint64
steamdiscover_dissect_header(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,gint offset,gint bytes_left)383 steamdiscover_dissect_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
384 gint offset, gint bytes_left)
385 {
386 gint len;
387 gint64 value;
388 gint64 msg_type = -1;
389 protobuf_desc_t pb = { tvb, offset, bytes_left };
390 protobuf_tag_t tag = { 0, 0, 0 };
391 while (protobuf_iter_next(&pb, &tag)) {
392 switch(tag.field_number) {
393 case STEAMDISCOVER_FN_HEADER_CLIENTID:
394 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
395 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
396 proto_tree_add_uint64(tree, hf_steam_ihs_discovery_header_clientid, pb.tvb,
397 pb.offset, len, (guint64)value);
398 break;
399 case STEAMDISCOVER_FN_HEADER_MSGTYPE:
400 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
401 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
402 msg_type = value;
403 proto_tree_add_uint64(tree, hf_steam_ihs_discovery_header_msgtype, pb.tvb,
404 pb.offset, len, (guint64)value);
405 break;
406 case STEAMDISCOVER_FN_HEADER_INSTANCEID:
407 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
408 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
409 proto_tree_add_uint64(tree, hf_steam_ihs_discovery_header_instanceid, pb.tvb,
410 pb.offset, len, (guint64)value);
411 break;
412 default:
413 len = protobuf_dissect_unknown_field(&pb, &tag, pinfo, tree, NULL);
414 break;
415 }
416 protobuf_seek_forward(&pb, len);
417 }
418 return msg_type;
419 }
420
421 /* Dissect a CMsgRemoteClientBroadcastDiscovery protobuf message body.
422 *
423 * message CMsgRemoteClientBroadcastDiscovery {
424 * optional uint32 seq_num = 1;
425 * repeated uint64 client_ids = 2;
426 * }
427 */
428 static void
steamdiscover_dissect_body_discovery(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,gint offset,gint bytes_left)429 steamdiscover_dissect_body_discovery(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
430 gint offset, gint bytes_left)
431 {
432 gint len;
433 gint64 value;
434 protobuf_desc_t pb = { tvb, offset, bytes_left };
435 protobuf_tag_t tag = { 0, 0, 0 };
436 while (protobuf_iter_next(&pb, &tag)) {
437 switch(tag.field_number) {
438 case STEAMDISCOVER_FN_DISCOVERY_SEQNUM:
439 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
440 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
441 proto_tree_add_uint(tree, hf_steam_ihs_discovery_body_discovery_seqnum, pb.tvb,
442 pb.offset, len, (guint32)value);
443 col_append_fstr(pinfo->cinfo, COL_INFO, " Seq=%"G_GUINT32_FORMAT, (guint32)value);
444 break;
445 case STEAMDISCOVER_FN_DISCOVERY_CLIENTIDS:
446 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
447 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
448 proto_tree_add_uint64(tree, hf_steam_ihs_discovery_body_discovery_clientids, pb.tvb,
449 pb.offset, len, value);
450 break;
451 default:
452 len = protobuf_dissect_unknown_field(&pb, &tag, pinfo, tree, NULL);
453 break;
454 }
455 protobuf_seek_forward(&pb, len);
456 }
457 }
458
459 /* Dissect a CMsgRemoteClientBroadcastStatus protobuf message body.
460 *
461 * message CMsgRemoteClientBroadcastStatus {
462 * message User {
463 * optional fixed64 steamid = 1;
464 * optional uint32 auth_key_id = 2;
465 * }
466 * optional int32 version = 1;
467 * optional int32 min_version = 2;
468 * optional uint32 connect_port = 3;
469 * optional string hostname = 4;
470 * optional uint32 enabled_services = 6;
471 * optional int32 ostype = 7 [default = 0];
472 * optional bool is64bit = 8 [default = false];
473 * repeated CMsgRemoteClientBroadcastStatus.User users = 9;
474 * optional int32 euniverse = 11;
475 * optional uint32 timestamp = 12;
476 * optional bool screen_locked = 13;
477 * optional bool games_running = 14;
478 * repeated string mac_addresses = 15;
479 * optional uint32 download_lan_peer_group = 16;
480 * optional bool broadcasting_active = 17;
481 * optional bool vr_active = 18;
482 * }
483 */
484 static void
steamdiscover_dissect_body_status(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,gint offset,gint bytes_left)485 steamdiscover_dissect_body_status(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
486 gint offset, gint bytes_left)
487 {
488 gint64 value;
489 gint len;
490 gint len2;
491 protobuf_desc_t pb = { tvb, offset, bytes_left };
492 protobuf_desc_t pb2 = { tvb, 0, 0 };
493 protobuf_tag_t tag = { 0, 0, 0 };
494 guint8 *hostname;
495 nstime_t timestamp;
496 proto_tree *user_tree;
497 proto_item *user_it;
498 while (protobuf_iter_next(&pb, &tag)) {
499 switch(tag.field_number) {
500 case STEAMDISCOVER_FN_STATUS_VERSION:
501 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
502 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
503 proto_tree_add_int(tree, hf_steam_ihs_discovery_body_status_version, pb.tvb,
504 pb.offset, len, (gint32)value);
505 break;
506 case STEAMDISCOVER_FN_STATUS_MINVERSION:
507 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
508 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
509 proto_tree_add_int(tree, hf_steam_ihs_discovery_body_status_minversion, pb.tvb,
510 pb.offset, len, (gint32)value);
511 break;
512 case STEAMDISCOVER_FN_STATUS_CONNECTPORT:
513 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
514 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
515 proto_tree_add_uint(tree, hf_steam_ihs_discovery_body_status_connectport, pb.tvb,
516 pb.offset, len, (guint32)value);
517 break;
518 case STEAMDISCOVER_FN_STATUS_HOSTNAME:
519 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_LENGTHDELIMITED);
520 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
521 proto_tree_add_item(tree, hf_steam_ihs_discovery_body_status_hostname, pb.tvb,
522 pb.offset+len, (gint)value, ENC_UTF_8|ENC_NA);
523 hostname = tvb_get_string_enc(pinfo->pool, pb.tvb, pb.offset+len, (gint)value, ENC_UTF_8);
524 if(hostname && strlen(hostname)) {
525 col_add_fstr(pinfo->cinfo, COL_INFO, "%s from %s", hf_steam_ihs_discovery_header_msgtype_strings[STEAMDISCOVER_MSGTYPE_CLIENTBROADCASTMSGSTATUS].strptr, hostname);
526 }
527 len += (gint)value;
528 break;
529 case STEAMDISCOVER_FN_STATUS_ENABLEDSERVICES:
530 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
531 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
532 proto_tree_add_uint(tree, hf_steam_ihs_discovery_body_status_enabledservices, pb.tvb,
533 pb.offset, len, (guint32)value);
534 break;
535 case STEAMDISCOVER_FN_STATUS_OSTYPE:
536 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
537 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
538 proto_tree_add_int(tree, hf_steam_ihs_discovery_body_status_ostype, pb.tvb,
539 pb.offset, len, (gint32)value);
540 break;
541 case STEAMDISCOVER_FN_STATUS_IS64BIT:
542 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
543 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
544 proto_tree_add_boolean(tree, hf_steam_ihs_discovery_body_status_is64bit, pb.tvb,
545 pb.offset, len, (gint32)value);
546 break;
547 case STEAMDISCOVER_FN_STATUS_USERS:
548 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_LENGTHDELIMITED);
549 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
550 pb2.offset = pb.offset+len;
551 pb2.bytes_left = (gint)value;
552 len += (gint)value;
553 user_tree = proto_tree_add_subtree(tree, pb.tvb, pb.offset, len, ett_steam_ihs_discovery_body_status_user, &user_it, "User");
554 while (protobuf_iter_next(&pb2, &tag)) {
555 switch(tag.field_number) {
556 case STEAMDISCOVER_FN_STATUS_USER_STEAMID:
557 if((len2 = protobuf_verify_wiretype(&pb2, &tag, pinfo, user_tree, PROTOBUF_WIRETYPE_64BIT))) break;
558 len2 = 8;
559 value = tvb_get_letoh64(pb2.tvb, pb2.offset);
560 proto_tree_add_uint64(user_tree, hf_steam_ihs_discovery_body_status_user_steamid, pb2.tvb,
561 pb2.offset, len2, (guint64)value);
562 proto_item_append_text(user_it, ", Steam ID: %"G_GUINT64_FORMAT, (guint64)value);
563 break;
564 case STEAMDISCOVER_FN_STATUS_USER_AUTHKEYID:
565 if((len2 = protobuf_verify_wiretype(&pb2, &tag, pinfo, user_tree, PROTOBUF_WIRETYPE_VARINT))) break;
566 value = get_varint64(pb2.tvb, pb2.offset, pb2.bytes_left, &len2);
567 proto_tree_add_uint(user_tree, hf_steam_ihs_discovery_body_status_user_authkeyid, pb2.tvb,
568 pb2.offset, len2, (guint32)value);
569 proto_item_append_text(user_it, ", Auth Key ID: %"G_GUINT32_FORMAT, (guint32)value);
570 break;
571 default:
572 len2 = protobuf_dissect_unknown_field(&pb2, &tag, pinfo, tree, NULL);
573 break;
574 }
575 protobuf_seek_forward(&pb2, len2);
576 }
577 break;
578 case STEAMDISCOVER_FN_STATUS_EUNIVERSE:
579 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
580 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
581 proto_tree_add_int(tree, hf_steam_ihs_discovery_body_status_euniverse, pb.tvb,
582 pb.offset, len, (gint32)value);
583 break;
584 case STEAMDISCOVER_FN_STATUS_TIMESTAMP:
585 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
586 timestamp.secs = (time_t)get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
587 timestamp.nsecs = 0;
588 proto_tree_add_time(tree, hf_steam_ihs_discovery_body_status_timestamp, pb.tvb,
589 pb.offset, len, ×tamp);
590 break;
591 case STEAMDISCOVER_FN_STATUS_SCREENLOCKED:
592 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
593 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
594 proto_tree_add_boolean(tree, hf_steam_ihs_discovery_body_status_screenlocked, pb.tvb,
595 pb.offset, len, (gint32)value);
596 break;
597 case STEAMDISCOVER_FN_STATUS_GAMESRUNNING:
598 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
599 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
600 proto_tree_add_boolean(tree, hf_steam_ihs_discovery_body_status_gamesrunning, pb.tvb,
601 pb.offset, len, (gint32)value);
602 break;
603 case STEAMDISCOVER_FN_STATUS_MACADDRESSES:
604 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_LENGTHDELIMITED);
605 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
606 proto_tree_add_item(tree, hf_steam_ihs_discovery_body_status_macaddresses, pb.tvb,
607 pb.offset+len, (gint)value, ENC_UTF_8|ENC_NA);
608 len += (gint)value;
609 break;
610 default:
611 len = protobuf_dissect_unknown_field(&pb, &tag, pinfo, tree, NULL);
612 break;
613 }
614 protobuf_seek_forward(&pb, len);
615 }
616 }
617
618 /* Dissect a CMsgRemoteDeviceAuthorizationRequest protobuf message body.
619 *
620 * message CMsgRemoteDeviceAuthorizationRequest {
621 * message CKeyEscrow_Ticket {
622 * optional bytes password = 1;
623 * optional uint64 identifier = 2;
624 * optional bytes payload = 3;
625 * optional uint32 timestamp = 4;
626 * optional CMsgRemoteDeviceAuthorizationRequest.EKeyEscrowUsage usage = 5;
627 * optional string device_name = 6;
628 * optional string device_model = 7;
629 * optional string device_serial = 8;
630 * optional uint32 device_provisioning_id = 9;
631 * }
632 * enum EKeyEscrowUsage {
633 * k_EKeyEscrowUsageStreamingDevice = 0;
634 * }
635 * required bytes device_token = 1;
636 * optional string device_name = 2;
637 * required bytes encrypted_request = 3;
638 * }
639 */
640 static void
steamdiscover_dissect_body_authrequest(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,gint offset,gint bytes_left)641 steamdiscover_dissect_body_authrequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
642 gint offset, gint bytes_left)
643 {
644 guint len;
645 gint64 value;
646 protobuf_desc_t pb = { tvb, offset, bytes_left };
647 protobuf_tag_t tag = { 0, 0, 0 };
648 guint8* devicename;
649 while (protobuf_iter_next(&pb, &tag)) {
650 switch(tag.field_number) {
651 case STEAMDISCOVER_FN_AUTHREQUEST_DEVICETOKEN:
652 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_LENGTHDELIMITED);
653 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
654 proto_tree_add_item(tree, hf_steam_ihs_discovery_body_authrequest_devicetoken, pb.tvb,
655 pb.offset+len, (gint)value, ENC_NA);
656 len += (gint)value;
657 break;
658 case STEAMDISCOVER_FN_AUTHREQUEST_DEVICENAME:
659 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_LENGTHDELIMITED);
660 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
661 proto_tree_add_item(tree, hf_steam_ihs_discovery_body_authrequest_devicename, pb.tvb,
662 pb.offset+len, (gint)value, ENC_UTF_8|ENC_NA);
663 devicename = tvb_get_string_enc(pinfo->pool, pb.tvb, pb.offset+len, (gint)value, ENC_UTF_8);
664 if (devicename && strlen(devicename)) {
665 col_append_fstr(pinfo->cinfo, COL_INFO, " from %s", devicename);
666 }
667 len += (gint)value;
668 break;
669 case STEAMDISCOVER_FN_AUTHREQUEST_ENCRYPTEDREQUEST:
670 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_LENGTHDELIMITED);
671 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
672 proto_tree_add_item(tree, hf_steam_ihs_discovery_body_authrequest_encryptedrequest, pb.tvb,
673 pb.offset+len, (gint)value, ENC_NA);
674 len += (gint)value;
675 break;
676 default:
677 len = protobuf_dissect_unknown_field(&pb, &tag, pinfo, tree, NULL);
678 break;
679 }
680 protobuf_seek_forward(&pb, len);
681 }
682 }
683
684 /* Dissect a CMsgRemoteDeviceAuthorizationResponse protobuf message body.
685 *
686 * message CMsgRemoteDeviceAuthorizationResponse {
687 * required ERemoteDeviceAuthorizationResult result = 1;
688 * }
689 */
690 static void
steamdiscover_dissect_body_authresponse(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,gint offset,gint bytes_left)691 steamdiscover_dissect_body_authresponse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
692 gint offset, gint bytes_left)
693 {
694 gint len;
695 gint64 value;
696 protobuf_desc_t pb = { tvb, offset, bytes_left };
697 protobuf_tag_t tag = { 0, 0, 0 };
698 while (protobuf_iter_next(&pb, &tag)) {
699 switch(tag.field_number) {
700 case STEAMDISCOVER_FN_AUTHRESPONSE_AUTHRESULT:
701 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
702 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
703 proto_tree_add_uint64(tree, hf_steam_ihs_discovery_body_authresponse_authresult, pb.tvb,
704 pb.offset, len, (guint64)value);
705 col_add_fstr(pinfo->cinfo, COL_INFO, "%s Result=%"G_GUINT64_FORMAT"(%s)", hf_steam_ihs_discovery_header_msgtype_strings[STEAMDISCOVER_MSGTYPE_DEVICEAUTHORIZATIONRESPONSE].strptr,
706 (guint64)value, val64_to_str_const((guint64)value, hf_steam_ihs_discovery_body_authresponse_authresult_strings, "Unknown"));
707 break;
708 default:
709 len = protobuf_dissect_unknown_field(&pb, &tag, pinfo, tree, NULL);
710 break;
711 }
712 protobuf_seek_forward(&pb, len);
713 }
714 }
715
716 /* Dissect a CMsgRemoteDeviceStreamingRequest protobuf message body.
717 *
718 * message CMsgRemoteDeviceStreamingRequest {
719 * required uint32 request_id = 1;
720 * optional int32 maximum_resolution_x = 2;
721 * optional int32 maximum_resolution_y = 3;
722 * optional int32 audio_channel_count = 4 [default = 2];
723 * optional string device_version = 5;
724 * optional bool stream_desktop = 6;
725 * optional bytes device_token = 7;
726 * optional bytes pin = 8;
727 * optional bool enable_video_streaming = 9 [default = true];
728 * optional bool enable_audio_streaming = 10 [default = true];
729 * optional bool enable_input_streaming = 11 [default = true];
730 * }
731 */
732 static void
steamdiscover_dissect_body_streamingrequest(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,gint offset,gint bytes_left)733 steamdiscover_dissect_body_streamingrequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
734 gint offset, gint bytes_left)
735 {
736 gint len;
737 gint64 value;
738 protobuf_desc_t pb = { tvb, offset, bytes_left };
739 protobuf_tag_t tag = { 0, 0, 0 };
740 while (protobuf_iter_next(&pb, &tag)) {
741 switch(tag.field_number) {
742 case STEAMDISCOVER_FN_STREAMINGREQUEST_REQUESTID:
743 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
744 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
745 proto_tree_add_uint(tree, hf_steam_ihs_discovery_body_streamingrequest_requestid, pb.tvb,
746 pb.offset, len, (guint32)value);
747 col_add_fstr(pinfo->cinfo, COL_INFO, "%s ID=%08x", hf_steam_ihs_discovery_header_msgtype_strings[STEAMDISCOVER_MSGTYPE_DEVICESTREAMINGREQUEST].strptr, (guint32)value);
748 break;
749 case STEAMDISCOVER_FN_STREAMINGREQUEST_MAXIMUMRESOLUTIONX:
750 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
751 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
752 proto_tree_add_int(tree, hf_steam_ihs_discovery_body_streamingrequest_maximumresolutionx, pb.tvb,
753 pb.offset, len, (gint32)value);
754 break;
755 case STEAMDISCOVER_FN_STREAMINGREQUEST_MAXIMUMRESOLUTIONY:
756 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
757 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
758 proto_tree_add_int(tree, hf_steam_ihs_discovery_body_streamingrequest_maximumresolutiony, pb.tvb,
759 pb.offset, len, (gint32)value);
760 break;
761 case STEAMDISCOVER_FN_STREAMINGREQUEST_AUDIOCHANNELCOUNT:
762 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
763 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
764 proto_tree_add_int(tree, hf_steam_ihs_discovery_body_streamingrequest_audiochannelcount, pb.tvb,
765 pb.offset, len, (gint32)value);
766 break;
767 case STEAMDISCOVER_FN_STREAMINGREQUEST_DEVICEVERSION:
768 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_LENGTHDELIMITED);
769 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
770 proto_tree_add_item(tree, hf_steam_ihs_discovery_body_streamingrequest_deviceversion, pb.tvb, pb.offset+len, (gint)value, ENC_UTF_8|ENC_NA);
771 len += (gint)value;
772 break;
773 case STEAMDISCOVER_FN_STREAMINGREQUEST_STREAMDESKTOP:
774 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
775 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
776 proto_tree_add_boolean(tree, hf_steam_ihs_discovery_body_streamingrequest_streamdesktop, pb.tvb,
777 pb.offset, len, (gint32)value);
778 break;
779 case STEAMDISCOVER_FN_STREAMINGREQUEST_DEVICETOKEN:
780 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_LENGTHDELIMITED);
781 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
782 proto_tree_add_item(tree, hf_steam_ihs_discovery_body_streamingrequest_devicetoken, pb.tvb, pb.offset+len, (gint)value, ENC_NA);
783 len += (gint)value;
784 break;
785 case STEAMDISCOVER_FN_STREAMINGREQUEST_PIN:
786 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_LENGTHDELIMITED);
787 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
788 proto_tree_add_item(tree, hf_steam_ihs_discovery_body_streamingrequest_pin, pb.tvb, pb.offset+len, (gint)value, ENC_NA);
789 len += (gint)value;
790 break;
791 case STEAMDISCOVER_FN_STREAMINGREQUEST_ENABLEVIDEOSTREAMING:
792 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
793 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
794 proto_tree_add_boolean(tree, hf_steam_ihs_discovery_body_streamingrequest_enablevideostreaming, pb.tvb,
795 pb.offset, len, (gint32)value);
796 break;
797 case STEAMDISCOVER_FN_STREAMINGREQUEST_ENABLEAUDIOSTREAMING:
798 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
799 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
800 proto_tree_add_boolean(tree, hf_steam_ihs_discovery_body_streamingrequest_enableaudiostreaming, pb.tvb,
801 pb.offset, len, (gint32)value);
802 break;
803 case STEAMDISCOVER_FN_STREAMINGREQUEST_ENABLEINPUTSTREAMING:
804 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
805 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
806 proto_tree_add_boolean(tree, hf_steam_ihs_discovery_body_streamingrequest_enableinputstreaming, pb.tvb,
807 pb.offset, len, (gint32)value);
808 break;
809 default:
810 len = protobuf_dissect_unknown_field(&pb, &tag, pinfo, tree, NULL);
811 break;
812 }
813 protobuf_seek_forward(&pb, len);
814 }
815 }
816
817 /* Dissect a CMsgRemoteDeviceStreamingCancelRequest protobuf message body.
818 *
819 * message CMsgRemoteDeviceStreamingCancelRequest {
820 * required uint32 request_id = 1;
821 * }
822 */
823 static void
steamdiscover_dissect_body_streamingcancelrequest(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,gint offset,gint bytes_left)824 steamdiscover_dissect_body_streamingcancelrequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
825 gint offset, gint bytes_left)
826 {
827 guint len;
828 gint64 value;
829 protobuf_desc_t pb = { tvb, offset, bytes_left };
830 protobuf_tag_t tag = { 0, 0, 0 };
831 while (protobuf_iter_next(&pb, &tag)) {
832 switch(tag.field_number) {
833 case STEAMDISCOVER_FN_STREAMINGCANCELREQUEST_REQUESTID:
834 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
835 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
836 proto_tree_add_uint(tree, hf_steam_ihs_discovery_body_streamingcancelrequest_requestid, pb.tvb,
837 pb.offset, len, (guint32)value);
838 col_add_fstr(pinfo->cinfo, COL_INFO, "%s, ID=%08x", hf_steam_ihs_discovery_header_msgtype_strings[STEAMDISCOVER_MSGTYPE_DEVICESTREAMINGCANCELREQUEST].strptr, (guint32)value);
839 break;
840 default:
841 len = protobuf_dissect_unknown_field(&pb, &tag, pinfo, tree, NULL);
842 break;
843 }
844 protobuf_seek_forward(&pb, len);
845 }
846 }
847
848 /* Dissect a CMsgRemoteDeviceStreamingResponse protobuf message body.
849 *
850 * enum ERemoteDeviceStreamingResult {
851 * k_ERemoteDeviceStreamingSuccess = 0;
852 * k_ERemoteDeviceStreamingUnauthorized = 1;
853 * k_ERemoteDeviceStreamingScreenLocked = 2;
854 * k_ERemoteDeviceStreamingFailed = 3;
855 * k_ERemoteDeviceStreamingBusy = 4;
856 * k_ERemoteDeviceStreamingInProgress = 5;
857 * k_ERemoteDeviceStreamingCanceled = 6;
858 * k_ERemoteDeviceStreamingDriversNotInstalled = 7;
859 * k_ERemoteDeviceStreamingDisabled = 8;
860 * k_ERemoteDeviceStreamingBroadcastingActive = 9;
861 * k_ERemoteDeviceStreamingVRActive = 10;
862 * k_ERemoteDeviceStreamingPINRequired = 11;
863 * }
864 *
865 * message CMsgRemoteDeviceStreamingResponse {
866 * required uint32 request_id = 1;
867 * required ERemoteDeviceStreamingResult result = 2;
868 * optional uint32 port = 3;
869 * optional bytes encrypted_session_key = 4;
870 * optional int32 virtualhere_licensed_device_count_OBSOLETE = 5;
871 * }
872 */
873 static void
steamdiscover_dissect_body_streamingresponse(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,gint offset,gint bytes_left)874 steamdiscover_dissect_body_streamingresponse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
875 gint offset, gint bytes_left)
876 {
877 guint len;
878 gint64 value;
879 protobuf_desc_t pb = { tvb, offset, bytes_left };
880 protobuf_tag_t tag = { 0, 0, 0 };
881 while (protobuf_iter_next(&pb, &tag)) {
882 switch(tag.field_number) {
883 case STEAMDISCOVER_FN_STREAMINGRESPONSE_REQUESTID:
884 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
885 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
886 proto_tree_add_uint(tree, hf_steam_ihs_discovery_body_streamingresponse_requestid, pb.tvb,
887 pb.offset, len, (guint32)value);
888 col_append_fstr(pinfo->cinfo, COL_INFO, " ID=%08x", (guint32)value);
889 break;
890 case STEAMDISCOVER_FN_STREAMINGRESPONSE_RESULT:
891 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
892 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
893 proto_tree_add_uint64(tree, hf_steam_ihs_discovery_body_streamingresponse_result, pb.tvb,
894 pb.offset, len, (guint64)value);
895 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"));
896 break;
897 case STEAMDISCOVER_FN_STREAMINGRESPONSE_PORT:
898 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
899 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
900 proto_tree_add_uint(tree, hf_steam_ihs_discovery_body_streamingresponse_port, pb.tvb,
901 pb.offset, len, (guint32)value);
902 col_append_fstr(pinfo->cinfo, COL_INFO, " Port=%"G_GUINT32_FORMAT, (guint32)value);
903 break;
904 case STEAMDISCOVER_FN_STREAMINGRESPONSE_ENCRYPTEDSESSIONKEY:
905 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_LENGTHDELIMITED);
906 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
907 proto_tree_add_item(tree, hf_steam_ihs_discovery_body_streamingresponse_encryptedsessionkey, pb.tvb, pb.offset+len, (gint)value, ENC_NA);
908 len += (gint)value;
909 break;
910 case STEAMDISCOVER_FN_STREAMINGRESPONSE_VIRTUALHERELICENSEDDEVICECOUNT:
911 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_VARINT);
912 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
913 proto_tree_add_int(tree, hf_steam_ihs_discovery_body_streamingresponse_virtualherelicenseddevicecount, pb.tvb,
914 pb.offset, len, (gint32)value);
915 break;
916 default:
917 len = protobuf_dissect_unknown_field(&pb, &tag, pinfo, tree, NULL);
918 break;
919 }
920 protobuf_seek_forward(&pb, len);
921 }
922 }
923
924 /* Dissect a CMsgRemoteDeviceProofRequest protobuf message body.
925 *
926 * message CMsgRemoteDeviceProofRequest {
927 * required bytes challenge = 1;
928 * }
929 */
930 static void
steamdiscover_dissect_body_proofrequest(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,gint offset,gint bytes_left)931 steamdiscover_dissect_body_proofrequest(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
932 gint offset, gint bytes_left)
933 {
934 gint len;
935 gint64 value;
936 protobuf_desc_t pb = { tvb, offset, bytes_left };
937 protobuf_tag_t tag = { 0, 0, 0 };
938 while (protobuf_iter_next(&pb, &tag)) {
939 switch(tag.field_number) {
940 case STEAMDISCOVER_FN_PROOFREQUEST_CHALLENGE:
941 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_LENGTHDELIMITED);
942 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
943 proto_tree_add_item(tree, hf_steam_ihs_discovery_body_proofrequest_challenge, pb.tvb, pb.offset+len, (gint)value, ENC_NA);
944 len += (gint)value;
945 break;
946 default:
947 len = protobuf_dissect_unknown_field(&pb, &tag, pinfo, tree, NULL);
948 break;
949 }
950 protobuf_seek_forward(&pb, len);
951 }
952 }
953
954 /* Dissect a CMsgRemoteDeviceProofResponse protobuf message body.
955 *
956 * message CMsgRemoteDeviceProofResponse {
957 * required bytes response = 1;
958 * }
959 */
960 static void
steamdiscover_dissect_body_proofresponse(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,gint offset,gint bytes_left)961 steamdiscover_dissect_body_proofresponse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
962 gint offset, gint bytes_left)
963 {
964 gint len;
965 gint64 value;
966 protobuf_desc_t pb = { tvb, offset, bytes_left };
967 protobuf_tag_t tag = { 0, 0, 0 };
968 while (protobuf_iter_next(&pb, &tag)) {
969 switch(tag.field_number) {
970 case STEAMDISCOVER_FN_PROOFRESPONSE_RESPONSE:
971 STEAMDISCOVER_ENSURE_WIRETYPE(PROTOBUF_WIRETYPE_LENGTHDELIMITED);
972 value = get_varint64(pb.tvb, pb.offset, pb.bytes_left, &len);
973 proto_tree_add_item(tree, hf_steam_ihs_discovery_body_proofresponse_response, pb.tvb, pb.offset+len, (gint)value, ENC_NA);
974 len += (gint)value;
975 break;
976 default:
977 len = protobuf_dissect_unknown_field(&pb, &tag, pinfo, tree, NULL);
978 break;
979 }
980 protobuf_seek_forward(&pb, len);
981 }
982 }
983
984 static void
steamdiscover_dissect_body_unknown(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,gint offset,gint bytes_left)985 steamdiscover_dissect_body_unknown(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
986 gint offset, gint bytes_left)
987 {
988 gint len;
989 protobuf_desc_t pb = { tvb, offset, bytes_left };
990 protobuf_tag_t tag = { 0, 0, 0 };
991 while (protobuf_iter_next(&pb, &tag)) {
992 len = protobuf_dissect_unknown_field(&pb, &tag, pinfo, tree, NULL);
993 protobuf_seek_forward(&pb, len);
994 }
995 }
996
997 /* Code to actually dissect the packets */
998 static int
dissect_steam_ihs_discovery(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)999 dissect_steam_ihs_discovery(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1000 void *data _U_)
1001 {
1002 /* Set up structures needed to add the protocol subtree and manage it */
1003 proto_item *ti;
1004 proto_tree *steam_ihs_discovery_tree;
1005 /* Other misc. local variables. */
1006 gint offset = 0;
1007 gint header_length = 0;
1008 gint body_length = 0;
1009 gint total_length = 0;
1010 gint64 msg_type;
1011
1012 /* Check that the packet is long enough for it to belong to us. */
1013 if (tvb_reported_length(tvb) < STEAM_IHS_DISCOVERY_MIN_LENGTH)
1014 return 0;
1015
1016 if (tvb_captured_length(tvb) < STEAM_IHS_DISCOVERY_MIN_LENGTH)
1017 return 0;
1018
1019 /* Check if packet starts with the 8 byte signature value. */
1020 if (tvb_get_ntoh64(tvb, 0) != STEAM_IHS_DISCOVERY_SIGNATURE_VALUE)
1021 return 0;
1022
1023 /* Parse header and body lengths.
1024 *
1025 * A packet looks like this:
1026 * 1. Signature Value (8 bytes)
1027 * 2. Header length (4 bytes)
1028 * 3. Header
1029 * 4. Body length (4 bytes)
1030 * 6. Body
1031 * */
1032 header_length = tvb_get_letohl(tvb, STEAM_IHS_DISCOVERY_SIGNATURE_LENGTH);
1033 body_length = tvb_get_letohl(tvb, STEAM_IHS_DISCOVERY_SIGNATURE_LENGTH + 4 + header_length);
1034 total_length = STEAM_IHS_DISCOVERY_SIGNATURE_LENGTH + 4 + header_length + 4 + body_length;
1035
1036 /* Check if expected and captured packet length are equal. */
1037 if (tvb_reported_length(tvb) != (guint)total_length)
1038 return 0;
1039
1040 if (tvb_captured_length(tvb) != (guint)total_length)
1041 return 0;
1042
1043 /* Set the Protocol column to the constant string of steam_ihs_discovery */
1044 col_set_str(pinfo->cinfo, COL_PROTOCOL, "STEAMDISCOVER");
1045
1046 col_clear(pinfo->cinfo, COL_INFO);
1047
1048 /* create display subtree for the protocol */
1049 ti = proto_tree_add_item(tree, proto_steam_ihs_discovery, tvb, 0, -1, ENC_NA);
1050
1051 steam_ihs_discovery_tree = proto_item_add_subtree(ti, ett_steam_ihs_discovery);
1052
1053 proto_tree_add_item(steam_ihs_discovery_tree, hf_steam_ihs_discovery_signature, tvb,
1054 offset, STEAM_IHS_DISCOVERY_SIGNATURE_LENGTH, ENC_LITTLE_ENDIAN);
1055 offset += STEAM_IHS_DISCOVERY_SIGNATURE_LENGTH;
1056
1057 proto_tree_add_item(steam_ihs_discovery_tree, hf_steam_ihs_discovery_header_length, tvb,
1058 offset, 4, ENC_LITTLE_ENDIAN);
1059 offset += 4;
1060
1061 msg_type = steamdiscover_dissect_header(tvb, pinfo, steam_ihs_discovery_tree, offset, header_length);
1062
1063 if ((0 <= msg_type) && (msg_type <= STEAMDISCOVER_MSGTYPES_MAX)) {
1064 col_set_str(pinfo->cinfo, COL_INFO, hf_steam_ihs_discovery_header_msgtype_strings[msg_type].strptr);
1065 } else {
1066 col_set_str(pinfo->cinfo, COL_INFO, "Unknown Message");
1067 }
1068
1069 offset += header_length;
1070
1071 proto_tree_add_item(steam_ihs_discovery_tree, hf_steam_ihs_discovery_body_length, tvb,
1072 offset, 4, ENC_LITTLE_ENDIAN);
1073 offset += 4;
1074
1075 switch(msg_type)
1076 {
1077 case STEAMDISCOVER_MSGTYPE_CLIENTBROADCASTMSGDISCOVERY:
1078 steamdiscover_dissect_body_discovery(tvb, pinfo, steam_ihs_discovery_tree, offset, body_length);
1079 break;
1080 case STEAMDISCOVER_MSGTYPE_CLIENTBROADCASTMSGSTATUS:
1081 steamdiscover_dissect_body_status(tvb, pinfo, steam_ihs_discovery_tree, offset, body_length);
1082 break;
1083 case STEAMDISCOVER_MSGTYPE_CLIENTBROADCASTMSGOFFLINE:
1084 /* Message seems to have no body */
1085 break;
1086 case STEAMDISCOVER_MSGTYPE_DEVICEAUTHORIZATIONREQUEST:
1087 steamdiscover_dissect_body_authrequest(tvb, pinfo, steam_ihs_discovery_tree, offset, body_length);
1088 break;
1089 case STEAMDISCOVER_MSGTYPE_DEVICEAUTHORIZATIONCANCELREQUEST:
1090 /* Message seems to have no body */
1091 break;
1092 case STEAMDISCOVER_MSGTYPE_DEVICEAUTHORIZATIONRESPONSE:
1093 steamdiscover_dissect_body_authresponse(tvb, pinfo, steam_ihs_discovery_tree, offset, body_length);
1094 break;
1095 case STEAMDISCOVER_MSGTYPE_DEVICESTREAMINGREQUEST:
1096 steamdiscover_dissect_body_streamingrequest(tvb, pinfo, steam_ihs_discovery_tree, offset, body_length);
1097 break;
1098 case STEAMDISCOVER_MSGTYPE_DEVICESTREAMINGCANCELREQUEST:
1099 steamdiscover_dissect_body_streamingcancelrequest(tvb, pinfo, steam_ihs_discovery_tree, offset, body_length);
1100 break;
1101 case STEAMDISCOVER_MSGTYPE_DEVICESTREAMINGRESPONSE:
1102 steamdiscover_dissect_body_streamingresponse(tvb, pinfo, steam_ihs_discovery_tree, offset, body_length);
1103 break;
1104 case STEAMDISCOVER_MSGTYPE_DEVICEPROOFREQUEST:
1105 steamdiscover_dissect_body_proofrequest(tvb, pinfo, steam_ihs_discovery_tree, offset, body_length);
1106 break;
1107 case STEAMDISCOVER_MSGTYPE_DEVICEPROOFRESPONSE:
1108 steamdiscover_dissect_body_proofresponse(tvb, pinfo, steam_ihs_discovery_tree, offset, body_length);
1109 break;
1110 default:
1111 steamdiscover_dissect_body_unknown(tvb, pinfo, steam_ihs_discovery_tree, offset, body_length);
1112 break;
1113 }
1114
1115 return tvb_captured_length(tvb);
1116 }
1117
1118 /* Register the protocol with Wireshark. */
1119 void
proto_register_steam_ihs_discovery(void)1120 proto_register_steam_ihs_discovery(void)
1121 {
1122 module_t *steam_ihs_discovery_module;
1123 expert_module_t *expert_steam_ihs_discovery;
1124
1125 static hf_register_info hf[] = {
1126 /* Non-protobuf header fields */
1127 { &hf_steam_ihs_discovery_signature,
1128 { "Signature", "steam_ihs_discovery.signature",
1129 FT_UINT64, BASE_HEX, NULL, 0,
1130 "Every packet of the Steam In-Home Streaming Discovery Protocol begins with this signature.", HFILL }
1131 },
1132 { &hf_steam_ihs_discovery_header_length,
1133 { "Header Length", "steam_ihs_discovery.header_length",
1134 FT_UINT32, BASE_DEC, NULL, 0,
1135 NULL, HFILL }
1136 },
1137 { &hf_steam_ihs_discovery_body_length,
1138 { "Body Length", "steam_ihs_discovery.body_length",
1139 FT_UINT32, BASE_DEC, NULL, 0,
1140 NULL, HFILL }
1141 },
1142 { &hf_steam_ihs_discovery_unknown_data,
1143 { "Unknown Data", "steam_ihs_discovery.unknown_data",
1144 FT_BYTES, BASE_NONE, NULL, 0,
1145 NULL, HFILL }
1146 },
1147 { &hf_steam_ihs_discovery_unknown_number,
1148 { "Unknown Number", "steam_ihs_discovery.unknown_number",
1149 FT_UINT64, BASE_DEC_HEX, NULL, 0,
1150 NULL, HFILL }
1151 },
1152 /* CMsgRemoteClientBroadcastHeader */
1153 { &hf_steam_ihs_discovery_header_clientid,
1154 { "Client ID", "steam_ihs_discovery.header_client_id",
1155 FT_UINT64, BASE_DEC_HEX, NULL, 0,
1156 NULL, HFILL }
1157 },
1158 { &hf_steam_ihs_discovery_header_msgtype,
1159 { "Message Type", "steam_ihs_discovery.header_msg_type",
1160 FT_UINT64, BASE_DEC|BASE_VAL64_STRING, VALS64(hf_steam_ihs_discovery_header_msgtype_strings), 0,
1161 NULL, HFILL }
1162 },
1163 { &hf_steam_ihs_discovery_header_instanceid,
1164 { "Instance ID", "steam_ihs_discovery.header_instance_id",
1165 FT_UINT64, BASE_DEC_HEX, NULL, 0,
1166 NULL, HFILL }
1167 },
1168 /* CMsgRemoteClientBroadcastDiscovery message */
1169 { &hf_steam_ihs_discovery_body_discovery_seqnum,
1170 { "Sequence Number", "steam_ihs_discovery.body_discovery_seqnum",
1171 FT_UINT32, BASE_DEC, NULL, 0,
1172 NULL, HFILL }
1173 },
1174 { &hf_steam_ihs_discovery_body_discovery_clientids,
1175 { "Client IDs", "steam_ihs_discovery.body_discovery_clientids",
1176 FT_UINT64, BASE_HEX, NULL, 0,
1177 NULL, HFILL }
1178 },
1179 /* CMsgRemoteClientBroadcastStatus message */
1180 { &hf_steam_ihs_discovery_body_status_version,
1181 { "Version", "steam_ihs_discovery.body_status_version",
1182 FT_INT32, BASE_DEC, NULL, 0,
1183 NULL, HFILL }
1184 },
1185 { &hf_steam_ihs_discovery_body_status_minversion,
1186 { "Minimum Version", "steam_ihs_discovery.body_status_minversion",
1187 FT_INT32, BASE_DEC, NULL, 0,
1188 NULL, HFILL }
1189 },
1190 { &hf_steam_ihs_discovery_body_status_connectport,
1191 { "Connect Port", "steam_ihs_discovery.body_status_connectport",
1192 FT_UINT32, BASE_DEC, NULL, 0,
1193 NULL, HFILL }
1194 },
1195 { &hf_steam_ihs_discovery_body_status_hostname,
1196 { "Hostname", "steam_ihs_discovery.body_status_hostname",
1197 FT_STRING, STR_UNICODE, NULL, 0,
1198 NULL, HFILL }
1199 },
1200 { &hf_steam_ihs_discovery_body_status_enabledservices,
1201 { "Enabled Services", "steam_ihs_discovery.body_status_enabledservices",
1202 FT_UINT32, BASE_HEX, NULL, 0,
1203 NULL, HFILL }
1204 },
1205 { &hf_steam_ihs_discovery_body_status_ostype,
1206 { "OS Type", "steam_ihs_discovery.body_status_ostype",
1207 FT_INT32, BASE_DEC, NULL, 0,
1208 NULL, HFILL }
1209 },
1210 { &hf_steam_ihs_discovery_body_status_is64bit,
1211 { "Is 64 Bit", "steam_ihs_discovery.body_status_is64bit",
1212 FT_BOOLEAN, BASE_NONE, NULL, 0,
1213 NULL, HFILL }
1214 },
1215 { &hf_steam_ihs_discovery_body_status_euniverse,
1216 { "EUniverse", "steam_ihs_discovery.body_status_euniverse",
1217 FT_INT32, BASE_DEC, NULL, 0,
1218 NULL, HFILL }
1219 },
1220 { &hf_steam_ihs_discovery_body_status_timestamp,
1221 { "Timestamp", "steam_ihs_discovery.body_status_timestamp",
1222 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0,
1223 NULL, HFILL }
1224 },
1225 { &hf_steam_ihs_discovery_body_status_screenlocked,
1226 { "Screen Locked", "steam_ihs_discovery.body_status_screenlocked",
1227 FT_BOOLEAN, BASE_NONE, NULL, 0,
1228 NULL, HFILL }
1229 },
1230 { &hf_steam_ihs_discovery_body_status_gamesrunning,
1231 { "Games Running", "steam_ihs_discovery.body_status_gamesrunning",
1232 FT_BOOLEAN, BASE_NONE, NULL, 0,
1233 NULL, HFILL }
1234 },
1235 { &hf_steam_ihs_discovery_body_status_macaddresses,
1236 { "MAC Addresses", "steam_ihs_discovery.body_status_macaddresses",
1237 FT_STRING, STR_ASCII, NULL, 0,
1238 NULL, HFILL }
1239 },
1240 /* CMsgRemoteClientBroadcastStatus.User */
1241 { &hf_steam_ihs_discovery_body_status_user_steamid,
1242 { "Steam ID", "steam_ihs_discovery.body_status_user_steamid",
1243 FT_UINT64, BASE_DEC, NULL, 0,
1244 NULL, HFILL }
1245 },
1246 { &hf_steam_ihs_discovery_body_status_user_authkeyid,
1247 { "Auth Key ID", "steam_ihs_discovery.body_status_user_authkeyid",
1248 FT_UINT32, BASE_DEC, NULL, 0,
1249 NULL, HFILL }
1250 },
1251 /* CMsgRemoteDeviceAuthorizationRequest */
1252 { &hf_steam_ihs_discovery_body_authrequest_devicetoken,
1253 { "Device Token", "steam_ihs_discovery.body_authrequest_devicetoken",
1254 FT_BYTES, BASE_NONE, NULL, 0,
1255 NULL, HFILL }
1256 },
1257 { &hf_steam_ihs_discovery_body_authrequest_devicename,
1258 { "Device Name", "steam_ihs_discovery.body_authrequest_devicename",
1259 FT_STRING, STR_UNICODE, NULL, 0,
1260 NULL, HFILL }
1261 },
1262 { &hf_steam_ihs_discovery_body_authrequest_encryptedrequest,
1263 { "Encrypted Request", "steam_ihs_discovery.body_authrequest_encryptedrequest",
1264 FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0,
1265 NULL, HFILL }
1266 },
1267 /* CMsgRemoteDeviceAuthorizationResponse */
1268 { &hf_steam_ihs_discovery_body_authresponse_authresult,
1269 { "Result", "steam_ihs_discovery.body_authresponse_authresult",
1270 FT_UINT64, BASE_DEC|BASE_VAL64_STRING, VALS64(hf_steam_ihs_discovery_body_authresponse_authresult_strings), 0,
1271 NULL, HFILL }
1272 },
1273 /* CMsgRemoteDeviceStreamingRequest */
1274 { &hf_steam_ihs_discovery_body_streamingrequest_requestid,
1275 { "Request ID", "steam_ihs_discovery.body_streamingrequest_requestid",
1276 FT_UINT32, BASE_HEX, NULL, 0,
1277 NULL, HFILL }
1278 },
1279 { &hf_steam_ihs_discovery_body_streamingrequest_maximumresolutionx,
1280 { "Maximum Resolution X", "steam_ihs_discovery.body_streamingrequest_maximumresolutionx",
1281 FT_INT32, BASE_DEC, NULL, 0,
1282 NULL, HFILL }
1283 },
1284 { &hf_steam_ihs_discovery_body_streamingrequest_maximumresolutiony,
1285 { "Maximum Resolution Y", "steam_ihs_discovery.body_streamingrequest_maximumresolutiony",
1286 FT_INT32, BASE_DEC, NULL, 0,
1287 NULL, HFILL }
1288 },
1289 { &hf_steam_ihs_discovery_body_streamingrequest_audiochannelcount,
1290 { "Audio Channel Count", "steam_ihs_discovery.body_streamingrequest_audiochannelcount",
1291 FT_INT32, BASE_DEC, NULL, 0,
1292 NULL, HFILL }
1293 },
1294 { &hf_steam_ihs_discovery_body_streamingrequest_deviceversion,
1295 { "Device Version", "steam_ihs_discovery.body_streamingrequest_deviceversion",
1296 FT_STRING, STR_UNICODE, NULL, 0,
1297 NULL, HFILL }
1298 },
1299 { &hf_steam_ihs_discovery_body_streamingrequest_streamdesktop,
1300 { "Stream Desktop", "steam_ihs_discovery.body_streamingrequest_streamdesktop",
1301 FT_BOOLEAN, BASE_NONE, NULL, 0,
1302 NULL, HFILL }
1303 },
1304 { &hf_steam_ihs_discovery_body_streamingrequest_devicetoken,
1305 { "Device Token", "steam_ihs_discovery.body_streamingrequest_devicetoken",
1306 FT_BYTES, BASE_NONE, NULL, 0,
1307 NULL, HFILL }
1308 },
1309 { &hf_steam_ihs_discovery_body_streamingrequest_pin,
1310 { "PIN", "steam_ihs_discovery.body_streamingrequest_pin",
1311 FT_BYTES, BASE_NONE, NULL, 0,
1312 NULL, HFILL }
1313 },
1314 { &hf_steam_ihs_discovery_body_streamingrequest_enablevideostreaming,
1315 { "Enable Video Streaming", "steam_ihs_discovery.body_streamingrequest_enablevideostreaming",
1316 FT_BOOLEAN, BASE_NONE, NULL, 0,
1317 NULL, HFILL }
1318 },
1319 { &hf_steam_ihs_discovery_body_streamingrequest_enableaudiostreaming,
1320 { "Enable Audio Streaming", "steam_ihs_discovery.body_streamingrequest_enableaudiostreaming",
1321 FT_BOOLEAN, BASE_NONE, NULL, 0,
1322 NULL, HFILL }
1323 },
1324 { &hf_steam_ihs_discovery_body_streamingrequest_enableinputstreaming,
1325 { "Enable Input Streaming", "steam_ihs_discovery.body_streamingrequest_enableinputstreaming",
1326 FT_BOOLEAN, BASE_NONE, NULL, 0,
1327 NULL, HFILL }
1328 },
1329 /* CMsgRemoteDeviceStreamingCancelRequest */
1330 { &hf_steam_ihs_discovery_body_streamingcancelrequest_requestid,
1331 { "Request ID", "steam_ihs_discovery.body_streamingcancelrequest_requestid",
1332 FT_UINT32, BASE_HEX, NULL, 0,
1333 NULL, HFILL }
1334 },
1335 /* CMsgRemoteDeviceStreamingResponse */
1336 { &hf_steam_ihs_discovery_body_streamingresponse_requestid,
1337 { "Request ID", "steam_ihs_discovery.body_streamingresponse_requestid",
1338 FT_UINT32, BASE_HEX, NULL, 0,
1339 NULL, HFILL }
1340 },
1341 { &hf_steam_ihs_discovery_body_streamingresponse_result,
1342 { "Result", "steam_ihs_discovery.body_streamingresponse_result",
1343 FT_UINT64, BASE_DEC|BASE_VAL64_STRING, VALS64(hf_steam_ihs_discovery_body_streamingresponse_result_strings), 0,
1344 NULL, HFILL }
1345 },
1346 { &hf_steam_ihs_discovery_body_streamingresponse_port,
1347 { "Port", "steam_ihs_discovery.body_streamingresponse_port",
1348 FT_UINT32, BASE_DEC, NULL, 0,
1349 NULL, HFILL }
1350 },
1351 { &hf_steam_ihs_discovery_body_streamingresponse_encryptedsessionkey,
1352 { "Encrypted Session Key", "steam_ihs_discovery.body_streamingresponse_encryptedsessionkey",
1353 FT_BYTES, BASE_NONE, NULL, 0,
1354 NULL, HFILL }
1355 },
1356 { &hf_steam_ihs_discovery_body_streamingresponse_virtualherelicenseddevicecount,
1357 { "VirtualHere Licensed Device Count", "steam_ihs_discovery.body_streamingresponse_virtualherelicenseddevicecount",
1358 FT_INT32, BASE_DEC, NULL, 0,
1359 NULL, HFILL }
1360 },
1361 /* CMsgRemoteDeviceProofRequest */
1362 { &hf_steam_ihs_discovery_body_proofrequest_challenge,
1363 { "Challenge", "steam_ihs_discovery.body_proofrequest_challenge",
1364 FT_BYTES, BASE_NONE, NULL, 0,
1365 NULL, HFILL }
1366 },
1367 /* CMsgRemoteDeviceProofResponse */
1368 { &hf_steam_ihs_discovery_body_proofresponse_response,
1369 { "Response", "steam_ihs_discovery.body_proofresponse_response",
1370 FT_BYTES, BASE_NONE, NULL, 0,
1371 NULL, HFILL }
1372 }
1373 };
1374
1375 /* Setup protocol subtree array */
1376 static gint *ett[] = {
1377 &ett_steam_ihs_discovery,
1378 &ett_steam_ihs_discovery_body_status_user
1379 };
1380
1381 /* Setup protocol expert items */
1382 static ei_register_info ei[] = {
1383 { &ei_steam_ihs_discovery_unknown_data,
1384 { "steam_ihs_discovery.unknowndata", PI_UNDECODED, PI_WARN,
1385 "Unknown data section", EXPFILL }
1386 },
1387 { &ei_steam_ihs_discovery_unknown_number,
1388 { "steam_ihs_discovery.unknownnumber", PI_UNDECODED, PI_WARN,
1389 "Unknown numeric protobuf field", EXPFILL }
1390 },
1391 { &ei_steam_ihs_discovery_unknown_lengthdelimited,
1392 { "steam_ihs_discovery.unknownlengthdelimited", PI_UNDECODED, PI_WARN,
1393 "Unknown length-delimited protobuf field", EXPFILL }
1394 },
1395 { &ei_steam_ihs_discovery_invalid_wiretype,
1396 { "steam_ihs_discovery.invalid_wiretype", PI_MALFORMED, PI_ERROR,
1397 "Unexpected wire type", EXPFILL }
1398 },
1399 { &ei_steam_ihs_discovery_invalid_length,
1400 { "steam_ihs_discovery.invalid_length", PI_MALFORMED, PI_ERROR,
1401 "Length-delimited field has invalid length", EXPFILL }
1402 }
1403 };
1404
1405 /* Register the protocol name and description */
1406 proto_steam_ihs_discovery = proto_register_protocol("Steam In-Home Streaming Discovery Protocol",
1407 "Steam IHS Discovery", "steam_ihs_discovery");
1408
1409 /* Required function calls to register the header fields and subtrees */
1410 proto_register_field_array(proto_steam_ihs_discovery, hf, array_length(hf));
1411 proto_register_subtree_array(ett, array_length(ett));
1412
1413 /* Required function calls to register expert items */
1414 expert_steam_ihs_discovery = expert_register_protocol(proto_steam_ihs_discovery);
1415 expert_register_field_array(expert_steam_ihs_discovery, ei, array_length(ei));
1416
1417 /* Register a preferences module. */
1418 steam_ihs_discovery_module = prefs_register_protocol(proto_steam_ihs_discovery,
1419 proto_reg_handoff_steam_ihs_discovery);
1420
1421 /* Register an example port preference */
1422 prefs_register_uint_preference(steam_ihs_discovery_module, "udp.port", "steam_ihs_discovery UDP Port",
1423 " Steam IHS Discovery UDP port if other than the default",
1424 10, &udp_port_pref);
1425 }
1426
1427 void
proto_reg_handoff_steam_ihs_discovery(void)1428 proto_reg_handoff_steam_ihs_discovery(void)
1429 {
1430 static gboolean initialized = FALSE;
1431 static dissector_handle_t steam_ihs_discovery_handle;
1432 static int current_port;
1433
1434 if (!initialized) {
1435 steam_ihs_discovery_handle = create_dissector_handle(dissect_steam_ihs_discovery,
1436 proto_steam_ihs_discovery);
1437 initialized = TRUE;
1438
1439 } else {
1440 dissector_delete_uint("udp.port", current_port, steam_ihs_discovery_handle);
1441 }
1442
1443 current_port = udp_port_pref;
1444
1445 dissector_add_uint("udp.port", current_port, steam_ihs_discovery_handle);
1446 }
1447
1448 /*
1449 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1450 *
1451 * Local variables:
1452 * c-basic-offset: 4
1453 * tab-width: 8
1454 * indent-tabs-mode: nil
1455 * End:
1456 *
1457 * vi: set shiftwidth=4 tabstop=8 expandtab:
1458 * :indentSize=4:tabSize=8:noTabs=true:
1459 */
1460