2 * This is a dissector for the DirectPlay protocol.
3 * Copyright 2006 - 2008 by Kai Blin
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
16 #include <epan/packet.h>
17 #include <epan/aftypes.h>
20 /* function declarations */
21 void proto_register_dplay(void);
22 void proto_reg_handoff_dplay(void);
24 static void dissect_dplay(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
);
25 static int dissect_type1a_message(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
);
27 static int proto_dplay
;
29 /* Common data fields */
30 static int hf_dplay_size
; /* Size of the whole data */
31 static int hf_dplay_token
;
32 static int hf_dplay_saddr_af
; /* WINSOCK_AF_INET, as this dissector does not handle IPX yet */
33 static int hf_dplay_saddr_port
; /* port to use for the reply to this packet */
34 static int hf_dplay_saddr_ip
; /* IP to use for the reply to this packet, or 0.0.0.0,
35 then use the same IP as this packet used. */
36 static int hf_dplay_saddr_padding
; /* null padding used in s_addr_in structures */
37 static int hf_dplay_play_str
; /* always "play" without a null terminator */
38 static int hf_dplay_command
; /* the dplay command this message contains*/
39 static int hf_dplay_proto_dialect
; /* 0x0b00 for dplay7, 0x0e00 for dplay9 */
40 static int hf_dplay_play_str_2
; /* packet type 0x0015 encapsulates another packet */
41 static int hf_dplay_command_2
; /* that also has a "play" string, a command and a */
42 static int hf_dplay_proto_dialect_2
; /* protocol dialect, same as above */
43 static const int DPLAY_HEADER_OFFSET
= 28; /* The dplay header is 28 bytes in size */
44 static int hf_dplay_player_msg
;
46 /* The following fields are not part of the header, but hopefully have the same
47 * meaning for all packets they show up in. */
49 static int hf_dplay_sess_desc_flags
; /* This is a 32bit field with some sort of a flag */
50 static int hf_dplay_flags_no_create_players
;
51 static int hf_dplay_flags_0002
;
52 static int hf_dplay_flags_migrate_host
;
53 static int hf_dplay_flags_short_player_msg
;
54 static int hf_dplay_flags_ignored
;
55 static int hf_dplay_flags_can_join
;
56 static int hf_dplay_flags_use_ping
;
57 static int hf_dplay_flags_no_player_updates
;
58 static int hf_dplay_flags_use_auth
;
59 static int hf_dplay_flags_private_session
;
60 static int hf_dplay_flags_password_req
;
61 static int hf_dplay_flags_route
;
62 static int hf_dplay_flags_server_player_only
;
63 static int hf_dplay_flags_reliable
;
64 static int hf_dplay_flags_preserve_order
;
65 static int hf_dplay_flags_optimize_latency
;
66 static int hf_dplay_flags_acqire_voice
;
67 static int hf_dplay_flags_no_sess_desc_changes
;
69 #define DPLAY_FLAG_NO_CREATE_PLAYERS 0x00000001
70 #define DPLAY_FLAG_0002 0x00000002
71 #define DPLAY_FLAG_MIGRATE_HOST 0x00000004
72 #define DPLAY_FLAG_SHORT_PLAYER_MSG 0x00000008
73 #define DPLAY_FLAG_IGNORED 0x00000010
74 #define DPLAY_FLAG_CAN_JOIN 0x00000020
75 #define DPLAY_FLAG_USE_PING 0x00000040
76 #define DPLAY_FLAG_NO_P_UPD 0x00000080
77 #define DPLAY_FLAG_USE_AUTH 0x00000100
78 #define DPLAY_FLAG_PRIV_SESS 0x00000200
79 #define DPLAY_FLAG_PASS_REQ 0x00000400
80 #define DPLAY_FLAG_ROUTE 0x00000800
81 #define DPLAY_FLAG_SRV_ONLY 0x00001000
82 #define DPLAY_FLAG_RELIABLE 0x00002000
83 #define DPLAY_FLAG_ORDER 0x00004000
84 #define DPLAY_FLAG_OPT_LAT 0x00008000
85 #define DPLAY_FLAG_ACQ_VOICE 0x00010000
86 #define DPLAY_FLAG_NO_SESS_DESC_CHANGES 0x00020000
88 /* Session description structure fields */
89 static int hf_dplay_sess_desc_length
;
90 static int hf_dplay_game_guid
;
91 static int hf_dplay_instance_guid
;
92 static int hf_dplay_max_players
;
93 static int hf_dplay_curr_players
;
94 static int hf_dplay_sess_name_ptr
;
95 static int hf_dplay_passwd_ptr
;
96 static int hf_dplay_sess_desc_reserved_1
;
97 static int hf_dplay_sess_desc_reserved_2
;
98 static int hf_dplay_sess_desc_user_1
;
99 static int hf_dplay_sess_desc_user_2
;
100 static int hf_dplay_sess_desc_user_3
;
101 static int hf_dplay_sess_desc_user_4
;
103 /* PackedPlayer structure fields */
104 static int hf_dplay_pp_size
;
105 static int hf_dplay_pp_flags
;
106 static int hf_dplay_pp_flag_sysplayer
;
107 static int hf_dplay_pp_flag_nameserver
;
108 static int hf_dplay_pp_flag_in_group
;
109 static int hf_dplay_pp_flag_sending
;
110 static int hf_dplay_pp_id
;
111 static int hf_dplay_pp_short_name_len
;
112 static int hf_dplay_pp_long_name_len
;
113 static int hf_dplay_pp_sp_data_size
;
114 static int hf_dplay_pp_player_data_size
;
115 static int hf_dplay_pp_num_players
;
116 static int hf_dplay_pp_system_player
;
117 static int hf_dplay_pp_fixed_size
;
118 static int hf_dplay_pp_dialect
;
119 static int hf_dplay_pp_unknown_1
;
120 static int hf_dplay_pp_short_name
;
121 static int hf_dplay_pp_long_name
;
122 static int hf_dplay_pp_sp_data
;
123 static int hf_dplay_pp_player_data
;
124 static int hf_dplay_pp_player_id
;
125 static int hf_dplay_pp_parent_id
;
126 #define DPLAY_PP_FLAG_SYSPLAYER 0x00000001
127 #define DPLAY_PP_FLAG_NAMESERVER 0x00000002
128 #define DPLAY_PP_FLAG_IN_GROUP 0x00000004
129 #define DPLAY_PP_FLAG_SENDING 0x00000008
131 /* SuperPackedPlayer structure fields */
132 static int hf_dplay_spp_size
;
133 static int hf_dplay_spp_flags
;
134 static int hf_dplay_spp_flags_sysplayer
;
135 static int hf_dplay_spp_flags_nameserver
;
136 static int hf_dplay_spp_flags_in_group
;
137 static int hf_dplay_spp_flags_sending
;
138 static int hf_dplay_spp_id
;
139 static int hf_dplay_spp_player_info_mask
;
140 static int hf_dplay_spp_have_short_name
;
141 static int hf_dplay_spp_have_long_name
;
142 static int hf_dplay_spp_sp_length_type
;
143 static int hf_dplay_spp_pd_length_type
;
144 static int hf_dplay_spp_player_count_type
;
145 static int hf_dplay_spp_have_parent_id
;
146 static int hf_dplay_spp_shortcut_count_type
;
147 static int hf_dplay_spp_dialect
;
148 static int hf_dplay_spp_sys_player_id
;
149 static int hf_dplay_spp_short_name
;
150 static int hf_dplay_spp_long_name
;
151 static int hf_dplay_spp_player_data_length
;
152 static int hf_dplay_spp_player_data
;
153 static int hf_dplay_spp_sp_data_length
;
154 static int hf_dplay_spp_sp_data
;
155 static int hf_dplay_spp_player_count
;
156 static int hf_dplay_spp_player_id
;
157 static int hf_dplay_spp_parent_id
;
158 static int hf_dplay_spp_shortcut_count
;
159 static int hf_dplay_spp_shortcut_id
;
160 #define DPLAY_SPP_FLAG_SYSPLAYER 0x00000001
161 #define DPLAY_SPP_FLAG_NAMESERVER 0x00000002
162 #define DPLAY_SPP_FLAG_IN_GROUP 0x00000004
163 #define DPLAY_SPP_FLAG_SENDING 0x00000008
165 /* SecurityDesc structure fields */
166 static int hf_dplay_sd_size
;
167 static int hf_dplay_sd_flags
;
168 static int hf_dplay_sd_sspi
;
169 static int hf_dplay_sd_capi
;
170 static int hf_dplay_sd_capi_type
;
171 static int hf_dplay_sd_enc_alg
;
173 /* Message Type 0x0001 data fields */
174 static int hf_dplay_type_01_name_offset
;
175 static int hf_dplay_type_01_game_name
;
177 /* Message Type 0x0002 data fields */
178 static int hf_dplay_type_02_game_guid
;
179 static int hf_dplay_type_02_password_offset
;
180 static int hf_dplay_type_02_flags
;
181 static int hf_dplay_type_02_password
;
182 static int hf_enum_sess_flag_join
;
183 static int hf_enum_sess_flag_all
;
184 static int hf_enum_sess_flag_passwd
;
185 #define DPLAY_ENUM_SESS_FLAG_JOIN 0x00000001
186 #define DPLAY_ENUM_SESS_FLAG_ALL 0x00000002
187 #define DPLAY_ENUM_SESS_FLAG_PASSWD 0x00000040
189 /* Message Type 0x0005 data fields */
190 static int hf_dplay_type_05_flags
;
191 static int hf_dplay_type_05_system_player
;
192 static int hf_dplay_type_05_name_server
;
193 static int hf_dplay_type_05_local
;
194 static int hf_dplay_type_05_unknown
; /* unknown, but always set */
195 static int hf_dplay_type_05_secure
;
196 #define DPLAY_TYPE05_FLAG_SYSPLAYER 0x00000001
197 #define DPLAY_TYPE05_FLAG_NAMESERVER 0x00000002
198 #define DPLAY_TYPE05_FLAG_LOCAL 0x00000004
199 #define DPLAY_TYPE05_FLAG_UNKNOWN 0x00000008
200 #define DPLAY_TYPE05_FLAG_SECURE 0x00000200
202 /* Message Type 0x0007 data fields */
203 static int hf_dplay_type_07_dpid
;
204 static int hf_dplay_type_07_sspi_offset
;
205 static int hf_dplay_type_07_capi_offset
;
206 static int hf_dplay_type_07_hresult
;
207 static int hf_dplay_type_07_sspi
;
208 static int hf_dplay_type_07_capi
;
210 /* Data fields for message types 0x08, 0x09, 0x0b, 0x0c, 0x0d, 0x0e */
211 static int hf_dplay_multi_id_to
;
212 static int hf_dplay_multi_player_id
;
213 static int hf_dplay_multi_group_id
;
214 static int hf_dplay_multi_create_offset
;
215 static int hf_dplay_multi_password_offset
;
216 static int hf_dplay_multi_password
;
218 /* Message Type 0x000f data fields */
219 static int hf_dplay_type_0f_id_to
;
220 static int hf_dplay_type_0f_id
;
221 static int hf_dplay_type_0f_data_size
;
222 static int hf_dplay_type_0f_data_offset
;
223 static int hf_dplay_type_0f_data
;
225 /* Message Type 0x0013 data fields */
226 static int hf_dplay_type_13_id_to
;
227 static int hf_dplay_type_13_player_id
;
228 static int hf_dplay_type_13_group_id
;
229 static int hf_dplay_type_13_create_offset
;
230 static int hf_dplay_type_13_password_offset
;
231 static int hf_dplay_type_13_password
;
232 static int hf_dplay_type_13_tick_count
;
234 /* Message Type 0x0015 data fields */
235 static int hf_dplay_message_guid
;
236 static int hf_dplay_type_15_packet_idx
;
237 static int hf_dplay_type_15_data_size
;
238 static int hf_dplay_type_15_offset
;
239 static int hf_dplay_type_15_total_packets
;
240 static int hf_dplay_type_15_msg_size
;
241 static int hf_dplay_type_15_packet_offset
;
243 /* Message Type 0x0016 and 0x0017 data fields */
244 static int hf_dplay_ping_id_from
;
245 static int hf_dplay_ping_tick_count
;
247 /* Message Type 0x001a data fields */
248 static int hf_dplay_type_1a_id_to
;
249 static int hf_dplay_type_1a_sess_name_ofs
;
250 static int hf_dplay_type_1a_password_ofs
;
251 static int hf_dplay_type_1a_session_name
;
252 static int hf_dplay_type_1a_password
;
254 /* Message Type 0x0029 data fields */
255 static int hf_dplay_type_29_player_count
;
256 static int hf_dplay_type_29_group_count
;
257 static int hf_dplay_type_29_packed_offset
;
258 static int hf_dplay_type_29_shortcut_count
;
259 static int hf_dplay_type_29_description_offset
;
260 static int hf_dplay_type_29_name_offset
;
261 static int hf_dplay_type_29_password_offset
;
262 static int hf_dplay_type_29_game_name
;
263 static int hf_dplay_type_29_password
;
265 /* Message Type 0x002f data fields */
266 static int hf_dplay_type_2f_dpid
;
269 static int ett_dplay
;
270 static int ett_dplay_header
;
271 static int ett_dplay_sockaddr
;
272 static int ett_dplay_data
;
273 static int ett_dplay_enc_packet
;
274 static int ett_dplay_flags
;
275 static int ett_dplay_sess_desc_flags
;
276 static int ett_dplay_pp_flags
;
277 static int ett_dplay_spp_flags
;
278 static int ett_dplay_spp_info_mask
;
279 static int ett_dplay_type02_flags
;
280 static int ett_dplay_type05_flags
;
281 static int ett_dplay_type29_spp
;
283 static const value_string dplay_command_val
[] = {
284 { 0x0001, "Enum Sessions Reply" },
285 { 0x0002, "Enum Sessions" },
286 { 0x0003, "Enum Players Reply" },
287 { 0x0004, "Enum Players" },
288 { 0x0005, "Request Player ID" },
289 { 0x0006, "Request Group ID" },
290 { 0x0007, "Request Player Reply" },
291 { 0x0008, "Create Player" },
292 { 0x0009, "Create Group" },
293 { 0x000a, "Player Message" },
294 { 0x000b, "Delete Player" },
295 { 0x000c, "Delete Group" },
296 { 0x000d, "Add Player To Group" },
297 { 0x000e, "Delete Player From Group" },
298 { 0x000f, "Player Data Changed" },
299 { 0x0010, "Player Name Changed" },
300 { 0x0011, "Group Data Changed" },
301 { 0x0012, "Group Name Changed" },
302 { 0x0013, "Add Forward Request" },
303 /* There is no command 0x0014 */
304 { 0x0015, "Packet" },
307 { 0x0018, "You Are Dead" },
308 { 0x0019, "Player Wrapper" },
309 { 0x001a, "Session Desc Changed" },
310 { 0x001c, "Challenge" },
311 { 0x001d, "Access Granted" },
312 { 0x001e, "Logon Denied" },
313 { 0x001f, "Auth Error" },
314 { 0x0020, "Negotiate" },
315 { 0x0021, "Challenge Response" },
317 /* There is no command 0x0023 */
318 { 0x0024, "Add Forward Reply" },
319 { 0x0025, "Ask For Multicast" },
320 { 0x0026, "Ask For Multicast Guaranteed" },
321 { 0x0027, "Add Shortcut To Group" },
322 { 0x0028, "Delete Group From Group" },
323 { 0x0029, "Super Enum Players Reply" },
324 /* There is no command 0x002a */
325 { 0x002b, "Key Exchange" },
326 { 0x002c, "Key Exchange Reply" },
328 { 0x002e, "Add Forward" },
329 { 0x002f, "Add Forward ACK" },
330 { 0x0030, "Packet2 Data" },
331 { 0x0031, "Packet2 ACK" },
332 /* No commands 0x0032, 0x0033, 0x0034 */
333 { 0x0035, "I Am Nameserver" },
335 { 0x0037, "Multicast Delivery" },
336 { 0x0038, "Create Players Verify"},
340 static const value_string dplay_af_val
[] = {
341 { WINSOCK_AF_INET
, "AF_INET" },
342 { WINSOCK_AF_IPX
, "AF_IPX" },
346 static const value_string dplay_proto_dialect_val
[] = {
347 { 0x0009, "dplay 6" },
348 { 0x000a, "dplay 6.1" },
349 { 0x000b, "dplay 6.1a" },
350 { 0x000c, "dplay 7.1" },
351 { 0x000d, "dplay 8" },
352 { 0x000e, "dplay 9"},
356 static const value_string dplay_token_val
[] = {
357 { 0xfab, "Remote Message" },
358 { 0xcab, "Forwarded Message" },
359 { 0xbab, "Server Message" },
363 static const value_string dplay_spp_length_val
[] = {
364 { 0x0, "Not present" },
366 { 0x2, "Two bytes" },
367 { 0x3, "Four bytes" },
371 static const value_string dplay_enc_alg_val
[] = {
372 { 0x0000, "Default" },
381 static const value_string yes_no_val
[] = {
388 /* borrowed from epan/dissectors/packets-smb-common.c */
389 static int display_unicode_string(proto_tree
*tree
, int hf_index
, tvbuff_t
*tvb
, int offset
)
394 /* display a unicode string from the tree and return new offset */
396 str
= tvb_get_stringz_enc(wmem_packet_scope(), tvb
, offset
, &len
, ENC_UTF_16
|ENC_LITTLE_ENDIAN
);
397 proto_tree_add_string(tree
, hf_index
, tvb
, offset
, len
, str
);
402 static int dissect_sockaddr_in(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
)
406 sa_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, 16, ett_dplay_sockaddr
, NULL
,
407 "DirectPlay sockaddr_in structure");
408 proto_tree_add_item(sa_tree
, hf_dplay_saddr_af
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
); offset
+= 2;
409 proto_tree_add_item(sa_tree
, hf_dplay_saddr_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
); offset
+= 2;
410 proto_tree_add_item(sa_tree
, hf_dplay_saddr_ip
, tvb
, offset
, 4, ENC_BIG_ENDIAN
); offset
+= 4;
411 proto_tree_add_item(sa_tree
, hf_dplay_saddr_padding
, tvb
, offset
, 8, ENC_NA
); offset
+= 8;
415 static int dissect_session_desc(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
)
417 static int * const flags
[] = {
418 &hf_dplay_flags_no_sess_desc_changes
,
419 &hf_dplay_flags_acqire_voice
,
420 &hf_dplay_flags_optimize_latency
,
421 &hf_dplay_flags_preserve_order
,
422 &hf_dplay_flags_reliable
,
423 &hf_dplay_flags_server_player_only
,
424 &hf_dplay_flags_route
,
425 &hf_dplay_flags_password_req
,
426 &hf_dplay_flags_private_session
,
427 &hf_dplay_flags_use_auth
,
428 &hf_dplay_flags_no_player_updates
,
429 &hf_dplay_flags_use_ping
,
430 &hf_dplay_flags_can_join
,
431 &hf_dplay_flags_ignored
,
432 &hf_dplay_flags_short_player_msg
,
433 &hf_dplay_flags_migrate_host
,
434 &hf_dplay_flags_0002
,
435 &hf_dplay_flags_no_create_players
,
439 proto_tree_add_item(tree
, hf_dplay_sess_desc_length
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
440 proto_tree_add_bitmask(tree
, tvb
, offset
, hf_dplay_sess_desc_flags
, ett_dplay_sess_desc_flags
, flags
, ENC_LITTLE_ENDIAN
); offset
+= 4;
442 proto_tree_add_item(tree
, hf_dplay_instance_guid
, tvb
, offset
, 16, ENC_BIG_ENDIAN
); offset
+= 16;
443 proto_tree_add_item(tree
, hf_dplay_game_guid
, tvb
, offset
, 16, ENC_BIG_ENDIAN
); offset
+= 16;
444 proto_tree_add_item(tree
, hf_dplay_max_players
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
445 proto_tree_add_item(tree
, hf_dplay_curr_players
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
446 proto_tree_add_item(tree
, hf_dplay_sess_name_ptr
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
447 proto_tree_add_item(tree
, hf_dplay_passwd_ptr
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
448 proto_tree_add_item(tree
, hf_dplay_sess_desc_reserved_1
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
449 proto_tree_add_item(tree
, hf_dplay_sess_desc_reserved_2
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
450 proto_tree_add_item(tree
, hf_dplay_sess_desc_user_1
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
451 proto_tree_add_item(tree
, hf_dplay_sess_desc_user_2
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
452 proto_tree_add_item(tree
, hf_dplay_sess_desc_user_3
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
453 proto_tree_add_item(tree
, hf_dplay_sess_desc_user_4
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
458 static int dissect_packed_player(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
)
460 uint32_t sn_len
, ln_len
, sd_len
, pd_len
, num_players
, i
;
462 static int * const flags
[] = {
463 &hf_dplay_pp_flag_sending
,
464 &hf_dplay_pp_flag_in_group
,
465 &hf_dplay_pp_flag_nameserver
,
466 &hf_dplay_pp_flag_sysplayer
,
470 size
= tvb_get_letohl(tvb
, offset
);
471 proto_tree_add_item(tree
, hf_dplay_pp_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
473 proto_tree_add_bitmask(tree
, tvb
, offset
, hf_dplay_pp_flags
, ett_dplay_pp_flags
, flags
, ENC_LITTLE_ENDIAN
); offset
+= 4;
474 proto_tree_add_item(tree
, hf_dplay_pp_id
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
476 sn_len
= tvb_get_letohl(tvb
, offset
);
477 proto_tree_add_item(tree
, hf_dplay_pp_short_name_len
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
478 ln_len
= tvb_get_letohl(tvb
, offset
);
479 proto_tree_add_item(tree
, hf_dplay_pp_long_name_len
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
480 sd_len
= tvb_get_letohl(tvb
, offset
);
481 proto_tree_add_item(tree
, hf_dplay_pp_sp_data_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
482 pd_len
= tvb_get_letohl(tvb
, offset
);
483 proto_tree_add_item(tree
, hf_dplay_pp_player_data_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
484 num_players
= tvb_get_letohl(tvb
, offset
);
485 proto_tree_add_item(tree
, hf_dplay_pp_num_players
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
487 proto_tree_add_item(tree
, hf_dplay_pp_system_player
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
488 proto_tree_add_item(tree
, hf_dplay_pp_fixed_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
489 proto_tree_add_item(tree
, hf_dplay_pp_dialect
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
490 proto_tree_add_item(tree
, hf_dplay_pp_unknown_1
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
493 offset
= display_unicode_string(tree
, hf_dplay_pp_short_name
, tvb
, offset
);
496 offset
= display_unicode_string(tree
, hf_dplay_pp_long_name
, tvb
, offset
);
498 proto_tree_add_item(tree
, hf_dplay_pp_sp_data
, tvb
, offset
, sd_len
, ENC_NA
);
502 proto_tree_add_item(tree
, hf_dplay_pp_player_data
, tvb
, offset
, pd_len
, ENC_NA
);
506 for (i
=0; i
< num_players
; ++i
) {
507 proto_tree_add_item(tree
, hf_dplay_pp_player_id
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
510 /* Size seems to miss the unknown empty dword */
511 if (size
+ 4 > offset
) {
512 proto_tree_add_item(tree
, hf_dplay_pp_parent_id
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
518 static int spp_get_value(uint32_t length_type
, tvbuff_t
*tvb
, int offset
, uint32_t *value
)
524 switch (length_type
) {
527 *value
= tvb_get_uint8(tvb
, offset
);
531 *value
= tvb_get_letohs(tvb
, offset
);
535 *value
= tvb_get_letohl(tvb
, offset
);
542 static int dissect_dplay_super_packed_player(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
)
544 uint32_t flags
, is_sysplayer
, info_mask
;
545 uint32_t have_short_name
, have_long_name
, sp_length_type
, pd_length_type
;
546 uint32_t player_count_type
, have_parent_id
, shortcut_count_type
;
547 uint32_t player_data_length
, sp_data_length
, player_count
, shortcut_count
;
548 proto_item
*im_item
= NULL
;
549 proto_tree
*im_tree
= NULL
;
551 static int * const ssp_flags
[] = {
552 &hf_dplay_spp_flags_sending
,
553 &hf_dplay_spp_flags_in_group
,
554 &hf_dplay_spp_flags_nameserver
,
555 &hf_dplay_spp_flags_sysplayer
,
559 proto_tree_add_item(tree
, hf_dplay_spp_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
561 flags
= tvb_get_letohl(tvb
, offset
);
562 is_sysplayer
= flags
& 0x00000001;
563 proto_tree_add_bitmask(tree
, tvb
, offset
, hf_dplay_spp_flags
, ett_dplay_spp_flags
, ssp_flags
, ENC_LITTLE_ENDIAN
); offset
+= 4;
564 proto_tree_add_item(tree
, hf_dplay_spp_id
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
566 info_mask
= tvb_get_letohl(tvb
, offset
);
568 have_short_name
= info_mask
& 0x00000001;
569 have_long_name
= (info_mask
& 0x00000002) >> 1;
570 sp_length_type
= (info_mask
& 0x0000000c) >> 2;
571 pd_length_type
= (info_mask
& 0x00000030) >> 4;
572 player_count_type
= (info_mask
& 0x000000c0) >> 6;
573 have_parent_id
= (info_mask
& 0x00000100) >> 8;
574 shortcut_count_type
= (info_mask
& 0x00000600) >> 9;
576 im_item
= proto_tree_add_item(tree
, hf_dplay_spp_player_info_mask
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
578 im_tree
= proto_item_add_subtree(im_item
, ett_dplay_spp_info_mask
);
579 proto_tree_add_uint(im_tree
, hf_dplay_spp_have_short_name
, tvb
, offset
, 4, have_short_name
);
580 proto_tree_add_uint(im_tree
, hf_dplay_spp_have_long_name
, tvb
, offset
, 4, have_long_name
);
581 proto_tree_add_uint(im_tree
, hf_dplay_spp_sp_length_type
, tvb
, offset
, 4, sp_length_type
);
582 proto_tree_add_uint(im_tree
, hf_dplay_spp_pd_length_type
, tvb
, offset
, 4, pd_length_type
);
583 proto_tree_add_uint(im_tree
, hf_dplay_spp_player_count_type
, tvb
, offset
, 4, player_count_type
);
584 proto_tree_add_uint(im_tree
, hf_dplay_spp_have_parent_id
, tvb
, offset
, 4, have_parent_id
);
585 proto_tree_add_uint(im_tree
, hf_dplay_spp_shortcut_count_type
, tvb
, offset
, 4, shortcut_count_type
);
589 proto_tree_add_item(tree
, hf_dplay_spp_dialect
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
591 proto_tree_add_item(tree
, hf_dplay_spp_sys_player_id
, tvb
, offset
, 4, ENC_NA
);
595 if (have_short_name
) {
596 offset
= display_unicode_string(tree
, hf_dplay_spp_short_name
, tvb
, offset
);
599 if (have_long_name
) {
600 offset
= display_unicode_string(tree
, hf_dplay_spp_long_name
, tvb
, offset
);
603 if (pd_length_type
) {
604 len
= spp_get_value(pd_length_type
, tvb
, offset
, &player_data_length
);
605 proto_tree_add_item(tree
, hf_dplay_spp_player_data_length
, tvb
, offset
, len
, ENC_LITTLE_ENDIAN
);
607 proto_tree_add_item(tree
, hf_dplay_spp_player_data
, tvb
, offset
, player_data_length
, ENC_NA
);
608 offset
+= player_data_length
;
611 if (sp_length_type
) {
612 len
= spp_get_value(sp_length_type
, tvb
, offset
, &sp_data_length
);
613 proto_tree_add_item(tree
, hf_dplay_spp_sp_data_length
, tvb
, offset
, len
, ENC_LITTLE_ENDIAN
);
615 proto_tree_add_item(tree
, hf_dplay_spp_sp_data
, tvb
, offset
, sp_data_length
, ENC_NA
);
616 offset
+= sp_data_length
;
619 if (player_count_type
) {
622 len
= spp_get_value(player_count_type
, tvb
, offset
, &player_count
);
623 proto_tree_add_item(tree
, hf_dplay_spp_player_count
, tvb
, offset
, len
, ENC_LITTLE_ENDIAN
);
625 for (i
=0; i
< player_count
; ++i
) {
626 proto_tree_add_item(tree
, hf_dplay_spp_player_id
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
630 if (have_parent_id
) {
631 proto_tree_add_item(tree
, hf_dplay_spp_parent_id
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
634 if (shortcut_count_type
) {
637 len
= spp_get_value(shortcut_count_type
, tvb
, offset
, &shortcut_count
);
638 proto_tree_add_item(tree
, hf_dplay_spp_shortcut_count
, tvb
, offset
, len
, ENC_LITTLE_ENDIAN
);
640 for (i
=0; i
< shortcut_count
; ++i
) {
641 proto_tree_add_item(tree
, hf_dplay_spp_shortcut_id
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
648 static int dissect_security_desc(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
)
650 proto_tree_add_item(tree
, hf_dplay_sd_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
651 proto_tree_add_item(tree
, hf_dplay_sd_flags
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
652 proto_tree_add_item(tree
, hf_dplay_sd_sspi
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
653 proto_tree_add_item(tree
, hf_dplay_sd_capi
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
654 proto_tree_add_item(tree
, hf_dplay_sd_capi_type
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
655 proto_tree_add_item(tree
, hf_dplay_sd_enc_alg
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
659 static int dissect_dplay_header(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
)
661 uint32_t mixed
, size
, token
;
663 mixed
= tvb_get_letohl(tvb
, offset
);
664 size
= mixed
& 0x000FFFFF;
665 token
= (mixed
& 0xFFF00000) >> 20;
667 proto_tree_add_uint(tree
, hf_dplay_size
, tvb
, offset
, 4, size
);
668 proto_tree_add_uint(tree
, hf_dplay_token
, tvb
, offset
, 4, token
);
670 offset
= dissect_sockaddr_in(tree
, tvb
, offset
);
671 proto_tree_add_item(tree
, hf_dplay_play_str
, tvb
, offset
, 4, ENC_ASCII
); offset
+= 4;
672 proto_tree_add_item(tree
, hf_dplay_command
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
); offset
+= 2;
673 proto_tree_add_item(tree
, hf_dplay_proto_dialect
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
); offset
+= 2;
677 static int dissect_type01_message(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
)
679 uint32_t name_offset
;
681 offset
= dissect_session_desc(tree
, tvb
, offset
);
682 name_offset
= tvb_get_letohl(tvb
, offset
);
683 proto_tree_add_item(tree
, hf_dplay_type_01_name_offset
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
685 if (name_offset
!= 0) {
686 offset
= display_unicode_string(tree
, hf_dplay_type_01_game_name
, tvb
, offset
);
691 static int dissect_type02_message(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
)
693 uint32_t passwd_offset
;
694 static int * const flags
[] = {
695 &hf_enum_sess_flag_passwd
,
696 &hf_enum_sess_flag_all
,
697 &hf_enum_sess_flag_join
,
701 passwd_offset
= tvb_get_letohl(tvb
, offset
+ 16);
703 proto_tree_add_item(tree
, hf_dplay_type_02_game_guid
, tvb
, offset
, 16, ENC_BIG_ENDIAN
); offset
+= 16;
704 proto_tree_add_item(tree
, hf_dplay_type_02_password_offset
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
705 proto_tree_add_bitmask(tree
, tvb
, offset
, hf_dplay_type_02_flags
, ett_dplay_type02_flags
, flags
, ENC_LITTLE_ENDIAN
); offset
+= 4;
707 if (passwd_offset
!= 0) {
708 offset
= display_unicode_string(tree
, hf_dplay_type_02_password
, tvb
, offset
);
713 static int dissect_type05_message(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
)
715 static int * const flags
[] = {
716 &hf_dplay_type_05_secure
,
717 &hf_dplay_type_05_unknown
,
718 &hf_dplay_type_05_local
,
719 &hf_dplay_type_05_name_server
,
720 &hf_dplay_type_05_system_player
,
724 proto_tree_add_bitmask(tree
, tvb
, offset
, hf_dplay_type_05_flags
, ett_dplay_type05_flags
, flags
, ENC_LITTLE_ENDIAN
);
729 static int dissect_type07_message(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
)
731 uint32_t sspi_offset
, capi_offset
;
733 proto_tree_add_item(tree
, hf_dplay_type_07_dpid
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
734 offset
= dissect_security_desc(tree
, tvb
, offset
);
736 sspi_offset
= tvb_get_letohl(tvb
, offset
);
737 proto_tree_add_item(tree
, hf_dplay_type_07_sspi_offset
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
739 capi_offset
= tvb_get_letohl(tvb
, offset
);
740 proto_tree_add_item(tree
, hf_dplay_type_07_capi_offset
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
742 proto_tree_add_item(tree
, hf_dplay_type_07_hresult
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
745 offset
= display_unicode_string(tree
, hf_dplay_type_07_sspi
, tvb
, offset
);
749 offset
= display_unicode_string(tree
, hf_dplay_type_07_capi
, tvb
, offset
);
754 static int dissect_player_message(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
)
758 proto_tree_add_item(tree
, hf_dplay_multi_id_to
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
759 proto_tree_add_item(tree
, hf_dplay_multi_player_id
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
760 proto_tree_add_item(tree
, hf_dplay_multi_group_id
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
761 pp_ofs
= tvb_get_letohl(tvb
, offset
);
762 proto_tree_add_item(tree
, hf_dplay_multi_create_offset
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
763 proto_tree_add_item(tree
, hf_dplay_multi_password_offset
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
765 offset
= dissect_packed_player(tree
, tvb
, offset
);
766 if (tvb_bytes_exist(tvb
, offset
, 2))
767 offset
= display_unicode_string(tree
, hf_dplay_multi_password
, tvb
, offset
);
771 static int dissect_type0f_message(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
)
775 proto_tree_add_item(tree
, hf_dplay_type_0f_id_to
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
776 proto_tree_add_item(tree
, hf_dplay_type_0f_id
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
777 data_size
= tvb_get_letohl(tvb
, offset
);
778 proto_tree_add_item(tree
, hf_dplay_type_0f_data_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
779 proto_tree_add_item(tree
, hf_dplay_type_0f_data_offset
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
780 proto_tree_add_item(tree
, hf_dplay_type_0f_data
, tvb
, offset
, data_size
, ENC_NA
);
786 static int dissect_type13_message(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
)
788 uint32_t pp_ofs
, pw_ofs
;
790 proto_tree_add_item(tree
, hf_dplay_type_13_id_to
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
791 proto_tree_add_item(tree
, hf_dplay_type_13_player_id
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
792 proto_tree_add_item(tree
, hf_dplay_type_13_group_id
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
793 pp_ofs
= tvb_get_letohl(tvb
, offset
);
794 proto_tree_add_item(tree
, hf_dplay_type_13_create_offset
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
795 pw_ofs
= tvb_get_letohl(tvb
, offset
);
796 proto_tree_add_item(tree
, hf_dplay_type_13_password_offset
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
798 offset
= dissect_packed_player(tree
, tvb
, offset
);
800 offset
= display_unicode_string(tree
, hf_dplay_type_13_password
, tvb
, offset
);
801 proto_tree_add_item(tree
, hf_dplay_type_13_tick_count
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
806 static int dissect_type15_message(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
)
808 uint16_t second_message_type
;
809 proto_tree
*enc_tree
;
810 second_message_type
= tvb_get_letohs(tvb
, 72);
812 proto_tree_add_item(tree
, hf_dplay_message_guid
, tvb
, offset
, 16, ENC_BIG_ENDIAN
); offset
+= 16;
813 proto_tree_add_item(tree
, hf_dplay_type_15_packet_idx
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
814 proto_tree_add_item(tree
, hf_dplay_type_15_data_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
815 proto_tree_add_item(tree
, hf_dplay_type_15_offset
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
816 proto_tree_add_item(tree
, hf_dplay_type_15_total_packets
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
817 proto_tree_add_item(tree
, hf_dplay_type_15_msg_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
818 proto_tree_add_item(tree
, hf_dplay_type_15_packet_offset
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
820 enc_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, -1, ett_dplay_enc_packet
, NULL
, "DirectPlay encapsulated packet");
822 proto_tree_add_item(enc_tree
, hf_dplay_play_str_2
, tvb
, offset
, 4, ENC_ASCII
); offset
+= 4;
823 proto_tree_add_item(enc_tree
, hf_dplay_command_2
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
); offset
+= 2;
824 proto_tree_add_item(enc_tree
, hf_dplay_proto_dialect_2
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
); offset
+= 2;
826 switch(second_message_type
)
829 offset
= dissect_type05_message(enc_tree
, tvb
, offset
);
832 offset
= dissect_type05_message(enc_tree
, tvb
, offset
);
841 offset
= dissect_player_message(enc_tree
, tvb
, offset
);
844 offset
= dissect_type13_message(enc_tree
, tvb
, offset
);
847 offset
= dissect_type1a_message(enc_tree
, tvb
, offset
);
854 static int dissect_ping_message(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
)
856 proto_tree_add_item(tree
, hf_dplay_ping_id_from
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
857 proto_tree_add_item(tree
, hf_dplay_ping_tick_count
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
862 static int dissect_type1a_message(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
)
864 uint32_t sn_ofs
, pw_ofs
;
866 proto_tree_add_item(tree
, hf_dplay_type_1a_id_to
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
867 sn_ofs
= tvb_get_letohl(tvb
, offset
);
868 proto_tree_add_item(tree
, hf_dplay_type_1a_sess_name_ofs
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
869 pw_ofs
= tvb_get_letohl(tvb
, offset
);
870 proto_tree_add_item(tree
, hf_dplay_type_1a_password_ofs
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
871 offset
= dissect_session_desc(tree
, tvb
, offset
);
874 offset
= display_unicode_string(tree
, hf_dplay_type_1a_session_name
, tvb
, offset
);
878 offset
= display_unicode_string(tree
, hf_dplay_type_1a_password
, tvb
, offset
);
884 static int dissect_type29_message(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
)
886 uint32_t password_offset
= tvb_get_letohl(tvb
, offset
+ 24);
887 int player_count
, group_count
, shortcut_count
;
890 player_count
= tvb_get_letohl(tvb
, offset
);
891 proto_tree_add_item(tree
, hf_dplay_type_29_player_count
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
892 group_count
= tvb_get_letohl(tvb
, offset
);
893 proto_tree_add_item(tree
, hf_dplay_type_29_group_count
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
894 proto_tree_add_item(tree
, hf_dplay_type_29_packed_offset
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
895 shortcut_count
= tvb_get_letohl(tvb
, offset
);
896 proto_tree_add_item(tree
, hf_dplay_type_29_shortcut_count
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
897 proto_tree_add_item(tree
, hf_dplay_type_29_description_offset
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
898 proto_tree_add_item(tree
, hf_dplay_type_29_name_offset
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
899 proto_tree_add_item(tree
, hf_dplay_type_29_password_offset
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
); offset
+= 4;
900 offset
= dissect_session_desc(tree
, tvb
, offset
);
901 offset
= display_unicode_string(tree
, hf_dplay_type_29_game_name
, tvb
, offset
);
903 if (password_offset
!= 0) {
904 offset
= display_unicode_string(tree
, hf_dplay_type_29_password
, tvb
, offset
);
907 for (i
=0; i
< player_count
; ++i
) {
908 proto_tree
*spp_tree
;
910 spp_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, 0, ett_dplay_type29_spp
, NULL
, "Player %d", i
);
911 offset
= dissect_dplay_super_packed_player(spp_tree
, tvb
, offset
);
914 for (i
=0; i
< group_count
; ++i
) {
915 proto_tree
*spp_tree
;
917 spp_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, 0, ett_dplay_type29_spp
, NULL
, "Group %d", i
);
918 offset
= dissect_dplay_super_packed_player(spp_tree
, tvb
, offset
);
921 for (i
=0; i
< shortcut_count
; ++i
) {
922 proto_tree
*spp_tree
;
924 spp_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, 0, ett_dplay_type29_spp
, NULL
, "Shortcut %d", i
);
925 offset
= dissect_dplay_super_packed_player(spp_tree
, tvb
, offset
);
931 static int dissect_type2f_message(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
)
933 proto_tree_add_item(tree
, hf_dplay_type_2f_dpid
, tvb
, offset
, 4, ENC_NA
); offset
+= 4;
937 static void dissect_dplay(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
939 uint16_t message_type
;
940 uint16_t second_message_type
= UINT16_MAX
;
941 uint16_t proto_version
;
943 uint8_t play_id
[] = {'p','l','a','y'};
945 dplay_id
= tvb_get_letohl(tvb
, 20);
946 message_type
= tvb_get_letohs(tvb
, 24);
947 proto_version
= tvb_get_letohs(tvb
, 26);
949 if(memcmp(play_id
, (uint8_t *)&dplay_id
, 4) != 0)
951 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "DPLAY");
952 col_set_str(pinfo
->cinfo
,COL_INFO
, "DPlay data packet");
956 if(message_type
== 0x0015)
958 second_message_type
= tvb_get_letohs(tvb
, 72);
961 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "DPLAY");
963 if(message_type
== 0x0015)
964 col_add_fstr(pinfo
->cinfo
,COL_INFO
, "%s: %s, holding a %s",
965 val_to_str(proto_version
, dplay_proto_dialect_val
, "Unknown (0x%04x)"),
966 val_to_str(message_type
, dplay_command_val
, "Unknown (0x%04x)"),
967 val_to_str(second_message_type
, dplay_command_val
, "Unknown (0x%04x)"));
969 col_add_fstr(pinfo
->cinfo
,COL_INFO
, "%s: %s",
970 val_to_str(proto_version
, dplay_proto_dialect_val
, "Unknown (0x%04x)"),
971 val_to_str(message_type
, dplay_command_val
, "Unknown (0x%04x)"));
975 proto_item
*dplay_item
;
976 proto_tree
*dplay_tree
;
977 proto_tree
*dplay_header
;
978 proto_tree
*dplay_data
;
981 dplay_item
= proto_tree_add_item(tree
, proto_dplay
, tvb
, 0, -1, ENC_NA
);
982 dplay_tree
= proto_item_add_subtree(dplay_item
, ett_dplay
);
983 dplay_header
= proto_tree_add_subtree(dplay_tree
, tvb
, offset
, DPLAY_HEADER_OFFSET
, ett_dplay_header
, NULL
, "DirectPlay header");
985 offset
= dissect_dplay_header(dplay_header
, tvb
, offset
);
987 /* Special handling for empty type 0x0004 packets */
988 if(message_type
== 0x0004)
991 dplay_data
= proto_tree_add_subtree(dplay_tree
, tvb
, offset
, -1, ett_dplay_data
, NULL
, "DirectPlay data");
996 dissect_type01_message(dplay_data
, tvb
, offset
);
999 dissect_type02_message(dplay_data
, tvb
, offset
);
1002 dissect_type05_message(dplay_data
, tvb
, offset
);
1005 dissect_type07_message(dplay_data
, tvb
, offset
);
1009 /* type 0a doesn't have a dplay header and is not handled here */
1016 dissect_player_message(dplay_data
, tvb
, offset
);
1019 dissect_type0f_message(dplay_data
, tvb
, offset
);
1022 dissect_type13_message(dplay_data
, tvb
, offset
);
1025 dissect_type15_message(dplay_data
, tvb
, offset
);
1029 dissect_ping_message(dplay_data
, tvb
, offset
);
1032 dissect_type1a_message(dplay_data
, tvb
, offset
);
1035 dissect_type29_message(dplay_data
, tvb
, offset
);
1038 dissect_type2f_message(dplay_data
, tvb
, offset
);
1045 static void dissect_dplay_player_msg(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
1047 uint32_t mixed
, size
, token
;
1049 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "DPLAY");
1050 col_set_str(pinfo
->cinfo
,COL_INFO
, "DPlay player to player message");
1054 proto_item
*dplay_item
;
1055 proto_tree
*dplay_tree
;
1056 proto_tree
*data_tree
;
1059 dplay_item
= proto_tree_add_item(tree
, proto_dplay
, tvb
, offset
, -1, ENC_NA
);
1060 dplay_tree
= proto_item_add_subtree(dplay_item
, ett_dplay
);
1061 data_tree
= proto_tree_add_subtree(dplay_tree
, tvb
, offset
, -1, ett_dplay_data
, NULL
, "Message content");
1062 mixed
= tvb_get_letohl(tvb
, offset
);
1063 size
= mixed
& 0x000FFFFF;
1064 token
= (mixed
& 0xFFF00000) >> 20;
1066 proto_tree_add_uint(data_tree
, hf_dplay_size
, tvb
, offset
, 4, size
);
1067 proto_tree_add_uint(data_tree
, hf_dplay_token
, tvb
, offset
, 4, token
);
1069 offset
= dissect_sockaddr_in(data_tree
, tvb
, offset
);
1070 /* Now there's two dplay IDs iff the session desc does not have the
1071 * "short player message" flag set */
1072 proto_tree_add_item(data_tree
, hf_dplay_player_msg
, tvb
, offset
, -1, ENC_NA
);
1076 static bool heur_dissect_dplay(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
1078 uint32_t dplay_id
, token
;
1080 if(tvb_captured_length(tvb
) < 25)
1083 /* The string play = 0x706c6179 */
1084 dplay_id
= tvb_get_ntohl(tvb
, 20);
1085 if( dplay_id
== 0x706c6179) {
1086 dissect_dplay(tvb
, pinfo
, tree
);
1091 /* There is a player to player message that does not contain "play" */
1092 token
= tvb_get_letohl(tvb
, 0);
1093 token
= (token
& 0xfff00000) >> 20;
1094 if (token
== 0xfab || token
== 0xbab || token
== 0xcab) {
1095 /* Check the s_addr_in structure */
1096 if (tvb_get_letohs(tvb
, 4) == WINSOCK_AF_INET
) {
1098 for (offset
= 12; offset
<= 20; offset
++)
1099 if (tvb_get_uint8(tvb
, offset
) != 0)
1102 dissect_dplay_player_msg(tvb
, pinfo
, tree
);
1110 void proto_register_dplay(void)
1112 static hf_register_info hf
[] = {
1113 /* Common data fields */
1115 { "DirectPlay package size", "dplay.size", FT_UINT32
, BASE_DEC
,
1116 NULL
, 0x0, NULL
, HFILL
}},
1118 { "DirectPlay token", "dplay.token", FT_UINT32
, BASE_HEX
,
1119 VALS(dplay_token_val
), 0x0, NULL
, HFILL
}},
1120 { &hf_dplay_saddr_af
,
1121 { "DirectPlay s_addr_in address family", "dplay.saddr.af", FT_UINT16
, BASE_HEX
,
1122 VALS(dplay_af_val
), 0x0, NULL
, HFILL
}},
1123 { &hf_dplay_saddr_port
,
1124 { "DirectPlay s_addr_in port", "dplay.saddr.port", FT_UINT16
, BASE_DEC
,
1125 NULL
, 0x0, NULL
, HFILL
}},
1126 { &hf_dplay_saddr_ip
,
1127 { "DirectPlay s_addr_in ip address", "dplay.saddr.ip", FT_IPv4
, BASE_NONE
,
1128 NULL
, 0x0, NULL
, HFILL
}},
1129 { &hf_dplay_saddr_padding
,
1130 { "DirectPlay s_addr_in null padding", "dplay.saddr.padding", FT_BYTES
, BASE_NONE
,
1131 NULL
, 0x0, NULL
, HFILL
}},
1132 { &hf_dplay_play_str
,
1133 { "DirectPlay action string", "dplay.dplay_str", FT_STRING
, BASE_NONE
,
1134 NULL
, 0x0, NULL
, HFILL
}},
1135 { &hf_dplay_command
,
1136 { "DirectPlay command", "dplay.command", FT_UINT16
, BASE_HEX
,
1137 VALS(dplay_command_val
), 0x0, NULL
, HFILL
}},
1138 { &hf_dplay_proto_dialect
,
1139 { "DirectPlay dialect version", "dplay.dialect.version", FT_UINT16
, BASE_HEX
,
1140 VALS(dplay_proto_dialect_val
), 0x0, NULL
, HFILL
}},
1141 { &hf_dplay_play_str_2
,
1142 { "DirectPlay second action string", "dplay.dplay_str_2", FT_STRING
, BASE_NONE
,
1143 NULL
, 0x0, NULL
, HFILL
}},
1144 { &hf_dplay_command_2
,
1145 { "DirectPlay second command", "dplay.command_2", FT_UINT16
, BASE_HEX
,
1146 VALS(dplay_command_val
), 0x0, NULL
, HFILL
}},
1147 { &hf_dplay_proto_dialect_2
,
1148 { "DirectPlay second dialect version", "dplay.dialect.version_2", FT_UINT16
, BASE_HEX
,
1149 VALS(dplay_proto_dialect_val
), 0x0, NULL
, HFILL
}},
1150 { &hf_dplay_player_msg
,
1151 { "DirectPlay Player to Player message", "dplay.player_msg", FT_BYTES
, BASE_NONE
,
1152 NULL
, 0x0, NULL
, HFILL
}},
1154 /* Session Desc structure fields */
1155 { &hf_dplay_sess_desc_flags
,
1156 { "DirectPlay session desc flags", "dplay.flags", FT_UINT32
, BASE_HEX
,
1157 NULL
, 0x0, NULL
, HFILL
}},
1158 { &hf_dplay_flags_no_create_players
,
1159 { "no create players flag", "dplay.flags.no_create_players", FT_BOOLEAN
, 32,
1160 TFS(&tfs_present_absent
), DPLAY_FLAG_NO_CREATE_PLAYERS
, NULL
, HFILL
}},
1161 { &hf_dplay_flags_0002
,
1162 { "unused", "dplay.flags.unused", FT_BOOLEAN
, 32,
1163 TFS(&tfs_present_absent
), DPLAY_FLAG_0002
, NULL
, HFILL
}},
1164 { &hf_dplay_flags_migrate_host
,
1165 { "migrate host flag", "dplay.flags.migrate_host", FT_BOOLEAN
, 32,
1166 TFS(&tfs_present_absent
), DPLAY_FLAG_MIGRATE_HOST
, NULL
, HFILL
}},
1167 { &hf_dplay_flags_short_player_msg
,
1168 { "short player message", "dplay.flags.short_player_msg", FT_BOOLEAN
, 32,
1169 TFS(&tfs_present_absent
), DPLAY_FLAG_SHORT_PLAYER_MSG
, NULL
, HFILL
}},
1170 { &hf_dplay_flags_ignored
,
1171 { "ignored", "dplay.ignored", FT_BOOLEAN
, 32,
1172 TFS(&tfs_present_absent
), DPLAY_FLAG_IGNORED
, NULL
, HFILL
}},
1173 { &hf_dplay_flags_can_join
,
1174 { "can join", "dplay.flags.can_join", FT_BOOLEAN
, 32,
1175 TFS(&tfs_present_absent
), DPLAY_FLAG_CAN_JOIN
, NULL
, HFILL
}},
1176 { &hf_dplay_flags_use_ping
,
1177 { "use ping", "dplay.flags.use_ping", FT_BOOLEAN
, 32,
1178 TFS(&tfs_present_absent
), DPLAY_FLAG_USE_PING
, NULL
, HFILL
}},
1179 { &hf_dplay_flags_no_player_updates
,
1180 { "no player updates", "dplay.flags.no_player_updates", FT_BOOLEAN
, 32,
1181 TFS(&tfs_present_absent
), DPLAY_FLAG_NO_P_UPD
, NULL
, HFILL
}},
1182 { &hf_dplay_flags_use_auth
,
1183 { "use authentication", "dplay.flags.use_auth", FT_BOOLEAN
, 32,
1184 TFS(&tfs_present_absent
), DPLAY_FLAG_USE_AUTH
, NULL
, HFILL
}},
1185 { &hf_dplay_flags_private_session
,
1186 { "private session", "dplay.flags.priv_sess", FT_BOOLEAN
, 32,
1187 TFS(&tfs_present_absent
), DPLAY_FLAG_PRIV_SESS
, NULL
, HFILL
}},
1188 { &hf_dplay_flags_password_req
,
1189 { "password required", "dplay.flags.pass_req", FT_BOOLEAN
, 32,
1190 TFS(&tfs_present_absent
), DPLAY_FLAG_PASS_REQ
, NULL
, HFILL
}},
1191 { &hf_dplay_flags_route
,
1192 { "route via game host", "dplay.flags.route", FT_BOOLEAN
, 32,
1193 TFS(&tfs_present_absent
), DPLAY_FLAG_ROUTE
, NULL
, HFILL
}},
1194 { &hf_dplay_flags_server_player_only
,
1195 { "get server player only", "dplay.flags.srv_p_only", FT_BOOLEAN
, 32,
1196 TFS(&tfs_present_absent
), DPLAY_FLAG_SRV_ONLY
, NULL
, HFILL
}},
1197 { &hf_dplay_flags_reliable
,
1198 { "use reliable protocol", "dplay.flags.reliable", FT_BOOLEAN
, 32,
1199 TFS(&tfs_present_absent
), DPLAY_FLAG_RELIABLE
, NULL
, HFILL
}},
1200 { &hf_dplay_flags_preserve_order
,
1201 { "preserve order", "dplay.flags.order", FT_BOOLEAN
, 32,
1202 TFS(&tfs_present_absent
), DPLAY_FLAG_ORDER
, NULL
, HFILL
}},
1203 { &hf_dplay_flags_optimize_latency
,
1204 { "optimize for latency", "dplay.flags.opt_latency", FT_BOOLEAN
, 32,
1205 TFS(&tfs_present_absent
), DPLAY_FLAG_OPT_LAT
, "Opt Latency", HFILL
}},
1206 { &hf_dplay_flags_acqire_voice
,
1207 { "acquire voice", "dplay.flags.acq_voice", FT_BOOLEAN
, 32,
1208 TFS(&tfs_present_absent
), DPLAY_FLAG_ACQ_VOICE
, "Acq Voice", HFILL
}},
1209 { &hf_dplay_flags_no_sess_desc_changes
,
1210 { "no session desc changes", "dplay.flags.no_sess_desc", FT_BOOLEAN
, 32,
1211 TFS(&tfs_present_absent
), DPLAY_FLAG_NO_SESS_DESC_CHANGES
, "No Sess Desc Changes", HFILL
}},
1212 { &hf_dplay_instance_guid
,
1213 { "DirectPlay instance guid", "dplay.instance.guid", FT_GUID
, BASE_NONE
,
1214 NULL
, 0x0, NULL
, HFILL
}},
1215 { &hf_dplay_game_guid
,
1216 { "DirectPlay game GUID", "dplay.game.guid", FT_GUID
, BASE_NONE
,
1217 NULL
, 0x0, NULL
, HFILL
}},
1218 { &hf_dplay_sess_desc_length
,
1219 { "DirectPlay session desc length", "dplay.sess_desc.length", FT_UINT32
, BASE_DEC
,
1220 NULL
, 0x0, NULL
, HFILL
}},
1221 { &hf_dplay_max_players
,
1222 { "DirectPlay max players", "dplay.sess_desc.max_players", FT_UINT32
, BASE_DEC
,
1223 NULL
, 0x0, NULL
, HFILL
}},
1224 { &hf_dplay_curr_players
,
1225 { "DirectPlay current players", "dplay.sess_desc.curr_players", FT_UINT32
, BASE_DEC
,
1226 NULL
, 0x0, NULL
, HFILL
}},
1227 { &hf_dplay_sess_name_ptr
,
1228 { "Session description name pointer placeholder", "dplay.sess_desc.name_ptr", FT_BYTES
, BASE_NONE
,
1229 NULL
, 0x0, NULL
, HFILL
}},
1230 { &hf_dplay_passwd_ptr
,
1231 { "Session description password pointer placeholder", "dplay.sess_desc.pw_ptr", FT_BYTES
, BASE_NONE
,
1232 NULL
, 0x0, NULL
, HFILL
}},
1233 { &hf_dplay_sess_desc_reserved_1
,
1234 { "Session description reserved 1", "dplay.sess_desc.res_1", FT_BYTES
, BASE_NONE
,
1235 NULL
, 0x0, NULL
, HFILL
}},
1236 { &hf_dplay_sess_desc_reserved_2
,
1237 { "Session description reserved 2", "dplay.sess_desc.res_2", FT_BYTES
, BASE_NONE
,
1238 NULL
, 0x0, NULL
, HFILL
}},
1239 { &hf_dplay_sess_desc_user_1
,
1240 { "Session description user defined 1", "dplay.sess_desc.user_1", FT_BYTES
, BASE_NONE
,
1241 NULL
, 0x0, NULL
, HFILL
}},
1242 { &hf_dplay_sess_desc_user_2
,
1243 { "Session description user defined 2", "dplay.sess_desc.user_2", FT_BYTES
, BASE_NONE
,
1244 NULL
, 0x0, NULL
, HFILL
}},
1245 { &hf_dplay_sess_desc_user_3
,
1246 { "Session description user defined 3", "dplay.sess_desc.user_3", FT_BYTES
, BASE_NONE
,
1247 NULL
, 0x0, NULL
, HFILL
}},
1248 { &hf_dplay_sess_desc_user_4
,
1249 { "Session description user defined 4", "dplay.sess_desc.user_4", FT_BYTES
, BASE_NONE
,
1250 NULL
, 0x0, NULL
, HFILL
}},
1252 /* PackedPlayer structure fields */
1253 { &hf_dplay_pp_size
,
1254 { "PackedPlayer size", "dplay.pp.size", FT_UINT32
, BASE_DEC
,
1255 NULL
, 0x0, NULL
, HFILL
}},
1256 { &hf_dplay_pp_flags
,
1257 { "PackedPlayer flags", "dplay.pp.flags", FT_UINT32
, BASE_HEX
,
1258 NULL
, 0x0, NULL
, HFILL
}},
1259 { &hf_dplay_pp_flag_sysplayer
,
1260 { "is system player", "dplay.pp.flags.sysplayer", FT_BOOLEAN
, 32,
1261 TFS(&tfs_present_absent
), DPLAY_PP_FLAG_SYSPLAYER
, NULL
, HFILL
}},
1262 { &hf_dplay_pp_flag_nameserver
,
1263 { "is name server", "dplay.pp.flags.nameserver", FT_BOOLEAN
, 32,
1264 TFS(&tfs_present_absent
), DPLAY_PP_FLAG_NAMESERVER
, NULL
, HFILL
}},
1265 { &hf_dplay_pp_flag_in_group
,
1266 { "in group", "dplay.pp.flags.in_group", FT_BOOLEAN
, 32,
1267 TFS(&tfs_present_absent
), DPLAY_PP_FLAG_IN_GROUP
, NULL
, HFILL
}},
1268 { &hf_dplay_pp_flag_sending
,
1269 { "sending player on local machine", "dplay.pp.flags.sending", FT_BOOLEAN
, 32,
1270 TFS(&tfs_present_absent
), DPLAY_SPP_FLAG_SENDING
, NULL
, HFILL
}},
1272 { "PackedPlayer ID", "dplay.pp.id", FT_BYTES
, BASE_NONE
,
1273 NULL
, 0x0, NULL
, HFILL
}},
1274 { &hf_dplay_pp_short_name_len
,
1275 { "PackedPlayer short name length", "dplay.pp.short_name_len", FT_UINT32
, BASE_HEX
,
1276 NULL
, 0x0, NULL
, HFILL
}},
1277 { &hf_dplay_pp_long_name_len
,
1278 { "PackedPlayer long name length", "dplay.pp.long_name_len", FT_UINT32
, BASE_HEX
,
1279 NULL
, 0x0, NULL
, HFILL
}},
1280 { &hf_dplay_pp_sp_data_size
,
1281 { "PackedPlayer service provider data size", "dplay.pp.sp_data_size", FT_UINT32
, BASE_HEX
,
1282 NULL
, 0x0, NULL
, HFILL
}},
1283 { &hf_dplay_pp_player_data_size
,
1284 { "PackedPlayer player data size", "dplay.pp.player_data_size", FT_UINT32
, BASE_HEX
,
1285 NULL
, 0x0, NULL
, HFILL
}},
1286 { &hf_dplay_pp_num_players
,
1287 { "PackedPlayer player count", "dplay.pp.player_count", FT_UINT32
, BASE_HEX
,
1288 NULL
, 0x0, NULL
, HFILL
}},
1289 { &hf_dplay_pp_system_player
,
1290 { "PackedPlayer system player ID", "dplay.pp.sysplayer_id", FT_BYTES
, BASE_NONE
,
1291 NULL
, 0x0, NULL
, HFILL
}},
1292 { &hf_dplay_pp_fixed_size
,
1293 { "PackedPlayer fixed size", "dplay.pp.fixed_size", FT_UINT32
, BASE_DEC
,
1294 NULL
, 0x0, NULL
, HFILL
}},
1295 { &hf_dplay_pp_dialect
,
1296 { "PackedPlayer dialect version", "dplay.pp.dialect", FT_UINT32
, BASE_HEX
,
1297 VALS(dplay_proto_dialect_val
), 0x0, NULL
, HFILL
}},
1298 { &hf_dplay_pp_unknown_1
,
1299 { "PackedPlayer unknown 1", "dplay.pp.unknown_1", FT_BYTES
, BASE_NONE
,
1300 NULL
, 0x0, NULL
, HFILL
}},
1301 { &hf_dplay_pp_short_name
,
1302 { "PackedPlayer short name", "dplay.pp.short_name", FT_STRING
, BASE_NONE
,
1303 NULL
, 0x0, NULL
, HFILL
}},
1304 { &hf_dplay_pp_long_name
,
1305 { "PackedPlayer long name", "dplay.pp.long_name", FT_STRING
, BASE_NONE
,
1306 NULL
, 0x0, NULL
, HFILL
}},
1307 { &hf_dplay_pp_player_data
,
1308 { "PackedPlayer player data", "dplay.pp.player_data", FT_BYTES
, BASE_NONE
,
1309 NULL
, 0x0, NULL
, HFILL
}},
1310 { &hf_dplay_pp_sp_data
,
1311 { "PackedPlayer service provider data", "dplay.pp.sp_data", FT_BYTES
, BASE_NONE
,
1312 NULL
, 0x0, NULL
, HFILL
}},
1313 { &hf_dplay_pp_player_id
,
1314 { "PackedPlayer player ID", "dplay.pp.player_id", FT_BYTES
, BASE_NONE
,
1315 NULL
, 0x0, NULL
, HFILL
}},
1316 { &hf_dplay_pp_parent_id
,
1317 { "PackedPlayer parent ID", "dplay.pp.parent_id", FT_BYTES
, BASE_NONE
,
1318 NULL
, 0x0, NULL
, HFILL
}},
1320 /* SuperPackedPlayer structure fields */
1321 { &hf_dplay_spp_size
,
1322 { "SuperPackedPlayer size", "dplay.spp.size", FT_UINT32
, BASE_DEC
,
1323 NULL
, 0x0, NULL
, HFILL
}},
1324 { &hf_dplay_spp_flags
,
1325 { "SuperPackedPlayer flags", "dplay.spp.flags", FT_UINT32
, BASE_HEX
,
1326 NULL
, 0x0, NULL
, HFILL
}},
1327 { &hf_dplay_spp_flags_sysplayer
,
1328 { "is system player", "dplay.spp.flags.sysplayer", FT_BOOLEAN
, 32,
1329 TFS(&tfs_present_absent
), DPLAY_SPP_FLAG_SYSPLAYER
, NULL
, HFILL
}},
1330 { &hf_dplay_spp_flags_nameserver
,
1331 { "is name server", "dplay.spp.flags.nameserver", FT_BOOLEAN
, 32,
1332 TFS(&tfs_present_absent
), DPLAY_SPP_FLAG_NAMESERVER
, NULL
, HFILL
}},
1333 { &hf_dplay_spp_flags_in_group
,
1334 { "in group", "dplay.spp.flags.in_group", FT_BOOLEAN
, 32,
1335 TFS(&tfs_present_absent
), DPLAY_SPP_FLAG_IN_GROUP
, NULL
, HFILL
}},
1336 { &hf_dplay_spp_flags_sending
,
1337 { "sending player on local machine", "dplay.spp.flags.sending", FT_BOOLEAN
, 32,
1338 TFS(&tfs_present_absent
), DPLAY_SPP_FLAG_SENDING
, NULL
, HFILL
}},
1340 { "SuperPackedPlayer ID", "dplay.spp.id", FT_BYTES
, BASE_NONE
,
1341 NULL
, 0x0, NULL
, HFILL
}},
1342 { &hf_dplay_spp_player_info_mask
,
1343 { "SuperPackedPlayer player info mask", "dplay.spp.pim", FT_UINT32
, BASE_HEX
,
1344 NULL
, 0x0, NULL
, HFILL
}},
1345 { &hf_dplay_spp_have_short_name
,
1346 { "SuperPackedPlayer have short name", "dplay.spp.pim.short_name", FT_UINT32
, BASE_HEX
,
1347 VALS(yes_no_val
), 0x0, NULL
, HFILL
}},
1348 { &hf_dplay_spp_have_long_name
,
1349 { "SuperPackedPlayer have long name", "dplay.spp.pim.long_name", FT_UINT32
, BASE_HEX
,
1350 VALS(yes_no_val
), 0x0, NULL
, HFILL
}},
1351 { &hf_dplay_spp_sp_length_type
,
1352 { "SuperPackedPlayer service provider length info", "dplay.spp.pim.sp_length", FT_UINT32
, BASE_HEX
,
1353 VALS(dplay_spp_length_val
), 0x0, NULL
, HFILL
}},
1354 { &hf_dplay_spp_pd_length_type
,
1355 { "SuperPackedPlayer player data length info", "dplay.spp.pim.pd_length", FT_UINT32
, BASE_HEX
,
1356 VALS(dplay_spp_length_val
), 0x0, NULL
, HFILL
}},
1357 { &hf_dplay_spp_player_count_type
,
1358 { "SuperPackedPlayer player count info", "dplay.spp.pim.player_count", FT_UINT32
, BASE_HEX
,
1359 VALS(dplay_spp_length_val
), 0x0, NULL
, HFILL
}},
1360 { &hf_dplay_spp_have_parent_id
,
1361 { "SuperPackedPlayer have parent ID", "dplay.spp.pim.parent_id", FT_UINT32
, BASE_HEX
,
1362 VALS(yes_no_val
), 0x0, NULL
, HFILL
}},
1363 { &hf_dplay_spp_shortcut_count_type
,
1364 { "SuperPackedPlayer shortcut count info", "dplay.spp.pim.shortcut_count", FT_UINT32
, BASE_HEX
,
1365 VALS(dplay_spp_length_val
), 0x0, NULL
, HFILL
}},
1366 { &hf_dplay_spp_dialect
,
1367 { "SuperPackedPlayer dialect version", "dplay.spp.dialect", FT_UINT32
, BASE_HEX
,
1368 VALS(dplay_proto_dialect_val
), 0x0, NULL
, HFILL
}},
1369 { &hf_dplay_spp_sys_player_id
,
1370 { "SuperPackedPlayer system player ID", "dplay.spp.sysplayer_id", FT_BYTES
, BASE_NONE
,
1371 NULL
, 0x0, NULL
, HFILL
}},
1372 { &hf_dplay_spp_short_name
,
1373 { "SuperPackedPlayer short name", "dplay.spp.short_name", FT_STRING
, BASE_NONE
,
1374 NULL
, 0x0, NULL
, HFILL
}},
1375 { &hf_dplay_spp_long_name
,
1376 { "SuperPackedPlayer long name", "dplay.spp.long_name", FT_STRING
, BASE_NONE
,
1377 NULL
, 0x0, NULL
, HFILL
}},
1378 { &hf_dplay_spp_player_data_length
,
1379 { "SuperPackedPlayer player data length", "dplay.spp.pd_length", FT_UINT32
, BASE_HEX
,
1380 NULL
, 0x0, NULL
, HFILL
}},
1381 { &hf_dplay_spp_player_data
,
1382 { "SuperPackedPlayer player data", "dplay.spp.player_data", FT_BYTES
, BASE_NONE
,
1383 NULL
, 0x0, NULL
, HFILL
}},
1384 { &hf_dplay_spp_sp_data_length
,
1385 { "SuperPackedPlayer service provider data length", "dplay.spp.sp_data_length", FT_UINT32
, BASE_HEX
,
1386 NULL
, 0x0, NULL
, HFILL
}},
1387 { &hf_dplay_spp_sp_data
,
1388 { "SuperPackedPlayer service provider data", "dplay.spp.sp_data", FT_BYTES
, BASE_NONE
,
1389 NULL
, 0x0, NULL
, HFILL
}},
1390 { &hf_dplay_spp_player_count
,
1391 { "SuperPackedPlayer player count", "dplay.spp.player_count", FT_UINT32
, BASE_HEX
,
1392 NULL
, 0x0, NULL
, HFILL
}},
1393 { &hf_dplay_spp_player_id
,
1394 { "SuperPackedPlayer player ID", "dplay.spp.player_id", FT_BYTES
, BASE_NONE
,
1395 NULL
, 0x0, NULL
, HFILL
}},
1396 { &hf_dplay_spp_parent_id
,
1397 { "SuperPackedPlayer parent ID", "dplay.spp.parent_id", FT_BYTES
, BASE_NONE
,
1398 NULL
, 0x0, NULL
, HFILL
}},
1399 { &hf_dplay_spp_shortcut_count
,
1400 { "SuperPackedPlayer shortcut count", "dplay.spp.shortcut_count", FT_UINT32
, BASE_HEX
,
1401 NULL
, 0x0, NULL
, HFILL
}},
1402 { &hf_dplay_spp_shortcut_id
,
1403 { "SuperPackedPlayer shortcut ID", "dplay.spp.shortcut_id", FT_BYTES
, BASE_NONE
,
1404 NULL
, 0x0, NULL
, HFILL
}},
1406 /* Data fields for SecDesc struct */
1407 { &hf_dplay_sd_size
,
1408 { "SecDesc struct size", "dplay.sd.size", FT_UINT32
, BASE_DEC
,
1409 NULL
, 0x0, NULL
, HFILL
}},
1410 { &hf_dplay_sd_flags
,
1411 { "SecDesc flags", "dplay.sd.flags", FT_UINT32
, BASE_HEX
,
1412 NULL
, 0x0, NULL
, HFILL
}},
1413 { &hf_dplay_sd_sspi
,
1414 { "SecDesc SSPI provider ptr", "dplay.sd.sspi", FT_BYTES
, BASE_NONE
,
1415 NULL
, 0x0, NULL
, HFILL
}},
1416 { &hf_dplay_sd_capi
,
1417 { "SecDesc CAPI provider ptr", "dplay.sd.capi", FT_BYTES
, BASE_NONE
,
1418 NULL
, 0x0, NULL
, HFILL
}},
1419 { &hf_dplay_sd_capi_type
,
1420 { "SecDesc CAPI provider type", "dplay.sd.capi_type", FT_UINT32
, BASE_HEX
,
1421 NULL
, 0x0, NULL
, HFILL
}},
1422 { &hf_dplay_sd_enc_alg
,
1423 { "SecDesc encryption algorithm", "dplay.sd.enc_alg", FT_UINT32
, BASE_HEX
,
1424 VALS(dplay_enc_alg_val
), 0x0, NULL
, HFILL
}},
1426 /* Data fields for message type 0x0001 */
1427 { &hf_dplay_type_01_name_offset
,
1428 { "Enum Session Reply name offset", "dplay.type_01.name_offs", FT_UINT32
, BASE_DEC
,
1429 NULL
, 0x0, NULL
, HFILL
}},
1430 { &hf_dplay_type_01_game_name
,
1431 { "Enum Session Reply game name", "dplay.type_01.game_name", FT_STRING
, BASE_NONE
,
1432 NULL
, 0x0, NULL
, HFILL
}},
1434 /* Data fields for message type 0x0002 */
1435 { &hf_dplay_type_02_game_guid
,
1436 { "DirectPlay game GUID", "dplay.type02.game.guid", FT_GUID
, BASE_NONE
,
1437 NULL
, 0x0, NULL
, HFILL
}},
1438 { &hf_dplay_type_02_password_offset
,
1439 { "Enum Sessions password offset", "dplay.type02.password_offset", FT_UINT32
, BASE_DEC
,
1440 NULL
, 0x0, NULL
, HFILL
}},
1441 { &hf_dplay_type_02_flags
,
1442 { "Enum Session flags", "dplay.type02.flags", FT_UINT32
, BASE_HEX
,
1443 NULL
, 0x0, NULL
, HFILL
}},
1444 { &hf_dplay_type_02_password
,
1445 { "Session password", "dplay.type02.password", FT_STRING
, BASE_NONE
,
1446 NULL
, 0x0, NULL
, HFILL
}},
1447 { &hf_enum_sess_flag_join
,
1448 { "Enumerate joinable sessions", "dplay.type02.joinable", FT_BOOLEAN
, 32,
1449 TFS(&tfs_present_absent
), DPLAY_ENUM_SESS_FLAG_JOIN
, NULL
, HFILL
}},
1450 { &hf_enum_sess_flag_all
,
1451 { "Enumerate all sessions", "dplay.type02.all", FT_BOOLEAN
, 32,
1452 TFS(&tfs_present_absent
), DPLAY_ENUM_SESS_FLAG_ALL
, NULL
, HFILL
}},
1453 { &hf_enum_sess_flag_passwd
,
1454 { "Enumerate sessions requiring a password", "dplay.type02.pw_req", FT_BOOLEAN
, 32,
1455 TFS(&tfs_present_absent
), DPLAY_ENUM_SESS_FLAG_PASSWD
, NULL
, HFILL
}},
1457 /* Data fields for message type 0x0005 */
1458 { &hf_dplay_type_05_flags
,
1459 { "Player ID request flags", "dplay.type_05.flags", FT_UINT32
, BASE_HEX
,
1460 NULL
, 0x0, NULL
, HFILL
}},
1461 { &hf_dplay_type_05_system_player
,
1462 { "is system player", "dplay.type_05.flags.sys_player", FT_BOOLEAN
, 32,
1463 TFS(&tfs_present_absent
), DPLAY_TYPE05_FLAG_SYSPLAYER
, NULL
, HFILL
}},
1464 { &hf_dplay_type_05_name_server
,
1465 { "is name server", "dplay.type_05.flags.name_server", FT_BOOLEAN
, 32,
1466 TFS(&tfs_present_absent
), DPLAY_TYPE05_FLAG_NAMESERVER
, NULL
, HFILL
}},
1467 { &hf_dplay_type_05_local
,
1468 { "is local player", "dplay.type_05.flags.local", FT_BOOLEAN
, 32,
1469 TFS(&tfs_present_absent
), DPLAY_TYPE05_FLAG_LOCAL
, NULL
, HFILL
}},
1470 { &hf_dplay_type_05_unknown
,
1471 { "unknown", "dplay.type_05.flags.unknown", FT_BOOLEAN
, 32,
1472 TFS(&tfs_present_absent
), DPLAY_TYPE05_FLAG_UNKNOWN
, NULL
, HFILL
}},
1473 { &hf_dplay_type_05_secure
,
1474 { "is secure session", "dplay.type_05.flags.secure", FT_BOOLEAN
, 32,
1475 TFS(&tfs_present_absent
), DPLAY_TYPE05_FLAG_SECURE
, NULL
, HFILL
}},
1477 /* Data fields for message type 0x0007 */
1478 { &hf_dplay_type_07_dpid
,
1479 { "DirectPlay ID", "dplay.type_07.dpid", FT_BYTES
, BASE_NONE
,
1480 NULL
, 0x0, NULL
, HFILL
}},
1481 { &hf_dplay_type_07_sspi_offset
,
1482 { "SSPI provider offset", "dplay.type_07.sspi_offset", FT_UINT32
, BASE_DEC
,
1483 NULL
, 0x0, NULL
, HFILL
}},
1484 { &hf_dplay_type_07_capi_offset
,
1485 { "CAPI provider offset", "dplay.type_07.capi_offset", FT_UINT32
, BASE_DEC
,
1486 NULL
, 0x0, NULL
, HFILL
}},
1487 { &hf_dplay_type_07_hresult
,
1488 { "Request player HRESULT", "dplay.type_07.hresult", FT_UINT32
, BASE_DEC
,
1489 NULL
, 0x0, NULL
, HFILL
}},
1490 { &hf_dplay_type_07_sspi
,
1491 { "SSPI provider", "dplay.type_07.sspi", FT_STRING
, BASE_NONE
,
1492 NULL
, 0x0, NULL
, HFILL
}},
1493 { &hf_dplay_type_07_capi
,
1494 { "CAPI provider", "dplay.type_07.capi", FT_STRING
, BASE_NONE
,
1495 NULL
, 0x0, NULL
, HFILL
}},
1497 /* Data fields for message type 0x0008, 0x0009, 0x000b, 0x000c, 0x000d,
1498 * 0x000e, 0x002e and 0x0038*/
1499 { &hf_dplay_multi_id_to
,
1500 { "ID to", "dplay.multi.id_to", FT_BYTES
, BASE_NONE
,
1501 NULL
, 0x0, NULL
, HFILL
}},
1502 { &hf_dplay_multi_player_id
,
1503 { "Player ID", "dplay.multi.player_id", FT_BYTES
, BASE_NONE
,
1504 NULL
, 0x0, NULL
, HFILL
}},
1505 { &hf_dplay_multi_group_id
,
1506 { "Group ID", "dplay.multi.group_id", FT_BYTES
, BASE_NONE
,
1507 NULL
, 0x0, NULL
, HFILL
}},
1508 { &hf_dplay_multi_create_offset
,
1509 { "Offset to PackedPlayer struct", "dplay.multi.create_offset", FT_UINT32
, BASE_DEC
,
1510 NULL
, 0x0, NULL
, HFILL
}},
1511 { &hf_dplay_multi_password_offset
,
1512 { "Offset to password", "dplay.multi.password_offset", FT_UINT32
, BASE_DEC
,
1513 NULL
, 0x0, NULL
, HFILL
}},
1514 { &hf_dplay_multi_password
,
1515 { "Password", "dplay.multi.password", FT_STRING
, BASE_NONE
,
1516 NULL
, 0x0, NULL
, HFILL
}},
1518 /* Data fields for message type 0x000f */
1519 { &hf_dplay_type_0f_id_to
,
1520 { "ID to", "dplay.type_0f.id_to", FT_BYTES
, BASE_NONE
,
1521 NULL
, 0x0, NULL
, HFILL
}},
1522 { &hf_dplay_type_0f_id
,
1523 { "Player ID", "dplay.type_0f.player_id", FT_BYTES
, BASE_NONE
,
1524 NULL
, 0x0, NULL
, HFILL
}},
1525 { &hf_dplay_type_0f_data_size
,
1526 { "Data Size", "dplay.type_0f.data_size", FT_UINT32
, BASE_DEC
,
1527 NULL
, 0x0, NULL
, HFILL
}},
1528 { &hf_dplay_type_0f_data_offset
,
1529 { "Data Offset", "dplay.type_0f.data_offset", FT_UINT32
, BASE_DEC
,
1530 NULL
, 0x0, NULL
, HFILL
}},
1531 { &hf_dplay_type_0f_data
,
1532 { "Player Data", "dplay.type_0f.player_data", FT_BYTES
, BASE_NONE
,
1533 NULL
, 0x0, NULL
, HFILL
}},
1535 /* Data fields for message type 0x0013 */
1536 { &hf_dplay_type_13_id_to
,
1537 { "ID to", "dplay.type_13.id_to", FT_BYTES
, BASE_NONE
,
1538 NULL
, 0x0, NULL
, HFILL
}},
1539 { &hf_dplay_type_13_player_id
,
1540 { "Player ID", "dplay.type_13.player_id", FT_BYTES
, BASE_NONE
,
1541 NULL
, 0x0, NULL
, HFILL
}},
1542 { &hf_dplay_type_13_group_id
,
1543 { "Group ID", "dplay.type_13.group_id", FT_BYTES
, BASE_NONE
,
1544 NULL
, 0x0, NULL
, HFILL
}},
1545 { &hf_dplay_type_13_create_offset
,
1546 { "Create Offset", "dplay.type_13.create_offset", FT_UINT32
, BASE_DEC
,
1547 NULL
, 0x0, NULL
, HFILL
}},
1548 { &hf_dplay_type_13_password_offset
,
1549 { "Password Offset", "dplay.type_13.password_offset", FT_UINT32
, BASE_DEC
,
1550 NULL
, 0x0, NULL
, HFILL
}},
1551 { &hf_dplay_type_13_password
,
1552 { "Password", "dplay.type_13.password", FT_STRING
, BASE_NONE
,
1553 NULL
, 0x0, NULL
, HFILL
}},
1554 { &hf_dplay_type_13_tick_count
,
1555 { "Tick count? Looks like an ID", "dplay.type_13.tick_count", FT_BYTES
, BASE_NONE
,
1556 NULL
, 0x0, NULL
, HFILL
}},
1558 /* Data fields for message type 0x0015 */
1559 { &hf_dplay_message_guid
,
1560 { "Message GUID", "dplay.message.guid", FT_GUID
, BASE_NONE
,
1561 NULL
, 0x0, NULL
, HFILL
}},
1562 { &hf_dplay_type_15_packet_idx
,
1563 { "Packet Index", "dplay.type_15.packet_idx", FT_UINT32
, BASE_DEC
,
1564 NULL
, 0x0, NULL
, HFILL
}},
1565 { &hf_dplay_type_15_data_size
,
1566 { "Data Size", "dplay.type_15.data_size", FT_UINT32
, BASE_DEC
,
1567 NULL
, 0x0, NULL
, HFILL
}},
1568 { &hf_dplay_type_15_offset
,
1569 { "Offset", "dplay.type_15.offset", FT_UINT32
, BASE_DEC
,
1570 NULL
, 0x0, NULL
, HFILL
}},
1571 { &hf_dplay_type_15_total_packets
,
1572 { "Total Packets", "dplay.type_15.total_packets", FT_UINT32
, BASE_DEC
,
1573 NULL
, 0x0, NULL
, HFILL
}},
1574 { &hf_dplay_type_15_msg_size
,
1575 { "Message size", "dplay.type_15.message.size", FT_UINT32
, BASE_DEC
,
1576 NULL
, 0x0, NULL
, HFILL
}},
1577 { &hf_dplay_type_15_packet_offset
,
1578 { "Packet offset", "dplay.type_15.packet_offset", FT_UINT32
, BASE_DEC
,
1579 NULL
, 0x0, NULL
, HFILL
}},
1581 /* Data field for message type 0x0016 and 0x0017 */
1582 { &hf_dplay_ping_id_from
,
1583 { "ID From", "dplay.ping.id_from", FT_BYTES
, BASE_NONE
,
1584 NULL
, 0x0, NULL
, HFILL
}},
1585 { &hf_dplay_ping_tick_count
,
1586 { "Tick Count", "dplay.ping.tick_count", FT_UINT32
, BASE_DEC
,
1587 NULL
, 0x0, NULL
, HFILL
}},
1589 /* Data fields for message type 0x001a */
1590 { &hf_dplay_type_1a_id_to
,
1591 { "ID From", "dplay.type_1a.id_to", FT_BYTES
, BASE_NONE
,
1592 NULL
, 0x0, NULL
, HFILL
}},
1593 { &hf_dplay_type_1a_sess_name_ofs
,
1594 { "Session Name Offset", "dplay.type_1a.sess_name_ofs", FT_UINT32
, BASE_DEC
,
1595 NULL
, 0x0, NULL
, HFILL
}},
1596 { &hf_dplay_type_1a_password_ofs
,
1597 { "Password Offset", "dplay.type_1a.password_offset", FT_UINT32
, BASE_DEC
,
1598 NULL
, 0x0, NULL
, HFILL
}},
1599 { &hf_dplay_type_1a_session_name
,
1600 { "Session Name", "dplay.type_1a.session_name", FT_STRING
, BASE_NONE
,
1601 NULL
, 0x0, NULL
, HFILL
}},
1602 { &hf_dplay_type_1a_password
,
1603 { "Password", "dplay.type_1a.password", FT_STRING
, BASE_NONE
,
1604 NULL
, 0x0, NULL
, HFILL
}},
1606 /* Data fields for message type 0x0029 */
1607 { &hf_dplay_type_29_player_count
,
1608 { "SuperEnumPlayers Reply player count", "dplay.type_29.player_count", FT_UINT32
,
1609 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1610 { &hf_dplay_type_29_group_count
,
1611 { "SuperEnumPlayers Reply group count", "dplay.type_29.group_count", FT_UINT32
,
1612 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1613 { &hf_dplay_type_29_packed_offset
,
1614 { "SuperEnumPlayers Reply packed offset", "dplay.type_29.packed_offset", FT_UINT32
,
1615 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1616 { &hf_dplay_type_29_shortcut_count
,
1617 { "SuperEnumPlayers Reply shortcut count", "dplay.type_29.shortcut_count", FT_UINT32
,
1618 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1619 { &hf_dplay_type_29_description_offset
,
1620 { "SuperEnumPlayers Reply description offset", "dplay.type_29.desc_offset", FT_UINT32
,
1621 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1622 { &hf_dplay_type_29_name_offset
,
1623 { "SuperEnumPlayers Reply name offset", "dplay.type_29.name_offset", FT_UINT32
,
1624 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1625 { &hf_dplay_type_29_password_offset
,
1626 { "SuperEnumPlayers Reply password offset", "dplay.type_29.pass_offset", FT_UINT32
,
1627 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1628 { &hf_dplay_type_29_game_name
,
1629 { "SuperEnumPlayers Reply game name", "dplay.type_29.game_name", FT_STRING
, BASE_NONE
,
1630 NULL
, 0x0, NULL
, HFILL
}},
1631 { &hf_dplay_type_29_password
,
1632 { "SuperEnumPlayers Reply Password", "dplay.type_29.password", FT_STRING
, BASE_NONE
,
1633 NULL
, 0x0, NULL
, HFILL
}},
1635 /* Data fields for message type 0x002f */
1636 { &hf_dplay_type_2f_dpid
,
1637 { "ID of the forwarded player", "dplay.type_29.id", FT_BYTES
, BASE_NONE
,
1638 NULL
, 0x0, NULL
, HFILL
}},
1641 static int *ett
[] = {
1644 &ett_dplay_sockaddr
,
1647 &ett_dplay_enc_packet
,
1648 &ett_dplay_sess_desc_flags
,
1649 &ett_dplay_pp_flags
,
1650 &ett_dplay_spp_flags
,
1651 &ett_dplay_spp_info_mask
,
1652 &ett_dplay_type02_flags
,
1653 &ett_dplay_type05_flags
,
1654 &ett_dplay_type29_spp
,
1657 proto_dplay
= proto_register_protocol (
1658 "DirectPlay Protocol",
1662 proto_register_field_array(proto_dplay
, hf
, array_length(hf
));
1663 proto_register_subtree_array(ett
, array_length(ett
));
1666 void proto_reg_handoff_dplay(void)
1668 heur_dissector_add("udp", heur_dissect_dplay
, "DirectPlay over UDP", "dplay_udp", proto_dplay
, HEURISTIC_ENABLE
);
1669 heur_dissector_add("tcp", heur_dissect_dplay
, "DirectPlay over TCP", "dplay_tcp", proto_dplay
, HEURISTIC_ENABLE
);
1673 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1678 * indent-tabs-mode: nil
1681 * vi: set shiftwidth=4 tabstop=8 expandtab:
1682 * :indentSize=4:tabSize=8:noTabs=true: