epan/dissectors/pidl/ C99 drsuapi
[wireshark-sm.git] / epan / dissectors / packet-dplay.c
blob6e8bc1a5c85d576226eb94626922023dcce664a4
1 /* packet-dplay.c
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
13 #include "config.h"
16 #include <epan/packet.h>
17 #include <epan/aftypes.h>
18 #include <epan/tfs.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;
268 /* various */
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" },
305 { 0x0016, "Ping" },
306 { 0x0017, "Pong" },
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" },
316 { 0x0022, "Signed"},
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" },
327 { 0x002d, "Chat" },
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" },
334 { 0x0036, "Voice" },
335 { 0x0037, "Multicast Delivery" },
336 { 0x0038, "Create Players Verify"},
337 { 0 , NULL },
340 static const value_string dplay_af_val[] = {
341 { WINSOCK_AF_INET, "AF_INET" },
342 { WINSOCK_AF_IPX, "AF_IPX" },
343 { 0 , NULL},
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"},
353 { 0 , NULL},
356 static const value_string dplay_token_val[] = {
357 { 0xfab, "Remote Message" },
358 { 0xcab, "Forwarded Message" },
359 { 0xbab, "Server Message" },
360 { 0 , NULL },
363 static const value_string dplay_spp_length_val[] = {
364 { 0x0, "Not present" },
365 { 0x1, "One byte" },
366 { 0x2, "Two bytes" },
367 { 0x3, "Four bytes" },
368 { 0 , NULL},
371 static const value_string dplay_enc_alg_val[] = {
372 { 0x0000, "Default" },
373 { 0x6611, "AES" },
374 { 0x6603, "3DES" },
375 { 0x6601, "DES" },
376 { 0x6602, "RC2" },
377 { 0x6801, "RC4" },
378 { 0 , NULL },
381 static const value_string yes_no_val[] = {
382 { 0x0, "No" },
383 { 0x1, "Yes" },
384 { 0 , NULL },
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)
391 char *str;
392 int len;
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);
399 return offset+len;
402 static int dissect_sockaddr_in(proto_tree *tree, tvbuff_t *tvb, int offset)
404 proto_tree *sa_tree;
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;
412 return offset;
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,
436 NULL
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;
455 return offset;
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;
461 int size;
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,
467 NULL
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;
492 if (sn_len)
493 offset = display_unicode_string(tree, hf_dplay_pp_short_name, tvb, offset);
495 if (ln_len)
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);
499 offset += sd_len;
501 if (pd_len) {
502 proto_tree_add_item(tree, hf_dplay_pp_player_data, tvb, offset, pd_len, ENC_NA);
503 offset += pd_len;
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;
515 return offset;
518 static int spp_get_value(uint32_t length_type, tvbuff_t *tvb, int offset, uint32_t *value)
520 int len = 0;
522 *value = 0;
524 switch (length_type) {
525 case 1:
526 len = 1;
527 *value = tvb_get_uint8(tvb, offset);
528 break;
529 case 2:
530 len = 2;
531 *value = tvb_get_letohs(tvb, offset);
532 break;
533 case 3:
534 len = 4;
535 *value = tvb_get_letohl(tvb, offset);
536 break;
539 return len;
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;
550 int len;
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,
556 NULL
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);
586 offset+=4;
588 if (is_sysplayer) {
589 proto_tree_add_item(tree, hf_dplay_spp_dialect, tvb, offset, 4, ENC_LITTLE_ENDIAN);
590 } else {
591 proto_tree_add_item(tree, hf_dplay_spp_sys_player_id, tvb, offset, 4, ENC_NA);
593 offset += 4;
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);
606 offset += len;
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);
614 offset += len;
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) {
620 uint32_t i;
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);
624 offset += len;
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) {
635 uint32_t i;
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);
639 offset += len;
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;
645 return offset;
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;
656 return offset;
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);
669 offset += 4;
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;
674 return offset;
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);
688 return 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,
698 NULL
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);
710 return 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,
721 NULL
724 proto_tree_add_bitmask(tree, tvb, offset, hf_dplay_type_05_flags, ett_dplay_type05_flags, flags, ENC_LITTLE_ENDIAN);
725 offset += 4;
726 return offset;
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;
744 if (sspi_offset) {
745 offset = display_unicode_string(tree, hf_dplay_type_07_sspi, tvb, offset);
748 if (capi_offset) {
749 offset = display_unicode_string(tree, hf_dplay_type_07_capi, tvb, offset);
751 return offset;
754 static int dissect_player_message(proto_tree *tree, tvbuff_t *tvb, int offset)
756 uint32_t pp_ofs;
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;
764 if (pp_ofs)
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);
768 return offset;
771 static int dissect_type0f_message(proto_tree *tree, tvbuff_t *tvb, int offset)
773 uint32_t data_size;
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);
781 offset += data_size;
783 return offset;
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;
797 if (pp_ofs)
798 offset = dissect_packed_player(tree, tvb, offset);
799 if (pw_ofs)
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;
803 return offset;
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)
828 case 0x0005:
829 offset = dissect_type05_message(enc_tree, tvb, offset);
830 break;
831 case 0x0007:
832 offset = dissect_type05_message(enc_tree, tvb, offset);
833 break;
834 case 0x0008:
835 case 0x0009:
836 case 0x000b:
837 case 0x000c:
838 case 0x000d:
839 case 0x000e:
840 case 0x002e:
841 offset = dissect_player_message(enc_tree, tvb, offset);
842 break;
843 case 0x0013:
844 offset = dissect_type13_message(enc_tree, tvb, offset);
845 break;
846 case 0x001a:
847 offset = dissect_type1a_message(enc_tree, tvb, offset);
848 break;
851 return 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;
859 return offset;
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);
873 if (sn_ofs) {
874 offset = display_unicode_string(tree, hf_dplay_type_1a_session_name, tvb, offset);
877 if (pw_ofs) {
878 offset = display_unicode_string(tree, hf_dplay_type_1a_password, tvb, offset);
881 return 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;
888 int i;
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);
928 return 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;
934 return offset;
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;
942 uint32_t dplay_id;
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");
953 return;
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)"));
968 else
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)"));
973 if(tree)
975 proto_item *dplay_item;
976 proto_tree *dplay_tree;
977 proto_tree *dplay_header;
978 proto_tree *dplay_data;
979 int offset = 0;
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)
989 return;
991 dplay_data = proto_tree_add_subtree(dplay_tree, tvb, offset, -1, ett_dplay_data, NULL, "DirectPlay data");
993 switch(message_type)
995 case 0x0001:
996 dissect_type01_message(dplay_data, tvb, offset);
997 break;
998 case 0x0002:
999 dissect_type02_message(dplay_data, tvb, offset);
1000 break;
1001 case 0x0005:
1002 dissect_type05_message(dplay_data, tvb, offset);
1003 break;
1004 case 0x0007:
1005 dissect_type07_message(dplay_data, tvb, offset);
1006 break;
1007 case 0x0008:
1008 case 0x0009:
1009 /* type 0a doesn't have a dplay header and is not handled here */
1010 case 0x000b:
1011 case 0x000c:
1012 case 0x000d:
1013 case 0x000e:
1014 case 0x002e:
1015 case 0x0038:
1016 dissect_player_message(dplay_data, tvb, offset);
1017 break;
1018 case 0x000f:
1019 dissect_type0f_message(dplay_data, tvb, offset);
1020 break;
1021 case 0x0013:
1022 dissect_type13_message(dplay_data, tvb, offset);
1023 break;
1024 case 0x0015:
1025 dissect_type15_message(dplay_data, tvb, offset);
1026 break;
1027 case 0x0016:
1028 case 0x0017:
1029 dissect_ping_message(dplay_data, tvb, offset);
1030 break;
1031 case 0x001a:
1032 dissect_type1a_message(dplay_data, tvb, offset);
1033 break;
1034 case 0x0029:
1035 dissect_type29_message(dplay_data, tvb, offset);
1036 break;
1037 case 0x002f:
1038 dissect_type2f_message(dplay_data, tvb, offset);
1039 break;
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");
1052 if(tree)
1054 proto_item *dplay_item;
1055 proto_tree *dplay_tree;
1056 proto_tree *data_tree;
1057 int offset = 0;
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);
1068 offset += 4;
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)
1081 return false;
1083 /* The string play = 0x706c6179 */
1084 dplay_id = tvb_get_ntohl(tvb, 20);
1085 if( dplay_id == 0x706c6179) {
1086 dissect_dplay(tvb, pinfo, tree);
1087 return true;
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) {
1097 int offset;
1098 for (offset = 12; offset <= 20; offset++)
1099 if (tvb_get_uint8(tvb, offset) != 0)
1100 return false;
1102 dissect_dplay_player_msg(tvb, pinfo, tree);
1103 return true;
1107 return false;
1110 void proto_register_dplay(void)
1112 static hf_register_info hf [] = {
1113 /* Common data fields */
1114 { &hf_dplay_size,
1115 { "DirectPlay package size", "dplay.size", FT_UINT32, BASE_DEC,
1116 NULL, 0x0, NULL, HFILL}},
1117 { &hf_dplay_token,
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}},
1271 { &hf_dplay_pp_id,
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}},
1339 { &hf_dplay_spp_id,
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[] = {
1642 &ett_dplay,
1643 &ett_dplay_header,
1644 &ett_dplay_sockaddr,
1645 &ett_dplay_data,
1646 &ett_dplay_flags,
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",
1659 "DPLAY",
1660 "dplay"
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
1675 * Local variables:
1676 * c-basic-offset: 4
1677 * tab-width: 8
1678 * indent-tabs-mode: nil
1679 * End:
1681 * vi: set shiftwidth=4 tabstop=8 expandtab:
1682 * :indentSize=4:tabSize=8:noTabs=true: