2 * This is a dissector for the DirectPlay protocol.
3 * Copyright 2006 - 2008 by Kai Blin
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
24 * USA.59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32 #include <epan/packet.h>
33 #include <epan/emem.h>
34 #include <epan/aftypes.h>
37 /* function declarations */
38 static gboolean heur_dissect_dplay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
39 static void dissect_dplay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
40 static gint dissect_type1a_message(proto_tree *tree, tvbuff_t *tvb, gint offset);
42 static int proto_dplay = -1;
44 /* Common data fields */
45 static int hf_dplay_size = -1; /* Size of the whole data */
46 static int hf_dplay_token = -1;
47 static int hf_dplay_saddr_af = -1; /* WINSOCK_AF_INET, as this dissector does not handle IPX yet */
48 static int hf_dplay_saddr_port = -1; /* port to use for the reply to this packet */
49 static int hf_dplay_saddr_ip = -1; /* IP to use for the reply to this packet, or 0.0.0.0,
50 then use the same IP as this packet used. */
51 static int hf_dplay_saddr_padding = -1; /* null padding used in s_addr_in structures */
52 static int hf_dplay_play_str = -1; /* always "play" without a null terminator */
53 static int hf_dplay_command = -1; /* the dplay command this message contains*/
54 static int hf_dplay_proto_dialect = -1; /* 0x0b00 for dplay7, 0x0e00 for dplay9 */
55 static int hf_dplay_play_str_2 = -1; /* packet type 0x0015 encapsulates another packet */
56 static int hf_dplay_command_2 = -1; /* that also has a "play" string, a command and a */
57 static int hf_dplay_proto_dialect_2 = -1; /* protocol dialect, same as above */
58 static const int DPLAY_HEADER_OFFSET = 28; /* The dplay header is 28 bytes in size */
59 static int hf_dplay_player_msg = -1;
61 /* The following fields are not part of the header, but hopefully have the same
62 * meaning for all packets they show up in. */
64 static int hf_dplay_sess_desc_flags = -1; /* This is a 32bit field with some sort of a flag */
65 static int hf_dplay_flags_no_create_players = -1;
66 static int hf_dplay_flags_0002 = -1;
67 static int hf_dplay_flags_migrate_host = -1;
68 static int hf_dplay_flags_short_player_msg = -1;
69 static int hf_dplay_flags_ignored = -1;
70 static int hf_dplay_flags_can_join = -1;
71 static int hf_dplay_flags_use_ping = -1;
72 static int hf_dplay_flags_no_player_updates = -1;
73 static int hf_dplay_flags_use_auth = -1;
74 static int hf_dplay_flags_private_session = -1;
75 static int hf_dplay_flags_password_req = -1;
76 static int hf_dplay_flags_route = -1;
77 static int hf_dplay_flags_server_player_only = -1;
78 static int hf_dplay_flags_reliable = -1;
79 static int hf_dplay_flags_preserve_order = -1;
80 static int hf_dplay_flags_optimize_latency = -1;
81 static int hf_dplay_flags_acqire_voice = -1;
82 static int hf_dplay_flags_no_sess_desc_changes = -1;
84 #define DPLAY_FLAG_NO_CREATE_PLAYERS 0x0001
85 #define DPLAY_FLAG_0002 0x0002
86 #define DPLAY_FLAG_MIGRATE_HOST 0x0004
87 #define DPLAY_FLAG_SHORT_PLAYER_MSG 0x0008
88 #define DPLAY_FLAG_IGNORED 0x0010
89 #define DPLAY_FLAG_CAN_JOIN 0x0020
90 #define DPLAY_FLAG_USE_PING 0x0040
91 #define DPLAY_FLAG_NO_P_UPD 0x0080
92 #define DPLAY_FLAG_USE_AUTH 0x0100
93 #define DPLAY_FLAG_PRIV_SESS 0x0200
94 #define DPLAY_FLAG_PASS_REQ 0x0400
95 #define DPLAY_FLAG_ROUTE 0x0800
96 #define DPLAY_FLAG_SRV_ONLY 0x1000
97 #define DPLAY_FLAG_RELIABLE 0x2000
98 #define DPLAY_FLAG_ORDER 0x4000
99 #define DPLAY_FLAG_OPT_LAT 0x8000
100 #define DPLAY_FLAG_ACQ_VOICE 0x10000
101 #define DPLAY_FLAG_NO_SESS_DESC_CHANGES 0x20000
103 /* Session description structure fields */
104 static int hf_dplay_sess_desc_length = -1;
105 static int hf_dplay_game_guid = -1;
106 static int hf_dplay_instance_guid = -1;
107 static int hf_dplay_max_players = -1;
108 static int hf_dplay_curr_players = -1;
109 static int hf_dplay_sess_name_ptr = -1;
110 static int hf_dplay_passwd_ptr = -1;
111 static int hf_dplay_sess_desc_reserved_1 = -1;
112 static int hf_dplay_sess_desc_reserved_2 = -1;
113 static int hf_dplay_sess_desc_user_1 = -1;
114 static int hf_dplay_sess_desc_user_2 = -1;
115 static int hf_dplay_sess_desc_user_3 = -1;
116 static int hf_dplay_sess_desc_user_4 = -1;
118 /* PackedPlayer structure fields */
119 static int hf_dplay_pp_size = -1;
120 static int hf_dplay_pp_flags = -1;
121 static int hf_dplay_pp_flag_sysplayer = -1;
122 static int hf_dplay_pp_flag_nameserver = -1;
123 static int hf_dplay_pp_flag_in_group = -1;
124 static int hf_dplay_pp_flag_sending = -1;
125 static int hf_dplay_pp_id = -1;
126 static int hf_dplay_pp_short_name_len = -1;
127 static int hf_dplay_pp_long_name_len = -1;
128 static int hf_dplay_pp_sp_data_size = -1;
129 static int hf_dplay_pp_player_data_size = -1;
130 static int hf_dplay_pp_num_players = -1;
131 static int hf_dplay_pp_system_player = -1;
132 static int hf_dplay_pp_fixed_size = -1;
133 static int hf_dplay_pp_dialect = -1;
134 static int hf_dplay_pp_unknown_1 = -1;
135 static int hf_dplay_pp_short_name = -1;
136 static int hf_dplay_pp_long_name = -1;
137 static int hf_dplay_pp_sp_data = -1;
138 static int hf_dplay_pp_player_data = -1;
139 static int hf_dplay_pp_player_id = -1;
140 static int hf_dplay_pp_parent_id = -1;
141 #define DPLAY_PP_FLAG_SYSPLAYER 0x01
142 #define DPLAY_PP_FLAG_NAMESERVER 0x02
143 #define DPLAY_PP_FLAG_IN_GROUP 0x04
144 #define DPLAY_PP_FLAG_SENDING 0x08
146 /* SuperPackedPlayer structure fields */
147 static int hf_dplay_spp_size = -1;
148 static int hf_dplay_spp_flags = -1;
149 static int hf_dplay_spp_flags_sysplayer = -1;
150 static int hf_dplay_spp_flags_nameserver = -1;
151 static int hf_dplay_spp_flags_in_group = -1;
152 static int hf_dplay_spp_flags_sending = -1;
153 static int hf_dplay_spp_id = -1;
154 static int hf_dplay_spp_player_info_mask = -1;
155 static int hf_dplay_spp_have_short_name = -1;
156 static int hf_dplay_spp_have_long_name = -1;
157 static int hf_dplay_spp_sp_length_type = -1;
158 static int hf_dplay_spp_pd_length_type = -1;
159 static int hf_dplay_spp_player_count_type = -1;
160 static int hf_dplay_spp_have_parent_id = -1;
161 static int hf_dplay_spp_shortcut_count_type = -1;
162 static int hf_dplay_spp_dialect = -1;
163 static int hf_dplay_spp_sys_player_id = -1;
164 static int hf_dplay_spp_short_name = -1;
165 static int hf_dplay_spp_long_name = -1;
166 static int hf_dplay_spp_player_data_length = -1;
167 static int hf_dplay_spp_player_data = -1;
168 static int hf_dplay_spp_sp_data_length = -1;
169 static int hf_dplay_spp_sp_data = -1;
170 static int hf_dplay_spp_player_count = -1;
171 static int hf_dplay_spp_player_id = -1;
172 static int hf_dplay_spp_parent_id = -1;
173 static int hf_dplay_spp_shortcut_count = -1;
174 static int hf_dplay_spp_shortcut_id = -1;
175 #define DPLAY_SPP_FLAG_SYSPLAYER 0x01
176 #define DPLAY_SPP_FLAG_NAMESERVER 0x02
177 #define DPLAY_SPP_FLAG_IN_GROUP 0x04
178 #define DPLAY_SPP_FLAG_SENDING 0x08
180 /* SecurityDesc structure fields */
181 static int hf_dplay_sd_size = -1;
182 static int hf_dplay_sd_flags = -1;
183 static int hf_dplay_sd_sspi = -1;
184 static int hf_dplay_sd_capi = -1;
185 static int hf_dplay_sd_capi_type = -1;
186 static int hf_dplay_sd_enc_alg = -1;
188 /* Message Type 0x0001 data fields */
189 static int hf_dplay_type_01_name_offset = -1;
190 static int hf_dplay_type_01_game_name = -1;
192 /* Message Type 0x0002 data fields */
193 static int hf_dplay_type_02_game_guid = -1;
194 static int hf_dplay_type_02_password_offset = -1;
195 static int hf_dplay_type_02_flags = -1;
196 static int hf_dplay_type_02_password = -1;
197 static int hf_enum_sess_flag_join = -1;
198 static int hf_enum_sess_flag_all = -1;
199 static int hf_enum_sess_flag_passwd = -1;
200 #define DPLAY_ENUM_SESS_FLAG_JOIN 0x0001
201 #define DPLAY_ENUM_SESS_FLAG_ALL 0x0002
202 #define DPLAY_ENUM_SESS_FLAG_PASSWD 0x0040
204 /* Message Type 0x0005 data fields */
205 static int hf_dplay_type_05_flags = -1;
206 static int hf_dplay_type_05_system_player = -1;
207 static int hf_dplay_type_05_name_server = -1;
208 static int hf_dplay_type_05_local = -1;
209 static int hf_dplay_type_05_unknown = -1; /* unknown, but always set */
210 static int hf_dplay_type_05_secure = -1;
211 #define DPLAY_TYPE05_FLAG_SYSPLAYER 0x001
212 #define DPLAY_TYPE05_FLAG_NAMESERVER 0x002
213 #define DPLAY_TYPE05_FLAG_LOCAL 0x004
214 #define DPLAY_TYPE05_FLAG_UNKNOWN 0x008
215 #define DPLAY_TYPE05_FLAG_SECURE 0x200
217 /* Message Type 0x0007 data fields */
218 static int hf_dplay_type_07_dpid = -1;
219 static int hf_dplay_type_07_sspi_offset = -1;
220 static int hf_dplay_type_07_capi_offset = -1;
221 static int hf_dplay_type_07_hresult = -1;
222 static int hf_dplay_type_07_sspi = -1;
223 static int hf_dplay_type_07_capi = -1;
225 /* Data fields for message types 0x08, 0x09, 0x0b, 0x0c, 0x0d, 0x0e */
226 static int hf_dplay_multi_id_to = -1;
227 static int hf_dplay_multi_player_id = -1;
228 static int hf_dplay_multi_group_id = -1;
229 static int hf_dplay_multi_create_offset = -1;
230 static int hf_dplay_multi_password_offset = -1;
231 static int hf_dplay_multi_password = -1;
233 /* Message Type 0x000f data fields */
234 static int hf_dplay_type_0f_id_to = -1;
235 static int hf_dplay_type_0f_id = -1;
236 static int hf_dplay_type_0f_data_size = -1;
237 static int hf_dplay_type_0f_data_offset = -1;
238 static int hf_dplay_type_0f_data = -1;
240 /* Message Type 0x0013 data fields */
241 static int hf_dplay_type_13_id_to = -1;
242 static int hf_dplay_type_13_player_id = -1;
243 static int hf_dplay_type_13_group_id = -1;
244 static int hf_dplay_type_13_create_offset = -1;
245 static int hf_dplay_type_13_password_offset = -1;
246 static int hf_dplay_type_13_password = -1;
247 static int hf_dplay_type_13_tick_count = -1;
249 /* Message Type 0x0015 data fields */
250 static int hf_dplay_message_guid = -1;
251 static int hf_dplay_type_15_packet_idx = -1;
252 static int hf_dplay_type_15_data_size = -1;
253 static int hf_dplay_type_15_offset = -1;
254 static int hf_dplay_type_15_total_packets = -1;
255 static int hf_dplay_type_15_msg_size = -1;
256 static int hf_dplay_type_15_packet_offset = -1;
258 /* Message Type 0x0016 and 0x0017 data fields */
259 static int hf_dplay_ping_id_from = -1;
260 static int hf_dplay_ping_tick_count = -1;
262 /* Message Type 0x001a data fields */
263 static int hf_dplay_type_1a_id_to = -1;
264 static int hf_dplay_type_1a_sess_name_ofs = -1;
265 static int hf_dplay_type_1a_password_ofs = -1;
266 static int hf_dplay_type_1a_session_name = -1;
267 static int hf_dplay_type_1a_password = -1;
269 /* Message Type 0x0029 data fields */
270 static int hf_dplay_type_29_player_count = -1;
271 static int hf_dplay_type_29_group_count = -1;
272 static int hf_dplay_type_29_packed_offset = -1;
273 static int hf_dplay_type_29_shortcut_count = -1;
274 static int hf_dplay_type_29_description_offset = -1;
275 static int hf_dplay_type_29_name_offset = -1;
276 static int hf_dplay_type_29_password_offset = -1;
277 static int hf_dplay_type_29_game_name = -1;
278 static int hf_dplay_type_29_password = -1;
280 /* Message Type 0x002f data fields */
281 static int hf_dplay_type_2f_dpid = -1;
284 static gint ett_dplay = -1;
285 static gint ett_dplay_header = -1;
286 static gint ett_dplay_sockaddr = -1;
287 static gint ett_dplay_data = -1;
288 static gint ett_dplay_enc_packet = -1;
289 static gint ett_dplay_flags = -1;
290 static gint ett_dplay_sess_desc_flags = -1;
291 static gint ett_dplay_pp_flags = -1;
292 static gint ett_dplay_spp_flags = -1;
293 static gint ett_dplay_spp_info_mask = -1;
294 static gint ett_dplay_type02_flags = -1;
295 static gint ett_dplay_type05_flags = -1;
296 static gint ett_dplay_type29_spp = -1;
298 static const value_string dplay_command_val[] = {
299 { 0x0001, "Enum Sessions Reply" },
300 { 0x0002, "Enum Sessions" },
301 { 0x0003, "Enum Players Reply" },
302 { 0x0004, "Enum Players" },
303 { 0x0005, "Request Player ID" },
304 { 0x0006, "Request Group ID" },
305 { 0x0007, "Request Player Reply" },
306 { 0x0008, "Create Player" },
307 { 0x0009, "Create Group" },
308 { 0x000a, "Player Message" },
309 { 0x000b, "Delete Player" },
310 { 0x000c, "Delete Group" },
311 { 0x000d, "Add Player To Group" },
312 { 0x000e, "Delete Player From Group" },
313 { 0x000f, "Player Data Changed" },
314 { 0x0010, "Player Name Changed" },
315 { 0x0011, "Group Data Changed" },
316 { 0x0012, "Group Name Changed" },
317 { 0x0013, "Add Forward Request" },
318 /* There is no command 0x0014 */
319 { 0x0015, "Packet" },
322 { 0x0018, "You Are Dead" },
323 { 0x0019, "Player Wrapper" },
324 { 0x001a, "Session Desc Changed" },
325 { 0x001c, "Challenge" },
326 { 0x001d, "Access Granted" },
327 { 0x001e, "Logon Denied" },
328 { 0x001f, "Auth Error" },
329 { 0x0020, "Negotiate" },
330 { 0x0021, "Challenge Response" },
332 /* There is no command 0x0023 */
333 { 0x0024, "Add Forward Reply" },
334 { 0x0025, "Ask For Multicast" },
335 { 0x0026, "Ask For Multicast Guaranteed" },
336 { 0x0027, "Add Shortcut To Group" },
337 { 0x0028, "Delete Group From Group" },
338 { 0x0029, "Super Enum Players Reply" },
339 /* There is no command 0x002a */
340 { 0x002b, "Key Exchange" },
341 { 0x002c, "Key Exchange Reply" },
343 { 0x002e, "Add Forward" },
344 { 0x002f, "Add Forward ACK" },
345 { 0x0030, "Packet2 Data" },
346 { 0x0031, "Packet2 ACK" },
347 /* No commands 0x0032, 0x0033, 0x0034 */
348 { 0x0035, "I Am Nameserver" },
350 { 0x0037, "Multicast Delivery" },
351 { 0x0038, "Create Players Verify"},
355 static const value_string dplay_af_val[] = {
356 { WINSOCK_AF_INET, "AF_INET" },
357 { WINSOCK_AF_IPX, "AF_IPX" },
361 static const value_string dplay_proto_dialect_val[] = {
362 { 0x0009, "dplay 6" },
363 { 0x000a, "dplay 6.1" },
364 { 0x000b, "dplay 6.1a" },
365 { 0x000c, "dplay 7.1" },
366 { 0x000d, "dplay 8" },
367 { 0x000e, "dplay 9"},
371 static const value_string dplay_token_val[] = {
372 { 0xfab, "Remote Message" },
373 { 0xcab, "Forwarded Message" },
374 { 0xbab, "Server Message" },
378 static const value_string dplay_spp_length_val[] = {
379 { 0x0, "Not present" },
381 { 0x2, "Two bytes" },
382 { 0x3, "Four bytes" },
386 static const value_string dplay_enc_alg_val[] = {
387 { 0x0000, "Default" },
396 static const value_string yes_no_val[] = {
402 static const true_false_string tfs_dplay_flag = {
407 /* borrowed from epan/dissectors/packets-smb-common.c */
408 static gint display_unicode_string(proto_tree *tree, gint hf_index, tvbuff_t *tvb, gint offset)
415 /* display a unicode string from the tree and return new offset */
418 * Get the length of the string.
419 * XXX - is it a bug or a feature that this will throw an exception
420 * if we don't find the '\0'? I think it's a feature.
423 while ((character = tvb_get_letohs(tvb, offset + len)) != '\0')
425 len += 2; /* count the '\0' too */
428 * Allocate a buffer for the string; "len" is the length in
429 * bytes, not the length in characters.
431 str = ep_alloc(len/2);
434 * XXX - this assumes the string is just ISO 8859-1; we need
435 * to better handle multiple character sets in Wireshark,
436 * including Unicode/ISO 10646, and multiple encodings of
437 * that character set (UCS-2, UTF-8, etc.).
441 while ((character = tvb_get_letohs(tvb, charoffset)) != '\0') {
442 *p++ = (char) character;
447 proto_tree_add_string(tree, hf_index, tvb, offset, len, str);
452 static gint dissect_sockaddr_in(proto_tree *tree, tvbuff_t *tvb, gint offset)
454 proto_item *sa_item = NULL;
455 proto_tree *sa_tree = NULL;
457 sa_item = proto_tree_add_text(tree, tvb, offset, 16,
458 "DirectPlay sockaddr_in structure");
459 sa_tree = proto_item_add_subtree(sa_item, ett_dplay_sockaddr);
460 proto_tree_add_item(sa_tree, hf_dplay_saddr_af, tvb, offset, 2, TRUE); offset += 2;
461 proto_tree_add_item(sa_tree, hf_dplay_saddr_port, tvb, offset, 2, FALSE); offset += 2;
462 proto_tree_add_item(sa_tree, hf_dplay_saddr_ip, tvb, offset, 4, FALSE); offset += 4;
463 proto_tree_add_item(sa_tree, hf_dplay_saddr_padding, tvb, offset, 8, FALSE); offset += 8;
467 static gint dissect_session_desc(proto_tree *tree, tvbuff_t *tvb, gint offset)
471 proto_item *flags_item = NULL;
472 proto_tree *flags_tree = NULL;
474 data_len = tvb_get_letohl(tvb, offset);
475 flags = tvb_get_letohl(tvb, offset+4);
477 proto_tree_add_item(tree, hf_dplay_sess_desc_length, tvb, offset, 4, TRUE); offset += 4;
478 flags_item = proto_tree_add_item(tree, hf_dplay_sess_desc_flags, tvb, offset, 4, TRUE);
479 flags_tree = proto_item_add_subtree(flags_item, ett_dplay_sess_desc_flags);
480 proto_tree_add_boolean(flags_tree, hf_dplay_flags_no_sess_desc_changes, tvb, offset, 4, flags);
481 proto_tree_add_boolean(flags_tree, hf_dplay_flags_acqire_voice, tvb, offset, 4, flags);
482 proto_tree_add_boolean(flags_tree, hf_dplay_flags_optimize_latency, tvb, offset, 4, flags);
483 proto_tree_add_boolean(flags_tree, hf_dplay_flags_preserve_order, tvb, offset, 4, flags);
484 proto_tree_add_boolean(flags_tree, hf_dplay_flags_reliable, tvb, offset, 4, flags);
485 proto_tree_add_boolean(flags_tree, hf_dplay_flags_server_player_only, tvb, offset, 4, flags);
486 proto_tree_add_boolean(flags_tree, hf_dplay_flags_route, tvb, offset, 4, flags);
487 proto_tree_add_boolean(flags_tree, hf_dplay_flags_password_req, tvb, offset, 4, flags);
488 proto_tree_add_boolean(flags_tree, hf_dplay_flags_private_session, tvb, offset, 4, flags);
489 proto_tree_add_boolean(flags_tree, hf_dplay_flags_use_auth, tvb, offset, 4, flags);
490 proto_tree_add_boolean(flags_tree, hf_dplay_flags_no_player_updates, tvb, offset, 4, flags);
491 proto_tree_add_boolean(flags_tree, hf_dplay_flags_use_ping, tvb, offset, 4, flags);
492 proto_tree_add_boolean(flags_tree, hf_dplay_flags_can_join, tvb, offset, 4, flags);
493 proto_tree_add_boolean(flags_tree, hf_dplay_flags_ignored, tvb, offset, 4, flags);
494 proto_tree_add_boolean(flags_tree, hf_dplay_flags_short_player_msg, tvb, offset, 4, flags);
495 proto_tree_add_boolean(flags_tree, hf_dplay_flags_migrate_host, tvb, offset, 4, flags);
496 proto_tree_add_boolean(flags_tree, hf_dplay_flags_0002, tvb, offset, 4, flags);
497 proto_tree_add_boolean(flags_tree, hf_dplay_flags_no_create_players, tvb, offset, 4, flags);
500 proto_tree_add_item(tree, hf_dplay_instance_guid, tvb, offset, 16, FALSE); offset += 16;
501 proto_tree_add_item(tree, hf_dplay_game_guid, tvb, offset, 16, FALSE); offset += 16;
502 proto_tree_add_item(tree, hf_dplay_max_players, tvb, offset, 4, TRUE); offset += 4;
503 proto_tree_add_item(tree, hf_dplay_curr_players, tvb, offset, 4, TRUE); offset += 4;
504 proto_tree_add_item(tree, hf_dplay_sess_name_ptr, tvb, offset, 4, FALSE); offset += 4;
505 proto_tree_add_item(tree, hf_dplay_passwd_ptr, tvb, offset, 4, FALSE); offset += 4;
506 proto_tree_add_item(tree, hf_dplay_sess_desc_reserved_1, tvb, offset, 4, FALSE); offset += 4;
507 proto_tree_add_item(tree, hf_dplay_sess_desc_reserved_2, tvb, offset, 4, FALSE); offset += 4;
508 proto_tree_add_item(tree, hf_dplay_sess_desc_user_1, tvb, offset, 4, FALSE); offset += 4;
509 proto_tree_add_item(tree, hf_dplay_sess_desc_user_2, tvb, offset, 4, FALSE); offset += 4;
510 proto_tree_add_item(tree, hf_dplay_sess_desc_user_3, tvb, offset, 4, FALSE); offset += 4;
511 proto_tree_add_item(tree, hf_dplay_sess_desc_user_4, tvb, offset, 4, FALSE); offset += 4;
516 static gint dissect_packed_player(proto_tree *tree, tvbuff_t *tvb, gint offset)
518 proto_tree *flags_tree;
519 proto_item *flags_item;
520 guint32 flags, sn_len, ln_len, sd_len, pd_len, num_players, i;
523 size = tvb_get_letohl(tvb, offset);
524 proto_tree_add_item(tree, hf_dplay_pp_size, tvb, offset, 4, TRUE); offset += 4;
526 flags = tvb_get_letohl(tvb, offset);
527 flags_item = proto_tree_add_item(tree, hf_dplay_pp_flags, tvb, offset, 4, TRUE);
528 flags_tree = proto_item_add_subtree(flags_item, ett_dplay_pp_flags);
529 proto_tree_add_boolean(flags_tree, hf_dplay_pp_flag_sending, tvb, offset, 4, flags);
530 proto_tree_add_boolean(flags_tree, hf_dplay_pp_flag_in_group, tvb, offset, 4, flags);
531 proto_tree_add_boolean(flags_tree, hf_dplay_pp_flag_nameserver, tvb, offset, 4, flags);
532 proto_tree_add_boolean(flags_tree, hf_dplay_pp_flag_sysplayer, tvb, offset, 4, flags);
535 proto_tree_add_item(tree, hf_dplay_pp_id, tvb, offset, 4, FALSE); offset += 4;
537 sn_len = tvb_get_letohl(tvb, offset);
538 proto_tree_add_item(tree, hf_dplay_pp_short_name_len, tvb, offset, 4, TRUE); offset += 4;
539 ln_len = tvb_get_letohl(tvb, offset);
540 proto_tree_add_item(tree, hf_dplay_pp_long_name_len, tvb, offset, 4, TRUE); offset += 4;
541 sd_len = tvb_get_letohl(tvb, offset);
542 proto_tree_add_item(tree, hf_dplay_pp_sp_data_size, tvb, offset, 4, TRUE); offset += 4;
543 pd_len = tvb_get_letohl(tvb, offset);
544 proto_tree_add_item(tree, hf_dplay_pp_player_data_size, tvb, offset, 4, TRUE); offset += 4;
545 num_players = tvb_get_letohl(tvb, offset);
546 proto_tree_add_item(tree, hf_dplay_pp_num_players, tvb, offset, 4, TRUE); offset += 4;
548 proto_tree_add_item(tree, hf_dplay_pp_system_player, tvb, offset, 4, FALSE); offset += 4;
549 proto_tree_add_item(tree, hf_dplay_pp_fixed_size, tvb, offset, 4, TRUE); offset += 4;
550 proto_tree_add_item(tree, hf_dplay_pp_dialect, tvb, offset, 4, TRUE); offset += 4;
551 proto_tree_add_item(tree, hf_dplay_pp_unknown_1, tvb, offset, 4, FALSE); offset += 4;
554 offset = display_unicode_string(tree, hf_dplay_pp_short_name, tvb, offset);
557 offset = display_unicode_string(tree, hf_dplay_pp_long_name, tvb, offset);
559 proto_tree_add_item(tree, hf_dplay_pp_sp_data, tvb, offset, sd_len, FALSE);
563 proto_tree_add_item(tree, hf_dplay_pp_player_data, tvb, offset, pd_len, FALSE);
567 for (i=0; i < num_players; ++i) {
568 proto_tree_add_item(tree, hf_dplay_pp_player_id, tvb, offset, 4, FALSE); offset += 4;
571 /* Size seems to miss the unknown empty dword */
572 if (size + 4 > offset) {
573 proto_tree_add_item(tree, hf_dplay_pp_parent_id, tvb, offset, 4, FALSE); offset += 4;
579 static gint spp_get_value(guint32 length_type, tvbuff_t *tvb, gint offset, guint32 *value)
585 switch (length_type) {
588 *value = tvb_get_guint8(tvb, offset);
592 *value = tvb_get_letohs(tvb, offset);
596 *value = tvb_get_letohl(tvb, offset);
603 static gint dissect_dplay_super_packed_player(proto_tree *tree, tvbuff_t *tvb, gint offset)
605 guint32 flags, is_sysplayer, info_mask;
606 guint32 have_short_name, have_long_name, sp_length_type, pd_length_type;
607 guint32 player_count_type, have_parent_id, shortcut_count_type;
608 guint32 player_data_length, sp_data_length, player_count, shortcut_count;
609 proto_item *flags_item = NULL, *im_item = NULL;
610 proto_tree *flags_tree = NULL, *im_tree = NULL;
613 proto_tree_add_item(tree, hf_dplay_spp_size, tvb, offset, 4, TRUE); offset += 4;
615 flags = tvb_get_letohl(tvb, offset);
616 is_sysplayer = flags & 0x00000001;
617 flags_item = proto_tree_add_item(tree, hf_dplay_spp_flags, tvb, offset, 4, TRUE);
618 flags_tree = proto_item_add_subtree(flags_item, ett_dplay_spp_flags);
619 proto_tree_add_boolean(flags_tree, hf_dplay_spp_flags_sending, tvb, offset, 4, flags);
620 proto_tree_add_boolean(flags_tree, hf_dplay_spp_flags_in_group, tvb, offset, 4, flags);
621 proto_tree_add_boolean(flags_tree, hf_dplay_spp_flags_nameserver, tvb, offset, 4, flags);
622 proto_tree_add_boolean(flags_tree, hf_dplay_spp_flags_sysplayer, tvb, offset, 4, flags);
624 proto_tree_add_item(tree, hf_dplay_spp_id, tvb, offset, 4, TRUE); offset += 4;
626 info_mask = tvb_get_letohl(tvb, offset);
628 have_short_name = info_mask & 0x00000001;
629 have_long_name = (info_mask & 0x00000002) >> 1;
630 sp_length_type = (info_mask & 0x0000000c) >> 2;
631 pd_length_type = (info_mask & 0x00000030) >> 4;
632 player_count_type = (info_mask & 0x000000c0) >> 6;
633 have_parent_id = (info_mask & 0x00000100) >> 8;
634 shortcut_count_type = (info_mask & 0x00000600) >> 9;
636 im_item = proto_tree_add_item(tree, hf_dplay_spp_player_info_mask, tvb, offset, 4, TRUE);
638 im_tree = proto_item_add_subtree(im_item, ett_dplay_spp_info_mask);
639 proto_tree_add_uint(im_tree, hf_dplay_spp_have_short_name, tvb, offset, 4, have_short_name);
640 proto_tree_add_uint(im_tree, hf_dplay_spp_have_long_name, tvb, offset, 4, have_long_name);
641 proto_tree_add_uint(im_tree, hf_dplay_spp_sp_length_type, tvb, offset, 4, sp_length_type);
642 proto_tree_add_uint(im_tree, hf_dplay_spp_pd_length_type, tvb, offset, 4, pd_length_type);
643 proto_tree_add_uint(im_tree, hf_dplay_spp_player_count_type, tvb, offset, 4, player_count_type);
644 proto_tree_add_uint(im_tree, hf_dplay_spp_have_parent_id, tvb, offset, 4, have_parent_id);
645 proto_tree_add_uint(im_tree, hf_dplay_spp_shortcut_count_type, tvb, offset, 4, shortcut_count_type);
649 proto_tree_add_item(tree, hf_dplay_spp_dialect, tvb, offset, 4, TRUE);
651 proto_tree_add_item(tree, hf_dplay_spp_sys_player_id, tvb, offset, 4, FALSE);
655 if (have_short_name) {
656 offset = display_unicode_string(tree, hf_dplay_spp_short_name, tvb, offset);
659 if (have_long_name) {
660 offset = display_unicode_string(tree, hf_dplay_spp_long_name, tvb, offset);
663 if (pd_length_type) {
664 len = spp_get_value(pd_length_type, tvb, offset, &player_data_length);
665 proto_tree_add_item(tree, hf_dplay_spp_player_data_length, tvb, offset, len, TRUE);
667 proto_tree_add_item(tree, hf_dplay_spp_player_data, tvb, offset, player_data_length, FALSE);
668 offset += player_data_length;
671 if (sp_length_type) {
672 len = spp_get_value(sp_length_type, tvb, offset, &sp_data_length);
673 proto_tree_add_item(tree, hf_dplay_spp_sp_data_length, tvb, offset, len, TRUE);
675 proto_tree_add_item(tree, hf_dplay_spp_sp_data, tvb, offset, sp_data_length, FALSE);
676 offset += sp_data_length;
679 if (player_count_type) {
682 len = spp_get_value(player_count_type, tvb, offset, &player_count);
683 proto_tree_add_item(tree, hf_dplay_spp_player_count, tvb, offset, len, TRUE);
685 for (i=0; i < player_count; ++i) {
686 proto_tree_add_item(tree, hf_dplay_spp_player_id, tvb, offset, 4, FALSE); offset += 4;
690 if (have_parent_id) {
691 proto_tree_add_item(tree, hf_dplay_spp_parent_id, tvb, offset, 4, FALSE); offset += 4;
694 if (shortcut_count_type) {
697 len = spp_get_value(shortcut_count_type, tvb, offset, &shortcut_count);
698 proto_tree_add_item(tree, hf_dplay_spp_shortcut_count, tvb, offset, len, TRUE);
700 for (i=0; i < shortcut_count; ++i) {
701 proto_tree_add_item(tree, hf_dplay_spp_shortcut_id, tvb, offset, 4, FALSE); offset += 4;
708 static gint dissect_security_desc(proto_tree *tree, tvbuff_t *tvb, gint offset)
710 proto_tree_add_item(tree, hf_dplay_sd_size, tvb, offset, 4, TRUE); offset += 4;
711 proto_tree_add_item(tree, hf_dplay_sd_flags, tvb, offset, 4, TRUE); offset += 4;
712 proto_tree_add_item(tree, hf_dplay_sd_sspi, tvb, offset, 4, TRUE); offset += 4;
713 proto_tree_add_item(tree, hf_dplay_sd_capi, tvb, offset, 4, TRUE); offset += 4;
714 proto_tree_add_item(tree, hf_dplay_sd_capi_type, tvb, offset, 4, TRUE); offset += 4;
715 proto_tree_add_item(tree, hf_dplay_sd_enc_alg, tvb, offset, 4, TRUE); offset += 4;
719 static gint dissect_dplay_header(proto_tree *tree, tvbuff_t *tvb, gint offset)
721 guint32 mixed, size, token;
723 mixed = tvb_get_letohl(tvb, offset);
724 size = mixed & 0x000FFFFF;
725 token = (mixed & 0xFFF00000) >> 20;
727 proto_tree_add_uint(tree, hf_dplay_size, tvb, offset, 4, size);
728 proto_tree_add_uint(tree, hf_dplay_token, tvb, offset, 4, token);
730 offset = dissect_sockaddr_in(tree, tvb, offset);
731 proto_tree_add_item(tree, hf_dplay_play_str, tvb, offset, 4, TRUE); offset += 4;
732 proto_tree_add_item(tree, hf_dplay_command, tvb, offset, 2, TRUE); offset += 2;
733 proto_tree_add_item(tree, hf_dplay_proto_dialect, tvb, offset, 2, TRUE); offset += 2;
737 static gint dissect_type01_message(proto_tree *tree, tvbuff_t *tvb, gint offset)
741 offset = dissect_session_desc(tree, tvb, offset);
742 name_offset = tvb_get_letohl(tvb, offset);
743 proto_tree_add_item(tree, hf_dplay_type_01_name_offset, tvb, offset, 4, TRUE); offset += 4;
745 if (name_offset != 0) {
746 offset = display_unicode_string(tree, hf_dplay_type_01_game_name, tvb, offset);
751 static gint dissect_type02_message(proto_tree *tree, tvbuff_t *tvb, gint offset)
753 guint32 passwd_offset;
755 proto_item *flags_item = NULL;
756 proto_tree *flags_tree = NULL;
758 passwd_offset = tvb_get_letohl(tvb, offset + 16);
759 flags = tvb_get_letohl(tvb, offset + 20);
761 proto_tree_add_item(tree, hf_dplay_type_02_game_guid, tvb, offset, 16, FALSE); offset += 16;
762 proto_tree_add_item(tree, hf_dplay_type_02_password_offset, tvb, offset, 4, TRUE); offset += 4;
764 flags_item = proto_tree_add_item(tree, hf_dplay_type_02_flags, tvb, offset, 4, TRUE);
765 flags_tree = proto_item_add_subtree(flags_item, ett_dplay_type02_flags);
766 proto_tree_add_boolean(flags_tree, hf_enum_sess_flag_passwd, tvb, offset, 4, flags);
767 proto_tree_add_boolean(flags_tree, hf_enum_sess_flag_all, tvb, offset, 4, flags);
768 proto_tree_add_boolean(flags_tree, hf_enum_sess_flag_join, tvb, offset, 4, flags);
771 if (passwd_offset != 0) {
772 offset = display_unicode_string(tree, hf_dplay_type_02_password, tvb, offset);
777 static gint dissect_type05_message(proto_tree *tree, tvbuff_t *tvb, gint offset)
779 proto_item *flag_item;
780 proto_item *flag_tree;
783 flags = tvb_get_letohl(tvb, offset);
784 flag_item = proto_tree_add_item(tree, hf_dplay_type_05_flags, tvb, offset, 4, TRUE);
785 flag_tree = proto_item_add_subtree(flag_item, ett_dplay_type05_flags);
786 proto_tree_add_boolean(flag_tree, hf_dplay_type_05_secure, tvb, offset, 4, flags);
787 proto_tree_add_boolean(flag_tree, hf_dplay_type_05_unknown, tvb, offset, 4, flags);
788 proto_tree_add_boolean(flag_tree, hf_dplay_type_05_local, tvb, offset, 4, flags);
789 proto_tree_add_boolean(flag_tree, hf_dplay_type_05_name_server, tvb, offset, 4, flags);
790 proto_tree_add_boolean(flag_tree, hf_dplay_type_05_system_player, tvb, offset, 4, flags);
795 static gint dissect_type07_message(proto_tree *tree, tvbuff_t *tvb, gint offset)
797 guint32 sspi_offset, capi_offset;
799 proto_tree_add_item(tree, hf_dplay_type_07_dpid, tvb, offset, 4, FALSE); offset += 4;
800 offset = dissect_security_desc(tree, tvb, offset);
802 sspi_offset = tvb_get_letohl(tvb, offset);
803 proto_tree_add_item(tree, hf_dplay_type_07_sspi_offset, tvb, offset, 4, TRUE); offset += 4;
805 capi_offset = tvb_get_letohl(tvb, offset);
806 proto_tree_add_item(tree, hf_dplay_type_07_capi_offset, tvb, offset, 4, TRUE); offset += 4;
808 proto_tree_add_item(tree, hf_dplay_type_07_hresult, tvb, offset, 4, TRUE); offset += 4;
811 offset = display_unicode_string(tree, hf_dplay_type_07_sspi, tvb, offset);
815 offset = display_unicode_string(tree, hf_dplay_type_07_capi, tvb, offset);
820 static gint dissect_player_message(proto_tree *tree, tvbuff_t *tvb, gint offset)
824 proto_tree_add_item(tree, hf_dplay_multi_id_to, tvb, offset, 4, FALSE); offset += 4;
825 proto_tree_add_item(tree, hf_dplay_multi_player_id, tvb, offset, 4, FALSE); offset += 4;
826 proto_tree_add_item(tree, hf_dplay_multi_group_id, tvb, offset, 4, FALSE); offset += 4;
827 pp_ofs = tvb_get_letohl(tvb, offset);
828 proto_tree_add_item(tree, hf_dplay_multi_create_offset, tvb, offset, 4, TRUE); offset += 4;
829 proto_tree_add_item(tree, hf_dplay_multi_password_offset, tvb, offset, 4, TRUE); offset += 4;
831 offset = dissect_packed_player(tree, tvb, offset);
832 if (tvb_bytes_exist(tvb, offset, 2))
833 offset = display_unicode_string(tree, hf_dplay_multi_password, tvb, offset);
837 static gint dissect_type0f_message(proto_tree *tree, tvbuff_t *tvb, gint offset)
841 proto_tree_add_item(tree, hf_dplay_type_0f_id_to, tvb, offset, 4, FALSE); offset += 4;
842 proto_tree_add_item(tree, hf_dplay_type_0f_id, tvb, offset, 4, FALSE); offset += 4;
843 data_size = tvb_get_letohl(tvb, offset);
844 proto_tree_add_item(tree, hf_dplay_type_0f_data_size, tvb, offset, 4, TRUE); offset += 4;
845 proto_tree_add_item(tree, hf_dplay_type_0f_data_offset, tvb, offset, 4, TRUE); offset += 4;
846 proto_tree_add_item(tree, hf_dplay_type_0f_data, tvb, offset, data_size, FALSE);
852 static gint dissect_type13_message(proto_tree *tree, tvbuff_t *tvb, gint offset)
854 guint32 pp_ofs, pw_ofs;
856 proto_tree_add_item(tree, hf_dplay_type_13_id_to, tvb, offset, 4, FALSE); offset += 4;
857 proto_tree_add_item(tree, hf_dplay_type_13_player_id, tvb, offset, 4, FALSE); offset += 4;
858 proto_tree_add_item(tree, hf_dplay_type_13_group_id, tvb, offset, 4, FALSE); offset += 4;
859 pp_ofs = tvb_get_letohl(tvb, offset);
860 proto_tree_add_item(tree, hf_dplay_type_13_create_offset, tvb, offset, 4, TRUE); offset += 4;
861 pw_ofs = tvb_get_letohl(tvb, offset);
862 proto_tree_add_item(tree, hf_dplay_type_13_password_offset, tvb, offset, 4, TRUE); offset += 4;
864 offset = dissect_packed_player(tree, tvb, offset);
866 offset = display_unicode_string(tree, hf_dplay_type_13_password, tvb, offset);
867 proto_tree_add_item(tree, hf_dplay_type_13_tick_count, tvb, offset, 4, TRUE); offset += 4;
872 static gint dissect_type15_message(proto_tree *tree, tvbuff_t *tvb, gint offset)
874 guint16 second_message_type;
875 proto_item *enc_item = NULL;
876 proto_tree *enc_tree = NULL;
877 second_message_type = tvb_get_letohs(tvb, 72);
879 proto_tree_add_item(tree, hf_dplay_message_guid, tvb, offset, 16, FALSE); offset += 16;
880 proto_tree_add_item(tree, hf_dplay_type_15_packet_idx, tvb, offset, 4, TRUE); offset += 4;
881 proto_tree_add_item(tree, hf_dplay_type_15_data_size, tvb, offset, 4, TRUE); offset += 4;
882 proto_tree_add_item(tree, hf_dplay_type_15_offset, tvb, offset, 4, TRUE); offset += 4;
883 proto_tree_add_item(tree, hf_dplay_type_15_total_packets, tvb, offset, 4, TRUE); offset += 4;
884 proto_tree_add_item(tree, hf_dplay_type_15_msg_size, tvb, offset, 4, TRUE); offset += 4;
885 proto_tree_add_item(tree, hf_dplay_type_15_packet_offset, tvb, offset, 4, TRUE); offset += 4;
887 enc_item = proto_tree_add_text(tree, tvb, offset, -1, "DirectPlay encapsulated packet");
888 enc_tree = proto_item_add_subtree(enc_item, ett_dplay_enc_packet);
890 proto_tree_add_item(enc_tree, hf_dplay_play_str_2, tvb, offset, 4, FALSE); offset += 4;
891 proto_tree_add_item(enc_tree, hf_dplay_command_2, tvb, offset, 2, TRUE); offset += 2;
892 proto_tree_add_item(enc_tree, hf_dplay_proto_dialect_2, tvb, offset, 2, TRUE); offset += 2;
894 switch(second_message_type)
897 offset = dissect_type05_message(enc_tree, tvb, offset);
900 offset = dissect_type05_message(enc_tree, tvb, offset);
909 offset = dissect_player_message(enc_tree, tvb, offset);
912 offset = dissect_type13_message(enc_tree, tvb, offset);
915 offset = dissect_type1a_message(enc_tree, tvb, offset);
922 static gint dissect_ping_message(proto_tree *tree, tvbuff_t *tvb, gint offset)
924 proto_tree_add_item(tree, hf_dplay_ping_id_from, tvb, offset, 4, FALSE); offset += 4;
925 proto_tree_add_item(tree, hf_dplay_ping_tick_count, tvb, offset, 4, TRUE); offset += 4;
930 static gint dissect_type1a_message(proto_tree *tree, tvbuff_t *tvb, gint offset)
932 guint32 sn_ofs, pw_ofs;
934 proto_tree_add_item(tree, hf_dplay_type_1a_id_to, tvb, offset, 4, FALSE); offset += 4;
935 sn_ofs = tvb_get_letohl(tvb, offset);
936 proto_tree_add_item(tree, hf_dplay_type_1a_sess_name_ofs, tvb, offset, 4, TRUE); offset += 4;
937 pw_ofs = tvb_get_letohl(tvb, offset);
938 proto_tree_add_item(tree, hf_dplay_type_1a_password_ofs, tvb, offset, 4, TRUE); offset += 4;
939 offset = dissect_session_desc(tree, tvb, offset);
942 offset = display_unicode_string(tree, hf_dplay_type_1a_session_name, tvb, offset);
946 offset = display_unicode_string(tree, hf_dplay_type_1a_password, tvb, offset);
952 static gint dissect_type29_message(proto_tree *tree, tvbuff_t *tvb, gint offset)
954 guint32 password_offset = tvb_get_letohl(tvb, offset + 24);
955 gint player_count, group_count, shortcut_count;
958 player_count = tvb_get_letohl(tvb, offset);
959 proto_tree_add_item(tree, hf_dplay_type_29_player_count, tvb, offset, 4, TRUE); offset += 4;
960 group_count = tvb_get_letohl(tvb, offset);
961 proto_tree_add_item(tree, hf_dplay_type_29_group_count, tvb, offset, 4, TRUE); offset += 4;
962 proto_tree_add_item(tree, hf_dplay_type_29_packed_offset, tvb, offset, 4, TRUE); offset += 4;
963 shortcut_count = tvb_get_letohl(tvb, offset);
964 proto_tree_add_item(tree, hf_dplay_type_29_shortcut_count, tvb, offset, 4, TRUE); offset += 4;
965 proto_tree_add_item(tree, hf_dplay_type_29_description_offset, tvb, offset, 4, TRUE); offset += 4;
966 proto_tree_add_item(tree, hf_dplay_type_29_name_offset, tvb, offset, 4, TRUE); offset += 4;
967 proto_tree_add_item(tree, hf_dplay_type_29_password_offset, tvb, offset, 4, TRUE); offset += 4;
968 offset = dissect_session_desc(tree, tvb, offset);
969 offset = display_unicode_string(tree, hf_dplay_type_29_game_name, tvb, offset);
971 if (password_offset != 0) {
972 offset = display_unicode_string(tree, hf_dplay_type_29_password, tvb, offset);
975 for (i=0; i < player_count; ++i) {
976 proto_item *spp_item;
977 proto_tree *spp_tree;
979 spp_item = proto_tree_add_text(tree, tvb, offset, 0, "Player %d", i);
980 spp_tree = proto_item_add_subtree(spp_item, ett_dplay_type29_spp);
981 offset = dissect_dplay_super_packed_player(spp_tree, tvb, offset);
984 for (i=0; i < group_count; ++i) {
985 proto_item *spp_item;
986 proto_tree *spp_tree;
988 spp_item = proto_tree_add_text(tree, tvb, offset, 0, "Group %d", i);
989 spp_tree = proto_item_add_subtree(spp_item, ett_dplay_type29_spp);
990 offset = dissect_dplay_super_packed_player(spp_tree, tvb, offset);
993 for (i=0; i < shortcut_count; ++i) {
994 proto_item *spp_item;
995 proto_tree *spp_tree;
997 spp_item = proto_tree_add_text(tree, tvb, offset, 0, "Shortcut %d", i);
998 spp_tree = proto_item_add_subtree(spp_item, ett_dplay_type29_spp);
999 offset = dissect_dplay_super_packed_player(spp_tree, tvb, offset);
1005 static gint dissect_type2f_message(proto_tree *tree, tvbuff_t *tvb, gint offset)
1007 proto_tree_add_item(tree, hf_dplay_type_2f_dpid, tvb, offset, 4, FALSE); offset += 4;
1011 static void dissect_dplay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1013 guint16 message_type;
1014 guint16 second_message_type = -1;
1015 guint16 proto_version;
1016 guint16 packet_size;
1018 guint8 play_id[] = {'p','l','a','y'};
1020 packet_size = tvb_get_letohs(tvb, 0);
1021 dplay_id = tvb_get_letohl(tvb, 20);
1022 message_type = tvb_get_letohs(tvb, 24);
1023 proto_version = tvb_get_letohs(tvb, 26);
1025 if(memcmp(play_id, (guint8 *)&dplay_id, 4) != 0)
1027 if(check_col(pinfo->cinfo, COL_PROTOCOL))
1028 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DPLAY");
1029 /* Clear out stuff in the info column */
1030 if(check_col(pinfo->cinfo,COL_INFO))
1031 col_clear(pinfo->cinfo,COL_INFO);
1032 if(check_col(pinfo->cinfo,COL_INFO))
1033 col_add_fstr(pinfo->cinfo,COL_INFO, "DPlay data packet");
1037 if(message_type == 0x0015)
1039 second_message_type = tvb_get_letohs(tvb, 72);
1042 if(check_col(pinfo->cinfo, COL_PROTOCOL))
1043 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DPLAY");
1044 /* Clear out stuff in the info column */
1045 if(check_col(pinfo->cinfo,COL_INFO))
1047 col_clear(pinfo->cinfo,COL_INFO);
1050 if(check_col(pinfo->cinfo,COL_INFO))
1052 if(message_type == 0x0015)
1053 col_add_fstr(pinfo->cinfo,COL_INFO, "%s: %s, holding a %s",
1054 val_to_str(proto_version, dplay_proto_dialect_val, "Unknown (0x%04x)"),
1055 val_to_str(message_type, dplay_command_val, "Unknown (0x%04x)"),
1056 val_to_str(second_message_type, dplay_command_val, "Unknown (0x%04x)"));
1058 col_add_fstr(pinfo->cinfo,COL_INFO, "%s: %s",
1059 val_to_str(proto_version, dplay_proto_dialect_val, "Unknown (0x%04x)"),
1060 val_to_str(message_type, dplay_command_val, "Unknown (0x%04x)"));
1065 proto_item *dplay_item = NULL;
1066 proto_item *header_item = NULL;
1067 proto_item *data_item = NULL;
1068 proto_tree *dplay_tree = NULL;
1069 proto_tree *dplay_header = NULL;
1070 proto_tree *dplay_data = NULL;
1073 dplay_item = proto_tree_add_item(tree, proto_dplay, tvb, 0, -1, FALSE);
1074 dplay_tree = proto_item_add_subtree(dplay_item, ett_dplay);
1075 header_item = proto_tree_add_text(dplay_tree, tvb, offset, DPLAY_HEADER_OFFSET, "DirectPlay header");
1076 dplay_header = proto_item_add_subtree(header_item, ett_dplay_header);
1078 offset = dissect_dplay_header(dplay_header, tvb, offset);
1080 /* Special handling for empty type 0x0004 packets */
1081 if(message_type == 0x0004)
1084 data_item = proto_tree_add_text(dplay_tree, tvb, offset, -1, "DirectPlay data");
1085 dplay_data = proto_item_add_subtree(data_item, ett_dplay_data);
1087 switch(message_type)
1090 offset = dissect_type01_message(dplay_data, tvb, offset);
1093 offset = dissect_type02_message(dplay_data, tvb, offset);
1096 /* We should not get here. */
1099 offset = dissect_type05_message(dplay_data, tvb, offset);
1102 offset = dissect_type07_message(dplay_data, tvb, offset);
1106 /* type 0a doesn't have a dplay header and is not handled here */
1113 offset = dissect_player_message(dplay_data, tvb, offset);
1116 offset = dissect_type0f_message(dplay_data, tvb, offset);
1119 offset = dissect_type13_message(dplay_data, tvb, offset);
1122 offset = dissect_type15_message(dplay_data, tvb, offset);
1126 offset = dissect_ping_message(dplay_data, tvb, offset);
1129 offset = dissect_type1a_message(dplay_data, tvb, offset);
1132 offset = dissect_type29_message(dplay_data, tvb, offset);
1135 offset = dissect_type2f_message(dplay_data, tvb, offset);
1142 static void dissect_dplay_player_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1144 guint32 mixed, size, token;
1146 if(check_col(pinfo->cinfo, COL_PROTOCOL))
1147 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DPLAY");
1148 /* Clear out stuff in the info column */
1149 if(check_col(pinfo->cinfo,COL_INFO))
1150 col_clear(pinfo->cinfo,COL_INFO);
1151 if(check_col(pinfo->cinfo,COL_INFO))
1152 col_add_fstr(pinfo->cinfo,COL_INFO, "DPlay player to player message");
1156 proto_item *dplay_item = NULL;
1157 proto_item *data_item = NULL;
1158 proto_tree *dplay_tree = NULL;
1159 proto_tree *data_tree = NULL;
1162 dplay_item = proto_tree_add_item(tree, proto_dplay, tvb, offset, -1, FALSE);
1163 dplay_tree = proto_item_add_subtree(dplay_item, ett_dplay);
1164 data_item = proto_tree_add_text(dplay_tree, tvb, offset, -1, "Message content");
1165 data_tree = proto_item_add_subtree(data_item, ett_dplay_data);
1166 mixed = tvb_get_letohl(tvb, offset);
1167 size = mixed & 0x000FFFFF;
1168 token = (mixed & 0xFFF00000) >> 20;
1170 proto_tree_add_uint(data_tree, hf_dplay_size, tvb, offset, 4, size);
1171 proto_tree_add_uint(data_tree, hf_dplay_token, tvb, offset, 4, token);
1173 offset = dissect_sockaddr_in(data_tree, tvb, offset);
1174 /* Now there's two dplay IDs iff the session desc does not have the
1175 * "short player message" flag set */
1176 proto_tree_add_item(data_tree, hf_dplay_player_msg, tvb, offset, -1, FALSE);
1180 static gboolean heur_dissect_dplay(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1182 guint8 signature[] = {'p','l','a','y'};
1183 guint32 dplay_id, token;
1185 if(!tvb_bytes_exist(tvb, 0, 24))
1188 dplay_id = tvb_get_letohl(tvb, 20);
1189 if( memcmp(signature, (guint8 *)&dplay_id, 4) == 0) {
1190 dissect_dplay(tvb, pinfo, tree);
1194 /* There is a player to player message that does not contain "play" */
1195 token = tvb_get_letohl(tvb, 0);
1196 token = (token & 0xfff00000) >> 20;
1197 if (token == 0xfab || token == 0xbab || token == 0xcab) {
1198 /* Check the s_addr_in structure */
1199 if (tvb_get_letohs(tvb, 4) == WINSOCK_AF_INET) {
1201 for (offset = 12; offset <= 20; offset++)
1202 if (tvb_get_guint8(tvb, offset) != 0)
1205 dissect_dplay_player_msg(tvb, pinfo, tree);
1213 void proto_register_dplay(void)
1215 static hf_register_info hf [] = {
1216 /* Common data fields */
1218 { "DirectPlay package size", "dplay.size", FT_UINT32, BASE_DEC,
1219 NULL, 0x0, "", HFILL}},
1221 { "DirectPlay token", "dplay.token", FT_UINT32, BASE_HEX,
1222 VALS(dplay_token_val), 0x0, "", HFILL}},
1223 { &hf_dplay_saddr_af,
1224 { "DirectPlay s_addr_in address family", "dplay.saddr.af", FT_UINT16, BASE_HEX,
1225 VALS(dplay_af_val), 0x0, "", HFILL}},
1226 { &hf_dplay_saddr_port,
1227 { "DirectPlay s_addr_in port", "dplay.saddr.port", FT_UINT16, BASE_DEC,
1228 NULL, 0x0, "", HFILL}},
1229 { &hf_dplay_saddr_ip,
1230 { "DirectPlay s_addr_in ip address", "dplay.saddr.ip", FT_IPv4, BASE_NONE,
1231 NULL, 0x0, "", HFILL}},
1232 { &hf_dplay_saddr_padding,
1233 { "DirectPlay s_addr_in null padding", "dplay.saddr.padding", FT_BYTES, BASE_NONE,
1234 NULL, 0x0, "", HFILL}},
1235 { &hf_dplay_play_str,
1236 { "DirectPlay action string", "dplay.dplay_str", FT_STRING, BASE_NONE,
1237 NULL, 0x0, "", HFILL}},
1238 { &hf_dplay_command,
1239 { "DirectPlay command", "dplay.command", FT_UINT16, BASE_HEX,
1240 VALS(dplay_command_val), 0x0, "", HFILL}},
1241 { &hf_dplay_proto_dialect,
1242 { "DirectPlay dialect version", "dplay.dialect.version", FT_UINT16, BASE_HEX,
1243 VALS(dplay_proto_dialect_val), 0x0, "", HFILL}},
1244 { &hf_dplay_play_str_2,
1245 { "DirectPlay second action string", "dplay.dplay_str_2", FT_STRING, BASE_NONE,
1246 NULL, 0x0, "", HFILL}},
1247 { &hf_dplay_command_2,
1248 { "DirectPlay second command", "dplay.command_2", FT_UINT16, BASE_HEX,
1249 VALS(dplay_command_val), 0x0, "", HFILL}},
1250 { &hf_dplay_proto_dialect_2,
1251 { "DirectPlay second dialect version", "dplay.dialect.version_2", FT_UINT16, BASE_HEX,
1252 VALS(dplay_proto_dialect_val), 0x0, "", HFILL}},
1253 { &hf_dplay_player_msg,
1254 { "DirectPlay Player to Player message", "dplay.player_msg", FT_BYTES, BASE_HEX,
1255 NULL, 0x0, "", HFILL}},
1257 /* Session Desc structure fields */
1258 { &hf_dplay_sess_desc_flags,
1259 { "DirectPlay session desc flags", "dplay.flags", FT_UINT32, BASE_HEX,
1260 NULL, 0x0, "", HFILL}},
1261 { &hf_dplay_flags_no_create_players,
1262 { "no create players flag", "dplay.flags.no_create_players", FT_BOOLEAN, 32,
1263 TFS(&tfs_dplay_flag), DPLAY_FLAG_NO_CREATE_PLAYERS, "No Create Players", HFILL}},
1264 { &hf_dplay_flags_0002,
1265 { "unused", "dplay.flags.unused", FT_BOOLEAN, 32,
1266 TFS(&tfs_dplay_flag), DPLAY_FLAG_0002, "Unused", HFILL}},
1267 { &hf_dplay_flags_migrate_host,
1268 { "migrate host flag", "dplay.flags.migrate_host", FT_BOOLEAN, 32,
1269 TFS(&tfs_dplay_flag), DPLAY_FLAG_MIGRATE_HOST, "Migrate Host", HFILL}},
1270 { &hf_dplay_flags_short_player_msg,
1271 { "short player message", "dplay.flags.short_player_msg", FT_BOOLEAN, 32,
1272 TFS(&tfs_dplay_flag), DPLAY_FLAG_SHORT_PLAYER_MSG, "Short Player Msg", HFILL}},
1273 { &hf_dplay_flags_ignored,
1274 { "ignored", "dplay.flags.ignored", FT_BOOLEAN, 32,
1275 TFS(&tfs_dplay_flag), DPLAY_FLAG_IGNORED, "Ignored", HFILL}},
1276 { &hf_dplay_flags_can_join,
1277 { "can join", "dplay.flags.can_join", FT_BOOLEAN, 32,
1278 TFS(&tfs_dplay_flag), DPLAY_FLAG_CAN_JOIN, "Can Join", HFILL}},
1279 { &hf_dplay_flags_use_ping,
1280 { "use ping", "dplay.flags.use_ping", FT_BOOLEAN, 32,
1281 TFS(&tfs_dplay_flag), DPLAY_FLAG_USE_PING, "Use Ping", HFILL}},
1282 { &hf_dplay_flags_no_player_updates,
1283 { "no player updates", "dplay.flags.no_player_updates", FT_BOOLEAN, 32,
1284 TFS(&tfs_dplay_flag), DPLAY_FLAG_NO_P_UPD, "No Player Updates", HFILL}},
1285 { &hf_dplay_flags_use_auth,
1286 { "use authentication", "dplay.flags.use_auth", FT_BOOLEAN, 32,
1287 TFS(&tfs_dplay_flag), DPLAY_FLAG_USE_AUTH, "Use Auth", HFILL}},
1288 { &hf_dplay_flags_private_session,
1289 { "private session", "dplay.flags.priv_sess", FT_BOOLEAN, 32,
1290 TFS(&tfs_dplay_flag), DPLAY_FLAG_PRIV_SESS, "Priv Session", HFILL}},
1291 { &hf_dplay_flags_password_req,
1292 { "password required", "dplay.flags.pass_req", FT_BOOLEAN, 32,
1293 TFS(&tfs_dplay_flag), DPLAY_FLAG_PASS_REQ, "Pass Req", HFILL}},
1294 { &hf_dplay_flags_route,
1295 { "route via game host", "dplay.flags.route", FT_BOOLEAN, 32,
1296 TFS(&tfs_dplay_flag), DPLAY_FLAG_ROUTE, "Route", HFILL}},
1297 { &hf_dplay_flags_server_player_only,
1298 { "get server player only", "dplay.flags.srv_p_only", FT_BOOLEAN, 32,
1299 TFS(&tfs_dplay_flag), DPLAY_FLAG_SRV_ONLY, "Svr Player Only", HFILL}},
1300 { &hf_dplay_flags_reliable,
1301 { "use reliable protocol", "dplay.flags.reliable", FT_BOOLEAN, 32,
1302 TFS(&tfs_dplay_flag), DPLAY_FLAG_RELIABLE, "Reliable", HFILL}},
1303 { &hf_dplay_flags_preserve_order,
1304 { "preserve order", "dplay.flags.order", FT_BOOLEAN, 32,
1305 TFS(&tfs_dplay_flag), DPLAY_FLAG_ORDER, "Order", HFILL}},
1306 { &hf_dplay_flags_optimize_latency,
1307 { "optimize for latency", "dplay.flags.opt_latency", FT_BOOLEAN, 32,
1308 TFS(&tfs_dplay_flag), DPLAY_FLAG_OPT_LAT, "Opt Latency", HFILL}},
1309 { &hf_dplay_flags_acqire_voice,
1310 { "acquire voice", "dplay.flags.acq_voice", FT_BOOLEAN, 32,
1311 TFS(&tfs_dplay_flag), DPLAY_FLAG_ACQ_VOICE, "Acq Voice", HFILL}},
1312 { &hf_dplay_flags_no_sess_desc_changes,
1313 { "no session desc changes", "dplay.flags.no_sess_desc", FT_BOOLEAN, 32,
1314 TFS(&tfs_dplay_flag), DPLAY_FLAG_NO_SESS_DESC_CHANGES, "No Sess Desc Changes", HFILL}},
1315 { &hf_dplay_instance_guid,
1316 { "DirectPlay instance guid", "dplay.instance.guid", FT_GUID, BASE_NONE,
1317 NULL, 0x0, "", HFILL}},
1318 { &hf_dplay_game_guid,
1319 { "DirectPlay game GUID", "dplay.game.guid", FT_GUID, BASE_NONE,
1320 NULL, 0x0, "", HFILL}},
1321 { &hf_dplay_sess_desc_length,
1322 { "DirectPlay session desc length", "dplay.sess_desc.length", FT_UINT32, BASE_DEC,
1323 NULL, 0x0, "", HFILL}},
1324 { &hf_dplay_max_players,
1325 { "DirectPlay max players ", "dplay.sess_desc.max_players", FT_UINT32, BASE_DEC,
1326 NULL, 0x0, "", HFILL}},
1327 { &hf_dplay_curr_players,
1328 { "DirectPlay current players", "dplay.sess_desc.curr_players", FT_UINT32, BASE_DEC,
1329 NULL, 0x0, "", HFILL}},
1330 { &hf_dplay_sess_name_ptr,
1331 { "Session description name pointer placeholder", "dplay.sess_desc.name_ptr", FT_BYTES, BASE_HEX,
1332 NULL, 0x0, "", HFILL}},
1333 { &hf_dplay_passwd_ptr,
1334 { "Session description password pointer placeholder", "dplay.sess_desc.pw_ptr", FT_BYTES, BASE_HEX,
1335 NULL, 0x0, "", HFILL}},
1336 { &hf_dplay_sess_desc_reserved_1,
1337 { "Session description reserved 1", "dplay.sess_desc.res_1", FT_BYTES, BASE_HEX,
1338 NULL, 0x0, "", HFILL}},
1339 { &hf_dplay_sess_desc_reserved_2,
1340 { "Session description reserved 2", "dplay.sess_desc.res_2", FT_BYTES, BASE_HEX,
1341 NULL, 0x0, "", HFILL}},
1342 { &hf_dplay_sess_desc_user_1,
1343 { "Session description user defined 1", "dplay.sess_desc.user_1", FT_BYTES, BASE_HEX,
1344 NULL, 0x0, "", HFILL}},
1345 { &hf_dplay_sess_desc_user_2,
1346 { "Session description user defined 2", "dplay.sess_desc.user_2", FT_BYTES, BASE_HEX,
1347 NULL, 0x0, "", HFILL}},
1348 { &hf_dplay_sess_desc_user_3,
1349 { "Session description user defined 3", "dplay.sess_desc.user_3", FT_BYTES, BASE_HEX,
1350 NULL, 0x0, "", HFILL}},
1351 { &hf_dplay_sess_desc_user_4,
1352 { "Session description user defined 4", "dplay.sess_desc.user_4", FT_BYTES, BASE_HEX,
1353 NULL, 0x0, "", HFILL}},
1355 /* PackedPlayer structure fields */
1356 { &hf_dplay_pp_size,
1357 { "PackedPlayer size", "dplay.pp.size", FT_UINT32, BASE_DEC,
1358 NULL, 0x0, "", HFILL}},
1359 { &hf_dplay_pp_flags,
1360 { "PackedPlayer flags", "dplay.pp.flags", FT_UINT32, BASE_HEX,
1361 NULL, 0x0, "", HFILL}},
1362 { &hf_dplay_pp_flag_sysplayer,
1363 { "is system player", "dplay.pp.flags.sysplayer", FT_BOOLEAN, 32,
1364 TFS(&tfs_dplay_flag), DPLAY_PP_FLAG_SYSPLAYER, "", HFILL}},
1365 { &hf_dplay_pp_flag_nameserver,
1366 { "is name server", "dplay.pp.flags.nameserver", FT_BOOLEAN, 32,
1367 TFS(&tfs_dplay_flag), DPLAY_PP_FLAG_NAMESERVER, "", HFILL}},
1368 { &hf_dplay_pp_flag_in_group,
1369 { "in group", "dplay.pp.flags.in_group", FT_BOOLEAN, 32,
1370 TFS(&tfs_dplay_flag), DPLAY_PP_FLAG_IN_GROUP, "", HFILL}},
1371 { &hf_dplay_pp_flag_sending,
1372 { "sending player on local machine", "dplay.pp.flags.sending", FT_BOOLEAN, 32,
1373 TFS(&tfs_dplay_flag), DPLAY_SPP_FLAG_SENDING, "", HFILL}},
1375 { "PackedPlayer ID", "dplay.pp.id", FT_BYTES, BASE_HEX,
1376 NULL, 0x0, "", HFILL}},
1377 { &hf_dplay_pp_short_name_len,
1378 { "PackedPlayer short name length", "dplay.pp.short_name_len", FT_UINT32, BASE_HEX,
1379 NULL, 0x0, "", HFILL}},
1380 { &hf_dplay_pp_long_name_len,
1381 { "PackedPlayer long name length", "dplay.pp.long_name_len", FT_UINT32, BASE_HEX,
1382 NULL, 0x0, "", HFILL}},
1383 { &hf_dplay_pp_sp_data_size,
1384 { "PackedPlayer service provider data size", "dplay.pp.sp_data_size", FT_UINT32, BASE_HEX,
1385 NULL, 0x0, "", HFILL}},
1386 { &hf_dplay_pp_player_data_size,
1387 { "PackedPlayer player data size", "dplay.pp.player_data_size", FT_UINT32, BASE_HEX,
1388 NULL, 0x0, "", HFILL}},
1389 { &hf_dplay_pp_num_players,
1390 { "PackedPlayer player count", "dplay.pp.player_count", FT_UINT32, BASE_HEX,
1391 NULL, 0x0, "", HFILL}},
1392 { &hf_dplay_pp_system_player,
1393 { "PackedPlayer system player ID", "dplay.pp.sysplayer_id", FT_BYTES, BASE_HEX,
1394 NULL, 0x0, "", HFILL}},
1395 { &hf_dplay_pp_fixed_size,
1396 { "PackedPlayer fixed size", "dplay.pp.fixed_size", FT_UINT32, BASE_DEC,
1397 NULL, 0x0, "", HFILL}},
1398 { &hf_dplay_pp_dialect,
1399 { "PackedPlayer dialect version", "dplay.pp.dialect", FT_UINT32, BASE_HEX,
1400 VALS(&dplay_proto_dialect_val), 0x0, "", HFILL}},
1401 { &hf_dplay_pp_unknown_1,
1402 { "PackedPlayer unknown 1", "dplay.pp.unknown_1", FT_BYTES, BASE_HEX,
1403 NULL, 0x0, "", HFILL}},
1404 { &hf_dplay_pp_short_name,
1405 { "PackedPlayer short name", "dplay.pp.short_name", FT_STRING, BASE_NONE,
1406 NULL, 0x0, "", HFILL}},
1407 { &hf_dplay_pp_long_name,
1408 { "PackedPlayer long name", "dplay.pp.short_name", FT_STRING, BASE_NONE,
1409 NULL, 0x0, "", HFILL}},
1410 { &hf_dplay_pp_player_data,
1411 { "PackedPlayer player data", "dplay.pp.player_data", FT_BYTES, BASE_HEX,
1412 NULL, 0x0, "", HFILL}},
1413 { &hf_dplay_pp_sp_data,
1414 { "PackedPlayer service provider data", "dplay.pp.sp_data", FT_BYTES, BASE_HEX,
1415 NULL, 0x0, "", HFILL}},
1416 { &hf_dplay_pp_player_id,
1417 { "PackedPlayer player ID", "dplay.pp.player_id", FT_BYTES, BASE_HEX,
1418 NULL, 0x0, "", HFILL}},
1419 { &hf_dplay_pp_parent_id,
1420 { "PackedPlayer parent ID", "dplay.pp.parent_id", FT_BYTES, BASE_HEX,
1421 NULL, 0x0, "", HFILL}},
1423 /* SuperPackedPlayer structure fields */
1424 { &hf_dplay_spp_size,
1425 { "SuperPackedPlayer size", "dplay.spp.size", FT_UINT32, BASE_DEC,
1426 NULL, 0x0, "", HFILL}},
1427 { &hf_dplay_spp_flags,
1428 { "SuperPackedPlayer flags", "dplay.spp.flags", FT_UINT32, BASE_HEX,
1429 NULL, 0x0, "", HFILL}},
1430 { &hf_dplay_spp_flags_sysplayer,
1431 { "is system player", "dplay.spp.flags.sysplayer", FT_BOOLEAN, 32,
1432 TFS(&tfs_dplay_flag), DPLAY_SPP_FLAG_SYSPLAYER, "", HFILL}},
1433 { &hf_dplay_spp_flags_nameserver,
1434 { "is name server", "dplay.spp.flags.nameserver", FT_BOOLEAN, 32,
1435 TFS(&tfs_dplay_flag), DPLAY_SPP_FLAG_NAMESERVER, "", HFILL}},
1436 { &hf_dplay_spp_flags_in_group,
1437 { "in group", "dplay.spp.flags.in_group", FT_BOOLEAN, 32,
1438 TFS(&tfs_dplay_flag), DPLAY_SPP_FLAG_IN_GROUP, "", HFILL}},
1439 { &hf_dplay_spp_flags_sending,
1440 { "sending player on local machine", "dplay.spp.flags.sending", FT_BOOLEAN, 32,
1441 TFS(&tfs_dplay_flag), DPLAY_SPP_FLAG_SENDING, "", HFILL}},
1443 { "SuperPackedPlayer ID", "dplay.spp.id", FT_BYTES, BASE_HEX,
1444 NULL, 0x0, "", HFILL}},
1445 { &hf_dplay_spp_player_info_mask,
1446 { "SuperPackedPlayer player info mask", "dplay.spp.pim", FT_UINT32, BASE_HEX,
1447 NULL, 0x0, "", HFILL}},
1448 { &hf_dplay_spp_have_short_name,
1449 { "SuperPackedPlayer have short name", "dplay.spp.pim.short_name", FT_UINT32, BASE_HEX,
1450 VALS(yes_no_val), 0x0, "", HFILL}},
1451 { &hf_dplay_spp_have_long_name,
1452 { "SuperPackedPlayer have long name", "dplay.spp.pim.long_name", FT_UINT32, BASE_HEX,
1453 VALS(yes_no_val), 0x0, "", HFILL}},
1454 { &hf_dplay_spp_sp_length_type,
1455 { "SuperPackedPlayer service provider length info", "dplay.spp.pim.sp_length", FT_UINT32, BASE_HEX,
1456 VALS(dplay_spp_length_val), 0x0, "", HFILL}},
1457 { &hf_dplay_spp_pd_length_type,
1458 { "SuperPackedPlayer player data length info", "dplay.spp.pim.pd_length", FT_UINT32, BASE_HEX,
1459 VALS(dplay_spp_length_val), 0x0, "", HFILL}},
1460 { &hf_dplay_spp_player_count_type,
1461 { "SuperPackedPlayer player count info", "dplay.spp.pim.player_count", FT_UINT32, BASE_HEX,
1462 VALS(dplay_spp_length_val), 0x0, "", HFILL}},
1463 { &hf_dplay_spp_have_parent_id,
1464 { "SuperPackedPlayer have parent ID", "dplay.spp.pim.parent_id", FT_UINT32, BASE_HEX,
1465 VALS(yes_no_val), 0x0, "", HFILL}},
1466 { &hf_dplay_spp_shortcut_count_type,
1467 { "SuperPackedPlayer shortcut count info", "dplay.spp.pim.shortcut_count", FT_UINT32, BASE_HEX,
1468 VALS(dplay_spp_length_val), 0x0, "", HFILL}},
1469 { &hf_dplay_spp_dialect,
1470 { "SuperPackedPlayer dialect version", "dplay.spp.dialect", FT_UINT32, BASE_HEX,
1471 VALS(&dplay_proto_dialect_val), 0x0, "", HFILL}},
1472 { &hf_dplay_spp_sys_player_id,
1473 { "SuperPackedPlayer system player ID", "dplay.spp.sysplayer_id", FT_BYTES, BASE_HEX,
1474 NULL, 0x0, "", HFILL}},
1475 { &hf_dplay_spp_short_name,
1476 { "SuperPackedPlayer short name", "dplay.spp.short_name", FT_STRING, BASE_NONE,
1477 NULL, 0x0, "", HFILL}},
1478 { &hf_dplay_spp_long_name,
1479 { "SuperPackedPlayer long name", "dplay.spp.short_name", FT_STRING, BASE_NONE,
1480 NULL, 0x0, "", HFILL}},
1481 { &hf_dplay_spp_player_data_length,
1482 { "SuperPackedPlayer player data length", "dplay.spp.pd_length", FT_UINT32, BASE_HEX,
1483 NULL, 0x0, "", HFILL}},
1484 { &hf_dplay_spp_player_data,
1485 { "SuperPackedPlayer player data", "dplay.spp.player_data", FT_BYTES, BASE_HEX,
1486 NULL, 0x0, "", HFILL}},
1487 { &hf_dplay_spp_sp_data_length,
1488 { "SuperPackedPlayer service provider data length", "dplay.spp.sp_data_length", FT_UINT32, BASE_HEX,
1489 NULL, 0x0, "", HFILL}},
1490 { &hf_dplay_spp_sp_data,
1491 { "SuperPackedPlayer service provider data", "dplay.spp.sp_data", FT_BYTES, BASE_HEX,
1492 NULL, 0x0, "", HFILL}},
1493 { &hf_dplay_spp_player_count,
1494 { "SuperPackedPlayer player count", "dplay.spp.player_count", FT_UINT32, BASE_HEX,
1495 NULL, 0x0, "", HFILL}},
1496 { &hf_dplay_spp_player_id,
1497 { "SuperPackedPlayer player ID", "dplay.spp.player_id", FT_BYTES, BASE_HEX,
1498 NULL, 0x0, "", HFILL}},
1499 { &hf_dplay_spp_parent_id,
1500 { "SuperPackedPlayer parent ID", "dplay.spp.parent_id", FT_BYTES, BASE_HEX,
1501 NULL, 0x0, "", HFILL}},
1502 { &hf_dplay_spp_shortcut_count,
1503 { "SuperPackedPlayer shortcut count", "dplay.spp.shortcut_count", FT_UINT32, BASE_HEX,
1504 NULL, 0x0, "", HFILL}},
1505 { &hf_dplay_spp_shortcut_id,
1506 { "SuperPackedPlayer shortcut ID", "dplay.spp.shortcut_id", FT_BYTES, BASE_HEX,
1507 NULL, 0x0, "", HFILL}},
1509 /* Data fields for SecDesc struct */
1510 { &hf_dplay_sd_size,
1511 { "SecDesc struct size", "dplay.sd.size", FT_UINT32, BASE_DEC,
1512 NULL, 0x0, "", HFILL}},
1513 { &hf_dplay_sd_flags,
1514 { "SecDesc flags", "dplay.sd.flags", FT_UINT32, BASE_HEX,
1515 NULL, 0x0, "", HFILL}},
1516 { &hf_dplay_sd_sspi,
1517 { "SecDesc SSPI provider ptr", "dplay.sd.sspi", FT_BYTES, BASE_HEX,
1518 NULL, 0x0, "", HFILL}},
1519 { &hf_dplay_sd_capi,
1520 { "SecDesc CAPI provider ptr", "dplay.sd.capi", FT_BYTES, BASE_HEX,
1521 NULL, 0x0, "", HFILL}},
1522 { &hf_dplay_sd_capi_type,
1523 { "SecDesc CAPI provider type", "dplay.sd.capi_type", FT_UINT32, BASE_HEX,
1524 NULL, 0x0, "", HFILL}},
1525 { &hf_dplay_sd_enc_alg,
1526 { "SecDesc encryption algorithm" , "dplay.sd.enc_alg", FT_UINT32, BASE_HEX,
1527 VALS(dplay_enc_alg_val), 0x0, "", HFILL}},
1529 /* Data fields for message type 0x0001 */
1530 { &hf_dplay_type_01_name_offset,
1531 { "Enum Session Reply name offset", "dplay.type_01.name_offs", FT_UINT32, BASE_DEC,
1532 NULL, 0x0, "", HFILL}},
1533 { &hf_dplay_type_01_game_name,
1534 { "Enum Session Reply game name", "dplay.type_01.game_name", FT_STRING, BASE_NONE,
1535 NULL, 0x0, "", HFILL}},
1537 /* Data fields for message type 0x0002 */
1538 { &hf_dplay_type_02_game_guid,
1539 { "DirectPlay game GUID", "dplay.type02.game.guid", FT_GUID, BASE_NONE,
1540 NULL, 0x0, "", HFILL}},
1541 { &hf_dplay_type_02_password_offset,
1542 { "Enum Sessions password offset", "dplay.type02.password_offset", FT_UINT32, BASE_DEC,
1543 NULL, 0x0, "", HFILL}},
1544 { &hf_dplay_type_02_flags,
1545 { "Enum Session flags", "dplay.type02.flags", FT_UINT32, BASE_HEX,
1546 NULL, 0x0, "", HFILL}},
1547 { &hf_dplay_type_02_password,
1548 { "Session password", "dplay.type02.password", FT_STRING, BASE_NONE,
1549 NULL, 0x0, "", HFILL}},
1550 { &hf_enum_sess_flag_join,
1551 { "Enumerate joinable sessions", "dplay.type02.joinable", FT_BOOLEAN, 32,
1552 TFS(&tfs_dplay_flag), DPLAY_ENUM_SESS_FLAG_JOIN, "Joinable", HFILL}},
1553 { &hf_enum_sess_flag_all,
1554 { "Enumerate all sessions", "dplay.type02.all", FT_BOOLEAN, 32,
1555 TFS(&tfs_dplay_flag), DPLAY_ENUM_SESS_FLAG_ALL, "All", HFILL}},
1556 { &hf_enum_sess_flag_passwd,
1557 { "Enumerate sessions requiring a password", "dplay.type02.pw_req", FT_BOOLEAN, 32,
1558 TFS(&tfs_dplay_flag), DPLAY_ENUM_SESS_FLAG_PASSWD, "Password", HFILL}},
1560 /* Data fields for message type 0x0005 */
1561 { &hf_dplay_type_05_flags,
1562 { "Player ID request flags", "dplay.type_05.flags", FT_UINT32, BASE_HEX,
1563 NULL, 0x0, "", HFILL}},
1564 { &hf_dplay_type_05_system_player,
1565 { "is system player", "dplay.type_05.flags.sys_player", FT_BOOLEAN, 32,
1566 TFS(&tfs_dplay_flag), DPLAY_TYPE05_FLAG_SYSPLAYER, "", HFILL}},
1567 { &hf_dplay_type_05_name_server,
1568 { "is name server", "dplay.type_05.flags.name_server", FT_BOOLEAN, 32,
1569 TFS(&tfs_dplay_flag), DPLAY_TYPE05_FLAG_NAMESERVER, "", HFILL}},
1570 { &hf_dplay_type_05_local,
1571 { "is local player", "dplay.type_05.flags.local", FT_BOOLEAN, 32,
1572 TFS(&tfs_dplay_flag), DPLAY_TYPE05_FLAG_LOCAL, "", HFILL}},
1573 { &hf_dplay_type_05_unknown,
1574 { "unknown", "dplay.type_05.flags.unknown", FT_BOOLEAN, 32,
1575 TFS(&tfs_dplay_flag), DPLAY_TYPE05_FLAG_UNKNOWN, "", HFILL}},
1576 { &hf_dplay_type_05_secure,
1577 { "is secure session", "dplay.type_05.flags.secure", FT_BOOLEAN, 32,
1578 TFS(&tfs_dplay_flag), DPLAY_TYPE05_FLAG_SECURE, "", HFILL}},
1580 /* Data fields for message type 0x0007 */
1581 { &hf_dplay_type_07_dpid,
1582 { "DirectPlay ID", "dplay.type_07.dpid", FT_BYTES, BASE_HEX,
1583 NULL, 0x0, "", HFILL}},
1584 { &hf_dplay_type_07_sspi_offset,
1585 { "SSPI provider offset", "dplay.type_07.sspi_offset", FT_UINT32, BASE_DEC,
1586 NULL, 0x0, "", HFILL}},
1587 { &hf_dplay_type_07_capi_offset,
1588 { "CAPI provider offset", "dplay.type_07.capi_offset", FT_UINT32, BASE_DEC,
1589 NULL, 0x0, "", HFILL}},
1590 { &hf_dplay_type_07_hresult,
1591 { "Request player HRESULT", "dplay.type_07.hresult", FT_UINT32, BASE_DEC,
1592 NULL, 0x0, "", HFILL}},
1593 { &hf_dplay_type_07_sspi,
1594 { "SSPI provider", "dplay.type_07.sspi", FT_STRING, BASE_NONE,
1595 NULL, 0x0, "", HFILL}},
1596 { &hf_dplay_type_07_capi,
1597 { "CAPI provider", "dplay.type_07.capi", FT_STRING, BASE_NONE,
1598 NULL, 0x0, "", HFILL}},
1600 /* Data fields for message type 0x0008, 0x0009, 0x000b, 0x000c, 0x000d,
1601 * 0x000e, 0x002e and 0x0038*/
1602 { &hf_dplay_multi_id_to,
1603 { "ID to", "dplay.multi.id_to", FT_BYTES, BASE_HEX,
1604 NULL, 0x0, "", HFILL}},
1605 { &hf_dplay_multi_player_id,
1606 { "Player ID", "dplay.multi.player_id", FT_BYTES, BASE_HEX,
1607 NULL, 0x0, "", HFILL}},
1608 { &hf_dplay_multi_group_id,
1609 { "Group ID", "dplay.multi.group_id", FT_BYTES, BASE_HEX,
1610 NULL, 0x0, "", HFILL}},
1611 { &hf_dplay_multi_create_offset,
1612 { "Offset to PackedPlayer struct", "dplay.multi.create_offset", FT_UINT32, BASE_DEC,
1613 NULL, 0x0, "", HFILL}},
1614 { &hf_dplay_multi_password_offset,
1615 { "Offset to password", "dplay.multi.password_offset", FT_UINT32, BASE_DEC,
1616 NULL, 0x0, "", HFILL}},
1617 { &hf_dplay_multi_password,
1618 { "Password", "dplay.multi.password", FT_STRING, BASE_NONE,
1619 NULL, 0x0, "", HFILL}},
1621 /* Data fields for message type 0x000f */
1622 { &hf_dplay_type_0f_id_to,
1623 { "ID to", "dplay.type_0f.id_to", FT_BYTES, BASE_HEX,
1624 NULL, 0x0, "", HFILL}},
1625 { &hf_dplay_type_0f_id,
1626 { "Player ID", "dplay.type_0f.player_id", FT_BYTES, BASE_HEX,
1627 NULL, 0x0, "", HFILL}},
1628 { &hf_dplay_type_0f_data_size,
1629 { "Data Size", "dplay.multi.group_id", FT_UINT32, BASE_DEC,
1630 NULL, 0x0, "", HFILL}},
1631 { &hf_dplay_type_0f_data_offset,
1632 { "Data Offset", "dplay.type_0f.data_offset", FT_UINT32, BASE_DEC,
1633 NULL, 0x0, "", HFILL}},
1634 { &hf_dplay_type_0f_data,
1635 { "Player Data", "dplay.type_0f.player_data", FT_BYTES, BASE_HEX,
1636 NULL, 0x0, "", HFILL}},
1638 /* Data fields for message type 0x0013 */
1639 { &hf_dplay_type_13_id_to,
1640 { "ID to", "dplay.type_13.id_to", FT_BYTES, BASE_HEX,
1641 NULL, 0x0, "", HFILL}},
1642 { &hf_dplay_type_13_player_id,
1643 { "Player ID", "dplay.type_13.player_id", FT_BYTES, BASE_HEX,
1644 NULL, 0x0, "", HFILL}},
1645 { &hf_dplay_type_13_group_id,
1646 { "Group ID", "dplay.type_13.group_id", FT_BYTES, BASE_HEX,
1647 NULL, 0x0, "", HFILL}},
1648 { &hf_dplay_type_13_create_offset,
1649 { "Create Offset", "dplay.type_13.create_offset", FT_UINT32, BASE_DEC,
1650 NULL, 0x0, "", HFILL}},
1651 { &hf_dplay_type_13_password_offset,
1652 { "Password Offset", "dplay.type_13.password_offset", FT_UINT32, BASE_DEC,
1653 NULL, 0x0, "", HFILL}},
1654 { &hf_dplay_type_13_password,
1655 { "Password", "dplay.type_13.password", FT_STRING, BASE_NONE,
1656 NULL, 0x0, "", HFILL}},
1657 { &hf_dplay_type_13_tick_count,
1658 { "Tick count? Looks like an ID", "dplay.type_13.tick_count", FT_BYTES, BASE_HEX,
1659 NULL, 0x0, "", HFILL}},
1661 /* Data fields for message type 0x0015 */
1662 { &hf_dplay_message_guid,
1663 { "Message GUID", "dplay.message.guid", FT_GUID, BASE_NONE,
1664 NULL, 0x0, "", HFILL}},
1665 { &hf_dplay_type_15_packet_idx,
1666 { "Packet Index", "dplay.type_15.packet_idx", FT_UINT32, BASE_DEC,
1667 NULL, 0x0, "", HFILL}},
1668 { &hf_dplay_type_15_data_size,
1669 { "Data Size", "dplay.type_15.data_size", FT_UINT32, BASE_DEC,
1670 NULL, 0x0, "", HFILL}},
1671 { &hf_dplay_type_15_offset,
1672 { "Offset", "dplay.type_15.offset", FT_UINT32, BASE_DEC,
1673 NULL, 0x0, "", HFILL}},
1674 { &hf_dplay_type_15_total_packets,
1675 { "Total Packets", "dplay.type_15.total_packets", FT_UINT32, BASE_DEC,
1676 NULL, 0x0, "", HFILL}},
1677 { &hf_dplay_type_15_msg_size,
1678 { "Message size", "dplay.type_15.message.size", FT_UINT32, BASE_DEC,
1679 NULL, 0x0, "", HFILL}},
1680 { &hf_dplay_type_15_packet_offset,
1681 { "Packet offset", "dplay.type_15.packet_offset", FT_UINT32, BASE_DEC,
1682 NULL, 0x0, "", HFILL}},
1684 /* Data field for message type 0x0016 and 0x0017 */
1685 { &hf_dplay_ping_id_from,
1686 { "ID From", "dplay.ping.id_from", FT_BYTES, BASE_HEX,
1687 NULL, 0x0, "", HFILL}},
1688 { &hf_dplay_ping_tick_count,
1689 { "Tick Count", "dplay.ping.tick_count", FT_UINT32, BASE_DEC,
1690 NULL, 0x0, "", HFILL}},
1692 /* Data fields for message type 0x001a */
1693 { &hf_dplay_type_1a_id_to,
1694 { "ID From", "dplay.type_1a.id_to", FT_BYTES, BASE_HEX,
1695 NULL, 0x0, "", HFILL}},
1696 { &hf_dplay_type_1a_sess_name_ofs,
1697 { "Session Name Offset", "dplay.type_1a.sess_name_ofs", FT_UINT32, BASE_DEC,
1698 NULL, 0x0, "", HFILL}},
1699 { &hf_dplay_type_1a_password_ofs,
1700 { "Password Offset", "dplay.type_1a.password_offset", FT_UINT32, BASE_DEC,
1701 NULL, 0x0, "", HFILL}},
1702 { &hf_dplay_type_1a_session_name,
1703 { "Session Name", "dplay.type_1a.session_name", FT_STRING, BASE_NONE,
1704 NULL, 0x0, "", HFILL}},
1705 { &hf_dplay_type_1a_password,
1706 { "Password", "dplay.type_1a.password", FT_STRING, BASE_NONE,
1707 NULL, 0x0, "", HFILL}},
1709 /* Data fields for message type 0x0029 */
1710 { &hf_dplay_type_29_player_count,
1711 { "SuperEnumPlayers Reply player count", "dplay.type_29.player_count", FT_UINT32,
1712 BASE_DEC, NULL, 0x0, "", HFILL}},
1713 { &hf_dplay_type_29_group_count,
1714 { "SuperEnumPlayers Reply group count", "dplay.type_29.group_count", FT_UINT32,
1715 BASE_DEC, NULL, 0x0, "", HFILL}},
1716 { &hf_dplay_type_29_packed_offset,
1717 { "SuperEnumPlayers Reply packed offset", "dplay.type_29.packed_offset", FT_UINT32,
1718 BASE_DEC, NULL, 0x0, "", HFILL}},
1719 { &hf_dplay_type_29_shortcut_count,
1720 { "SuperEnumPlayers Reply shortcut count", "dplay.type_29.shortcut_count", FT_UINT32,
1721 BASE_DEC, NULL, 0x0, "", HFILL}},
1722 { &hf_dplay_type_29_description_offset,
1723 { "SuperEnumPlayers Reply description offset", "dplay.type_29.desc_offset", FT_UINT32,
1724 BASE_DEC, NULL, 0x0, "", HFILL}},
1725 { &hf_dplay_type_29_name_offset,
1726 { "SuperEnumPlayers Reply name offset", "dplay.type_29.name_offset", FT_UINT32,
1727 BASE_DEC, NULL, 0x0, "", HFILL}},
1728 { &hf_dplay_type_29_password_offset,
1729 { "SuperEnumPlayers Reply password offset", "dplay.type_29.pass_offset", FT_UINT32,
1730 BASE_DEC, NULL, 0x0, "", HFILL}},
1731 { &hf_dplay_type_29_game_name,
1732 { "SuperEnumPlayers Reply game name", "dplay.type_29.game_name", FT_STRING, BASE_NONE,
1733 NULL, 0x0, "", HFILL}},
1734 { &hf_dplay_type_29_password,
1735 { "SuperEnumPlayers Reply Password", "dplay.type_29.password", FT_STRING, BASE_NONE,
1736 NULL, 0x0, "", HFILL}},
1738 /* Data fields for message type 0x002f */
1739 { &hf_dplay_type_2f_dpid,
1740 { "ID of the forwarded player", "dplay.type_29.id", FT_BYTES, BASE_HEX,
1741 NULL, 0x0, "", HFILL}},
1744 static gint *ett[] = {
1747 &ett_dplay_sockaddr,
1750 &ett_dplay_enc_packet,
1751 &ett_dplay_sess_desc_flags,
1752 &ett_dplay_pp_flags,
1753 &ett_dplay_spp_flags,
1754 &ett_dplay_spp_info_mask,
1755 &ett_dplay_type02_flags,
1756 &ett_dplay_type05_flags,
1757 &ett_dplay_type29_spp,
1760 proto_dplay = proto_register_protocol (
1761 "DirectPlay Protocol",
1765 proto_register_field_array(proto_dplay, hf, array_length(hf));
1766 proto_register_subtree_array(ett, array_length(ett));
1769 void proto_reg_handoff_dplay(void)
1771 heur_dissector_add("udp", heur_dissect_dplay, proto_dplay);
1772 heur_dissector_add("tcp", heur_dissect_dplay, proto_dplay);