Coverage Report

Created: 2025-02-15 06:25

/src/wireshark/epan/dissectors/packet-dpnet.c
Line
Count
Source (jump to first uncovered line)
1
/* packet-dpnet.c
2
 * This is a dissector for the DirectPlay 8 protocol.
3
 *
4
 * Copyright 2017 - Alistair Leslie-Hughes
5
 *
6
 * Wireshark - Network traffic analyzer
7
 * By Gerald Combs <gerald@wireshark.org>
8
 * Copyright 1998 Gerald Combs
9
 *
10
 * SPDX-License-Identifier: GPL-2.0-or-later
11
 *
12
 */
13
14
#include "config.h"
15
16
#include <epan/packet.h>
17
#include <epan/tfs.h>
18
19
void proto_register_dpnet(void);
20
void proto_reg_handoff_dpnet(void);
21
22
static dissector_handle_t dpnet_handle;
23
24
14
#define DPNET_PORT 6073
25
26
static int proto_dpnet;
27
28
static int hf_dpnet_lead;
29
static int hf_dpnet_command;
30
static int hf_dpnet_payload;
31
static int hf_dpnet_type;
32
static int hf_dpnet_application;
33
static int hf_dpnet_data;
34
static int hf_dpnet_reply_offset;
35
static int hf_dpnet_response_size;
36
37
static int hf_dpnet_desc_size;
38
static int hf_dpnet_desc_flags;
39
static int hf_dpnet_max_players;
40
static int hf_dpnet_current_players;
41
static int hf_dpnet_session_offset;
42
static int hf_dpnet_session_size;
43
static int hf_dpnet_session_name;
44
static int hf_dpnet_password_offset;
45
static int hf_dpnet_password_size;
46
static int hf_dpnet_reserved_offset;
47
static int hf_dpnet_reserved_size;
48
static int hf_dpnet_application_offset;
49
static int hf_dpnet_application_size;
50
static int hf_dpnet_application_data;
51
static int hf_dpnet_instance;
52
static int hf_dpnet_data_cframe_control;
53
static int hf_dpnet_data_cframe_msgid;
54
static int hf_dpnet_data_cframe_rspid;
55
static int hf_dpnet_data_cframe_protocol;
56
static int hf_dpnet_data_cframe_session;
57
static int hf_dpnet_data_cframe_timestamp;
58
static int hf_dpnet_data_cframe_padding;
59
static int hf_dpnet_data_cframe_flags;
60
static int hf_dpnet_data_cframe_retry;
61
static int hf_dpnet_data_cframe_nseq;
62
static int hf_dpnet_data_cframe_nrcv;
63
static int hf_dpnet_data_cframe_sack_mask1;
64
static int hf_dpnet_data_cframe_sack_mask2;
65
static int hf_dpnet_data_cframe_send_mask1;
66
static int hf_dpnet_data_cframe_send_mask2;
67
static int hf_dpnet_data_cframe_signature;
68
static int hf_dpnet_data_cframe_send_secret;
69
static int hf_dpnet_data_cframe_recv_secret;
70
static int hf_dpnet_data_cframe_signing_opts;
71
static int hf_dpnet_data_cframe_echo_time;
72
static int hf_dpnet_data_seq;
73
static int hf_dpnet_data_nseq;
74
static int hf_dpnet_data_command;
75
static int hf_dpnet_command_data;
76
static int hf_dpnet_command_reliable;
77
static int hf_dpnet_command_seq;
78
static int hf_dpnet_command_poll;
79
static int hf_dpnet_command_new_msg;
80
static int hf_dpnet_command_end_msg;
81
static int hf_dpnet_command_user1;
82
static int hf_dpnet_command_user2;
83
static int hf_dpnet_desc_client_server;
84
static int hf_dpnet_desc_migrate_host;
85
static int hf_dpnet_desc_nodpnsvr;
86
static int hf_dpnet_desc_req_password;
87
static int hf_dpnet_desc_no_enums;
88
static int hf_dpnet_desc_fast_signed;
89
static int hf_dpnet_desc_full_signed;
90
91
static int ett_dpnet;
92
static int ett_dpnet_command_flags;
93
static int ett_dpnet_desc_flags;
94
95
0
#define DPNET_QUERY_GUID     0x01
96
97
0
#define DPNET_ENUM_QUERY     0x02
98
0
#define DPNET_ENUM_RESPONSE  0x03
99
100
14
#define DPNET_COMMAND_DATA                   0x01
101
14
#define DPNET_COMMAND_RELIABLE               0x02
102
14
#define DPNET_COMMAND_SEQUENTIAL             0x04
103
14
#define DPNET_COMMAND_POLL                   0x08
104
14
#define DPNET_COMMAND_NEW_MSG                0x10
105
14
#define DPNET_COMMAND_END_MSG                0x20
106
14
#define DPNET_COMMAND_USER_1                 0x40
107
14
#define DPNET_COMMAND_CFRAME                 0x80
108
109
#define DN_MSG_INTERNAL_PLAYER_CONNECT_INFO  0x000000c1
110
#define DN_MSG_INTERNAL_SEND_CONNECT_INFO    0x000000c2
111
#define DN_MSG_INTERNAL_ACK_CONNECT_INFO     0x000000c3
112
113
0
#define FRAME_EXOPCODE_CONNECT               0x01
114
0
#define FRAME_EXOPCODE_CONNECTED             0x02
115
0
#define FRAME_EXOPCODE_CONNECTED_SIGNED      0x03
116
0
#define FRAME_EXOPCODE_HARD_DISCONNECT       0x04
117
0
#define FRAME_EXOPCODE_SACK                  0x06
118
119
#define PROTOCOL_VER_0                       0x00010000
120
#define PROTOCOL_VER_1                       0x00010001
121
#define PROTOCOL_VER_2                       0x00010002
122
#define PROTOCOL_VER_3                       0x00010003
123
#define PROTOCOL_VER_4                       0x00010004
124
#define PROTOCOL_VER_5                       0x00010005
125
#define PROTOCOL_VER_6                       0x00010006
126
127
#define SACK_FLAGS_RESPONSE                  0x01
128
0
#define SACK_FLAGS_SACK_MASK1                0x02
129
0
#define SACK_FLAGS_SACK_MASK2                0x04
130
0
#define SACK_FLAGS_SEND_MASK1                0x08
131
0
#define SACK_FLAGS_SEND_MASK2                0x10
132
133
#define PACKET_SIGNING_FAST                  0x01
134
#define PACKET_SIGNING_FULL                  0x02
135
136
14
#define SESSION_CLIENT_SERVER                0x0001
137
14
#define SESSION_MIGRATE_HOST                 0x0004
138
14
#define SESSION_NODPNSVR                     0x0040
139
14
#define SESSION_REQUIREPASSWORD              0x0080
140
14
#define SESSION_NOENUMS                      0x0100
141
14
#define SESSION_FAST_SIGNED                  0x0200
142
14
#define SESSION_FULL_SIGNED                  0x0400
143
144
static const value_string packetenumttypes[] = {
145
    { 1, "Application GUID" },
146
    { 2, "All Applications" },
147
    { 0, NULL }
148
};
149
150
static const value_string packetquerytype[] = {
151
    { 2, "Enumeration Query" },
152
    { 3, "Enumeration Response" },
153
    { 0, NULL }
154
};
155
156
static const value_string msg_cframe_control[] = {
157
    {FRAME_EXOPCODE_CONNECT,              "FRAME_EXOPCODE_CONNECT"},
158
    {FRAME_EXOPCODE_CONNECTED,            "FRAME_EXOPCODE_CONNECTED"},
159
    {FRAME_EXOPCODE_CONNECTED_SIGNED,     "FRAME_EXOPCODE_CONNECTED_SIGNED"},
160
    {FRAME_EXOPCODE_HARD_DISCONNECT,      "FRAME_EXOPCODE_HARD_DISCONNECT"},
161
    {FRAME_EXOPCODE_SACK,                 "FRAME_EXOPCODE_SACK"},
162
    {0, NULL }
163
};
164
165
static const value_string protocol_versions[] = {
166
    {PROTOCOL_VER_0,                      "Supports Base Features"},
167
    {PROTOCOL_VER_1,                      "Supports Base Features"},
168
    {PROTOCOL_VER_2,                      "Supports Base Features"},
169
    {PROTOCOL_VER_3,                      "Supports Base Features"},
170
    {PROTOCOL_VER_4,                      "Supports Base Features"},
171
    {PROTOCOL_VER_5,                      "Supports Coalescence"},
172
    {PROTOCOL_VER_6,                      "Supports Coalescence and Signing"},
173
    {0, NULL }
174
};
175
176
static const value_string sack_flags[] = {
177
    {SACK_FLAGS_RESPONSE,                  "Retry field is valid"},
178
    {SACK_FLAGS_SACK_MASK1,                "Low 32 bits of the SACK mask are present in sack.mask1"},
179
    {SACK_FLAGS_SACK_MASK2,                "High 32 bits of the SACK mask are present in sack.mask2"},
180
    {SACK_FLAGS_SEND_MASK1,                "Low 32 bits of the Send mask are present in send.mask1"},
181
    {SACK_FLAGS_SEND_MASK2,                "High 32 bits of the Send mask are present in send.mask2"},
182
    {0, NULL }
183
};
184
185
static const value_string signing_opts[] = {
186
    {PACKET_SIGNING_FAST,                "Fasting signing"},
187
    {PACKET_SIGNING_FULL,                "Full signing"},
188
    {0, NULL }
189
};
190
191
static const true_false_string tfs_flags_game_client = {
192
    "Client/Server session",
193
    "Peer session"
194
};
195
196
static const true_false_string tfs_flags_migrate = {
197
    "Host Migrating allowed",
198
    "Host Migrating NOT allowed"
199
};
200
201
static const true_false_string tfs_flags_dpnsvr = {
202
    "NOT using dpnsvr.exe",
203
    "Using dpnsvr.exe"
204
};
205
206
static const true_false_string tfs_flags_password_required = {
207
    "Password required",
208
    "NO password required"
209
};
210
211
static const true_false_string tfs_flags_enumeration = {
212
    "Enumeration NOT allowed",
213
    "Enumeration allowed"
214
};
215
216
static const true_false_string tfs_flags_fast = {
217
    "Using Fast signing",
218
    "NOT using Fast signing"
219
};
220
221
static const true_false_string tfs_flags_full = {
222
    "Using Full signing",
223
    "NOT using Full signing"
224
};
225
226
227
static int * const desc_flags[] = {
228
    &hf_dpnet_desc_client_server,
229
    &hf_dpnet_desc_migrate_host,
230
    &hf_dpnet_desc_nodpnsvr,
231
    &hf_dpnet_desc_req_password,
232
    &hf_dpnet_desc_no_enums,
233
    &hf_dpnet_desc_fast_signed,
234
    &hf_dpnet_desc_full_signed,
235
    NULL
236
};
237
238
static int * const command_flags[] = {
239
    &hf_dpnet_command_data,
240
    &hf_dpnet_command_reliable,
241
    &hf_dpnet_command_seq,
242
    &hf_dpnet_command_poll,
243
    &hf_dpnet_command_new_msg,
244
    &hf_dpnet_command_end_msg,
245
    &hf_dpnet_command_user1,
246
    &hf_dpnet_command_user2,
247
    NULL
248
};
249
250
static void process_dpnet_query(proto_tree *dpnet_tree, tvbuff_t *tvb, packet_info *pinfo)
251
0
{
252
0
    int offset = 0, data_tvb_len;
253
0
    uint8_t has_guid;
254
0
    uint8_t is_query;
255
256
0
    proto_tree_add_item(dpnet_tree, hf_dpnet_lead, tvb, 0, 1, ENC_BIG_ENDIAN); offset += 1;
257
0
    is_query = tvb_get_uint8(tvb, offset);
258
0
    proto_tree_add_item(dpnet_tree, hf_dpnet_command, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1;
259
0
    proto_tree_add_item(dpnet_tree, hf_dpnet_payload, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2;
260
261
0
    if(is_query == DPNET_ENUM_QUERY)
262
0
    {
263
0
        col_set_str(pinfo->cinfo, COL_INFO, "DPNET Enum Query");
264
265
0
        has_guid = tvb_get_uint8(tvb, offset);
266
0
        proto_tree_add_item(dpnet_tree, hf_dpnet_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1;
267
268
0
        if (has_guid & DPNET_QUERY_GUID) {
269
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_application, tvb, offset, 16, ENC_BIG_ENDIAN);
270
0
            offset += 16;
271
0
        }
272
273
0
        data_tvb_len = tvb_reported_length_remaining(tvb, offset);
274
0
        if(data_tvb_len)
275
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data, tvb, offset, data_tvb_len, ENC_NA);
276
277
0
    }
278
0
    else if(is_query == DPNET_ENUM_RESPONSE)
279
0
    {
280
0
        uint32_t session_offset, session_size;
281
0
        uint32_t application_offset, application_size;
282
283
0
        col_set_str(pinfo->cinfo, COL_INFO, "DPNET Enum Response");
284
285
0
        proto_tree_add_item(dpnet_tree, hf_dpnet_reply_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
286
0
        proto_tree_add_item(dpnet_tree, hf_dpnet_response_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
287
0
        proto_tree_add_item(dpnet_tree, hf_dpnet_desc_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
288
0
        proto_tree_add_bitmask(dpnet_tree, tvb, offset, hf_dpnet_desc_flags, ett_dpnet_desc_flags, desc_flags, ENC_LITTLE_ENDIAN);
289
0
        offset += 4;
290
0
        proto_tree_add_item(dpnet_tree, hf_dpnet_max_players, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
291
0
        proto_tree_add_item(dpnet_tree, hf_dpnet_current_players, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
292
0
        proto_tree_add_item_ret_uint(dpnet_tree, hf_dpnet_session_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN, &session_offset); offset += 4;
293
0
        proto_tree_add_item_ret_uint(dpnet_tree, hf_dpnet_session_size, tvb, offset, 4, ENC_LITTLE_ENDIAN, &session_size); offset += 4;
294
0
        proto_tree_add_item(dpnet_tree, hf_dpnet_password_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
295
0
        proto_tree_add_item(dpnet_tree, hf_dpnet_password_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
296
0
        proto_tree_add_item(dpnet_tree, hf_dpnet_reserved_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
297
0
        proto_tree_add_item(dpnet_tree, hf_dpnet_reserved_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4;
298
0
        proto_tree_add_item_ret_uint(dpnet_tree, hf_dpnet_application_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN, &application_offset); offset += 4;
299
0
        proto_tree_add_item_ret_uint(dpnet_tree, hf_dpnet_application_size, tvb, offset, 4, ENC_LITTLE_ENDIAN, &application_size); offset += 4;
300
0
        proto_tree_add_item(dpnet_tree, hf_dpnet_instance, tvb, offset, 16, ENC_LITTLE_ENDIAN); offset += 16;
301
0
        proto_tree_add_item(dpnet_tree, hf_dpnet_application, tvb, offset, 16, ENC_LITTLE_ENDIAN);
302
303
0
        if(session_offset)
304
0
        {
305
            /* session_offset starts from the hf_dpnet_payload */
306
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_session_name, tvb, session_offset + 4, session_size, ENC_UTF_16|ENC_LITTLE_ENDIAN);
307
0
        }
308
309
0
        if(application_offset)
310
0
        {
311
            /* application_offset starts from the hf_dpnet_payload */
312
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_application_data, tvb, application_offset + 4, application_size, ENC_NA);
313
0
        }
314
0
    }
315
0
}
316
317
static void
318
dpnet_process_data_frame(proto_tree *dpnet_tree, tvbuff_t *tvb, packet_info *pinfo)
319
0
{
320
0
    int offset = 0;
321
322
0
    col_set_str(pinfo->cinfo, COL_INFO, "DPNET DFrame");
323
324
0
    proto_tree_add_bitmask(dpnet_tree, tvb, offset, hf_dpnet_data_command, ett_dpnet_command_flags, command_flags, ENC_BIG_ENDIAN);
325
326
    /* TODO */
327
0
}
328
329
static void
330
dpnet_process_control_frame(proto_tree *dpnet_tree, tvbuff_t *tvb, packet_info *pinfo)
331
0
{
332
0
    int offset = 0;
333
0
    int command;
334
0
    const char *command_str;
335
0
    int flag;
336
0
    uint32_t data_tvb_len;
337
338
0
    col_set_str(pinfo->cinfo, COL_INFO, "DPNET CFrame");
339
340
0
    proto_tree_add_bitmask(dpnet_tree, tvb, offset, hf_dpnet_data_command, ett_dpnet_command_flags, command_flags, ENC_BIG_ENDIAN);
341
0
    offset += 1;
342
343
0
    command = tvb_get_uint8(tvb, offset);
344
0
    command_str = val_to_str_const(command, msg_cframe_control, "Unknown Control (obsolete or malformed?)");
345
0
    col_append_fstr(pinfo->cinfo, COL_INFO, " - %s", command_str);
346
347
0
    proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_control, tvb, offset, 1, ENC_LITTLE_ENDIAN);
348
0
    offset += 1;
349
350
0
    switch(command)
351
0
    {
352
0
        case FRAME_EXOPCODE_CONNECT:
353
0
        case FRAME_EXOPCODE_CONNECTED:
354
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_msgid, tvb, offset, 1, ENC_LITTLE_ENDIAN);
355
0
            offset += 1;
356
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_rspid, tvb, offset, 1, ENC_LITTLE_ENDIAN);
357
0
            offset += 1;
358
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_protocol, tvb, offset, 4, ENC_LITTLE_ENDIAN);
359
0
            offset += 4;
360
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_session, tvb, offset, 4, ENC_LITTLE_ENDIAN);
361
0
            offset += 4;
362
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_timestamp, tvb, offset, 4, ENC_LITTLE_ENDIAN);
363
0
            break;
364
0
        case FRAME_EXOPCODE_CONNECTED_SIGNED:
365
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_msgid, tvb, offset, 1, ENC_LITTLE_ENDIAN);
366
0
            offset += 1;
367
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_rspid, tvb, offset, 1, ENC_LITTLE_ENDIAN);
368
0
            offset += 1;
369
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_protocol, tvb, offset, 4, ENC_LITTLE_ENDIAN);
370
0
            offset += 4;
371
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_session, tvb, offset, 4, ENC_LITTLE_ENDIAN);
372
0
            offset += 4;
373
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_timestamp, tvb, offset, 4, ENC_LITTLE_ENDIAN);
374
0
            offset += 4;
375
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_signature, tvb, offset, 8, ENC_NA);
376
0
            offset += 8;
377
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_send_secret, tvb, offset, 8, ENC_NA);
378
0
            offset += 8;
379
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_recv_secret, tvb, offset, 8, ENC_NA);
380
0
            offset += 8;
381
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_signing_opts, tvb, offset, 4, ENC_LITTLE_ENDIAN);
382
0
            offset += 4;
383
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_echo_time, tvb, offset, 4, ENC_LITTLE_ENDIAN);
384
0
            break;
385
0
        case FRAME_EXOPCODE_HARD_DISCONNECT:
386
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_msgid, tvb, offset, 1, ENC_LITTLE_ENDIAN);
387
0
            offset += 1;
388
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_rspid, tvb, offset, 1, ENC_LITTLE_ENDIAN);
389
0
            offset += 1;
390
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_protocol, tvb, offset, 4, ENC_LITTLE_ENDIAN);
391
0
            offset += 4;
392
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_session, tvb, offset, 4, ENC_LITTLE_ENDIAN);
393
0
            offset += 4;
394
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_timestamp, tvb, offset, 4, ENC_LITTLE_ENDIAN);
395
0
            offset += 4;
396
397
0
            data_tvb_len = tvb_reported_length_remaining(tvb, offset);
398
0
            if(data_tvb_len)
399
0
                proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_signature, tvb, offset, 8, ENC_NA);
400
0
            break;
401
0
        case FRAME_EXOPCODE_SACK:
402
0
            flag = tvb_get_uint8(tvb, offset);
403
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
404
0
            offset += 1;
405
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_retry, tvb, offset, 1, ENC_LITTLE_ENDIAN);
406
0
            offset += 1;
407
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_nseq, tvb, offset, 1, ENC_LITTLE_ENDIAN);
408
0
            offset += 1;
409
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_nrcv, tvb, offset, 1, ENC_LITTLE_ENDIAN);
410
0
            offset += 1;
411
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_padding, tvb, offset, 2, ENC_LITTLE_ENDIAN);
412
0
            offset += 2;
413
0
            proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_timestamp, tvb, offset, 4, ENC_LITTLE_ENDIAN);
414
0
            offset += 4;
415
416
0
            if(flag & SACK_FLAGS_SACK_MASK1)
417
0
            {
418
0
                proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_sack_mask1, tvb, offset, 4, ENC_LITTLE_ENDIAN);
419
0
                offset += 4;
420
0
            }
421
0
            if(flag & SACK_FLAGS_SACK_MASK2)
422
0
            {
423
0
                proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_sack_mask2, tvb, offset, 4, ENC_LITTLE_ENDIAN);
424
0
                offset += 4;
425
0
            }
426
0
            if(flag & SACK_FLAGS_SEND_MASK1)
427
0
            {
428
0
                proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_send_mask1, tvb, offset, 4, ENC_LITTLE_ENDIAN);
429
0
                offset += 4;
430
0
            }
431
0
            if(flag & SACK_FLAGS_SEND_MASK2)
432
0
            {
433
0
                proto_tree_add_item(dpnet_tree, hf_dpnet_data_cframe_send_mask2, tvb, offset, 4, ENC_LITTLE_ENDIAN);
434
0
            }
435
0
            break;
436
0
        default:
437
0
            break;
438
0
    }
439
0
}
440
441
static int
442
dissect_dpnet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
443
0
{
444
0
    uint8_t lead;
445
446
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "DPNET");
447
    /* Clear out stuff in the info column */
448
0
    col_clear(pinfo->cinfo,COL_INFO);
449
450
0
    proto_item *ti = proto_tree_add_item(tree, proto_dpnet, tvb, 0, -1, ENC_NA);
451
0
    proto_tree *dpnet_tree = proto_item_add_subtree(ti, ett_dpnet);
452
453
0
    lead = tvb_get_uint8(tvb, 0);
454
0
    if(lead == 0)
455
0
    {
456
0
        process_dpnet_query(dpnet_tree, tvb, pinfo);
457
0
    }
458
0
    else
459
0
    {
460
0
        if(lead & DPNET_COMMAND_DATA)
461
0
            dpnet_process_data_frame(dpnet_tree, tvb, pinfo);
462
0
        else
463
0
            dpnet_process_control_frame(dpnet_tree, tvb, pinfo);
464
0
    }
465
466
0
    return tvb_captured_length(tvb);
467
0
}
468
469
void
470
proto_register_dpnet(void)
471
14
{
472
14
    static hf_register_info hf[] = {
473
14
        { &hf_dpnet_lead,
474
14
            { "Lead", "dpnet.lead",
475
14
            FT_UINT8, BASE_DEC,
476
14
            NULL, 0,
477
14
            NULL, HFILL }
478
14
        },
479
14
        { &hf_dpnet_command,
480
14
            { "Command", "dpnet.command",
481
14
            FT_UINT8, BASE_HEX,
482
14
            VALS(packetquerytype), 0,
483
14
            NULL, HFILL }
484
14
        },
485
14
        { &hf_dpnet_payload,
486
14
            { "Payload", "dpnet.payload",
487
14
            FT_UINT16, BASE_HEX,
488
14
            NULL, 0,
489
14
            NULL, HFILL }
490
14
        },
491
14
        { &hf_dpnet_type,
492
14
            { "Type", "dpnet.type",
493
14
            FT_UINT8, BASE_DEC,
494
14
            VALS(packetenumttypes), 0,
495
14
            NULL, HFILL }
496
14
        },
497
14
        { &hf_dpnet_application,
498
14
            { "Application GUID", "dpnet.application",
499
14
            FT_GUID, BASE_NONE,
500
14
            NULL, 0,
501
14
            NULL, HFILL }
502
14
        },
503
14
        { &hf_dpnet_data,
504
14
            { "Data", "dpnet.data",
505
14
            FT_BYTES, BASE_NONE,
506
14
            NULL, 0,
507
14
            NULL, HFILL }
508
14
        },
509
14
        { &hf_dpnet_reply_offset,
510
14
            { "Reply Offset", "dpnet.reply_offset",
511
14
            FT_UINT32, BASE_DEC,
512
14
            NULL, 0,
513
14
            NULL, HFILL }
514
14
        },
515
14
        { &hf_dpnet_response_size,
516
14
            { "Response Size", "dpnet.response_size",
517
14
            FT_UINT32, BASE_DEC,
518
14
            NULL, 0,
519
14
            NULL, HFILL }
520
14
        },
521
14
        { &hf_dpnet_desc_size,
522
14
            { "Description Size", "dpnet.desc_size",
523
14
            FT_UINT32, BASE_DEC,
524
14
            NULL, 0,
525
14
            NULL, HFILL }
526
14
        },
527
14
        { &hf_dpnet_desc_flags,
528
14
            { "Description Flags", "dpnet.desc_flags",
529
14
            FT_UINT16, BASE_HEX,
530
14
            NULL, 0,
531
14
            NULL, HFILL }
532
14
        },
533
14
        { &hf_dpnet_max_players,
534
14
            { "Max Players", "dpnet.max_players",
535
14
            FT_UINT32, BASE_DEC,
536
14
            NULL, 0,
537
14
            NULL, HFILL }
538
14
        },
539
14
        { &hf_dpnet_current_players,
540
14
            { "Current Players", "dpnet.current_players",
541
14
            FT_UINT32, BASE_DEC,
542
14
            NULL, 0,
543
14
            NULL, HFILL }
544
14
        },
545
14
        { &hf_dpnet_session_offset,
546
14
            { "Session Offset", "dpnet.session_offset",
547
14
            FT_UINT32, BASE_DEC,
548
14
            NULL, 0,
549
14
            NULL, HFILL }
550
14
        },
551
14
        { &hf_dpnet_session_size,
552
14
            { "Session Size", "dpnet.session_size",
553
14
            FT_UINT32, BASE_DEC,
554
14
            NULL, 0,
555
14
            NULL, HFILL }
556
14
        },
557
14
        { &hf_dpnet_session_name,
558
14
            { "Session name", "dpnet.session_name",
559
14
            FT_STRING, BASE_NONE,
560
14
            NULL, 0,
561
14
            NULL, HFILL }
562
14
        },
563
14
        { &hf_dpnet_password_offset,
564
14
            { "Password Offset", "dpnet.password_offset",
565
14
            FT_UINT32, BASE_DEC,
566
14
            NULL, 0,
567
14
            NULL, HFILL }
568
14
        },
569
14
        { &hf_dpnet_password_size,
570
14
            { "Password Size", "dpnet.password_size",
571
14
            FT_UINT32, BASE_DEC,
572
14
            NULL, 0,
573
14
            NULL, HFILL }
574
14
        },
575
14
        { &hf_dpnet_reserved_offset,
576
14
            { "Reserved Offset", "dpnet.reserved_offset",
577
14
            FT_UINT32, BASE_DEC,
578
14
            NULL, 0,
579
14
            NULL, HFILL }
580
14
        },
581
14
        { &hf_dpnet_reserved_size,
582
14
            { "Reserved Size", "dpnet.reserved_size",
583
14
            FT_UINT32, BASE_DEC,
584
14
            NULL, 0,
585
14
            NULL, HFILL }
586
14
        },
587
14
        { &hf_dpnet_application_offset,
588
14
            { "Application Offset", "dpnet.application_offset",
589
14
            FT_UINT32, BASE_DEC,
590
14
            NULL, 0,
591
14
            NULL, HFILL }
592
14
        },
593
14
        { &hf_dpnet_application_size,
594
14
            { "Application Size", "dpnet.application_size",
595
14
            FT_UINT32, BASE_DEC,
596
14
            NULL, 0,
597
14
            NULL, HFILL }
598
14
        },
599
14
        { &hf_dpnet_application_data,
600
14
            { "Application data", "dpnet.application_data",
601
14
            FT_BYTES, BASE_NONE,
602
14
            NULL, 0,
603
14
            NULL, HFILL }
604
14
        },
605
14
        { &hf_dpnet_instance,
606
14
            { "Instance GUID", "dpnet.instance",
607
14
            FT_GUID, BASE_NONE,
608
14
            NULL, 0,
609
14
            NULL, HFILL }
610
14
        },
611
14
        { &hf_dpnet_data_command,
612
14
            { "Command", "dpnet.command",
613
14
            FT_UINT8, BASE_HEX,
614
14
            NULL, 0,
615
14
            NULL, HFILL }
616
14
        },
617
14
        { &hf_dpnet_data_cframe_control,
618
14
            { "Control", "dpnet.cframe.control",
619
14
            FT_UINT8, BASE_HEX,
620
14
            VALS(msg_cframe_control), 0,
621
14
            NULL, HFILL }
622
14
        },
623
14
        { &hf_dpnet_data_cframe_msgid,
624
14
            { "Message ID", "dpnet.cframe.msg_id",
625
14
            FT_UINT8, BASE_HEX,
626
14
            NULL, 0,
627
14
            NULL, HFILL }
628
14
        },
629
14
        { &hf_dpnet_data_cframe_rspid,
630
14
            { "Response ID", "dpnet.cframe.rsp_id",
631
14
            FT_UINT8, BASE_HEX,
632
14
            NULL, 0,
633
14
            NULL, HFILL }
634
14
        },
635
14
        { &hf_dpnet_data_cframe_protocol,
636
14
            { "Protocol", "dpnet.cframe.protocol",
637
14
            FT_UINT32, BASE_HEX,
638
14
            VALS(protocol_versions), 0,
639
14
            NULL, HFILL }
640
14
        },
641
14
        { &hf_dpnet_data_cframe_session,
642
14
            { "Session", "dpnet.cframe.session",
643
14
            FT_UINT32, BASE_HEX,
644
14
            NULL, 0,
645
14
            NULL, HFILL }
646
14
        },
647
14
        { &hf_dpnet_data_cframe_timestamp,
648
14
            { "Timestamp", "dpnet.cframe.timestamp",
649
14
            FT_UINT32, BASE_DEC,
650
14
            NULL, 0,
651
14
            NULL, HFILL }
652
14
        },
653
14
        { &hf_dpnet_data_cframe_padding,
654
14
            { "Padding", "dpnet.cframe.padding",
655
14
            FT_UINT16, BASE_DEC,
656
14
            NULL, 0,
657
14
            NULL, HFILL }
658
14
        },
659
14
        { &hf_dpnet_data_cframe_flags,
660
14
            { "Flags", "dpnet.cframe.flags",
661
14
            FT_UINT8, BASE_HEX,
662
14
            VALS(sack_flags), 0,
663
14
            NULL, HFILL }
664
14
        },
665
14
        { &hf_dpnet_data_cframe_retry,
666
14
            { "Retry", "dpnet.cframe.retry",
667
14
            FT_UINT8, BASE_HEX,
668
14
            NULL, 0,
669
14
            NULL, HFILL }
670
14
        },
671
14
        { &hf_dpnet_data_cframe_nseq,
672
14
            { "Next Sequence", "dpnet.cframe.nseq",
673
14
            FT_UINT8, BASE_HEX,
674
14
            NULL, 0,
675
14
            NULL, HFILL }
676
14
        },
677
14
        { &hf_dpnet_data_cframe_nrcv,
678
14
            { "Received", "dpnet.cframe.nrcv",
679
14
            FT_UINT8, BASE_HEX,
680
14
            NULL, 0,
681
14
            NULL, HFILL }
682
14
        },
683
14
        { &hf_dpnet_data_cframe_sack_mask1,
684
14
            { "SACK Mask1", "dpnet.cframe.sack.mask1",
685
14
            FT_UINT32, BASE_HEX,
686
14
            NULL, 0,
687
14
            NULL, HFILL }
688
14
        },
689
14
        { &hf_dpnet_data_cframe_sack_mask2,
690
14
            { "SACK Mask2", "dpnet.cframe.sack.mask2",
691
14
            FT_UINT32, BASE_HEX,
692
14
            NULL, 0,
693
14
            NULL, HFILL }
694
14
        },
695
14
        { &hf_dpnet_data_cframe_send_mask1,
696
14
            { "Send Mask1", "dpnet.cframe.send.mask1",
697
14
            FT_UINT32, BASE_HEX,
698
14
            NULL, 0,
699
14
            NULL, HFILL }
700
14
        },
701
14
        { &hf_dpnet_data_cframe_send_mask2,
702
14
            { "Send Mask2", "dpnet.cframe.send.mask2",
703
14
            FT_UINT32, BASE_HEX,
704
14
            NULL, 0,
705
14
            NULL, HFILL }
706
14
        },
707
14
        { &hf_dpnet_data_cframe_signature,
708
14
            { "Signature", "dpnet.cframe.signature",
709
14
            FT_UINT64, BASE_HEX,
710
14
            NULL, 0,
711
14
            NULL, HFILL }
712
14
        },
713
14
        { &hf_dpnet_data_cframe_send_secret,
714
14
            { "Sender Secret", "dpnet.cframe.sender_secret",
715
14
            FT_UINT64, BASE_HEX,
716
14
            NULL, 0,
717
14
            NULL, HFILL }
718
14
        },
719
14
        { &hf_dpnet_data_cframe_recv_secret,
720
14
            { "Receiver Secret", "dpnet.cframe.receiver_secret",
721
14
            FT_UINT64, BASE_HEX,
722
14
            NULL, 0,
723
14
            NULL, HFILL }
724
14
        },
725
14
        { &hf_dpnet_data_cframe_signing_opts,
726
14
            { "Signing Options", "dpnet.cframe.sign_opt",
727
14
            FT_UINT32, BASE_HEX,
728
14
            VALS(signing_opts), 0,
729
14
            NULL, HFILL }
730
14
        },
731
14
        { &hf_dpnet_data_cframe_echo_time,
732
14
            { "Signing Options", "dpnet.cframe.echo_time",
733
14
            FT_UINT32, BASE_HEX,
734
14
            NULL, 0,
735
14
            NULL, HFILL }
736
14
        },
737
14
        { &hf_dpnet_data_seq,
738
14
            { "Sequence", "dpnet.sequence",
739
14
            FT_UINT8, BASE_HEX,
740
14
            NULL, 0,
741
14
            NULL, HFILL }
742
14
        },
743
14
        { &hf_dpnet_data_nseq,
744
14
            { "Next Sequence", "dpnet.next",
745
14
            FT_UINT8, BASE_HEX,
746
14
            NULL, 0,
747
14
            NULL, HFILL }
748
14
        },
749
14
        {&hf_dpnet_command_data,
750
14
            {"Control Data", "dpnet.control.data",
751
14
            FT_BOOLEAN, 8,
752
14
            NULL, DPNET_COMMAND_DATA,
753
14
            NULL, HFILL}
754
14
        },
755
14
        {&hf_dpnet_command_reliable,
756
14
            {"Reliable", "dpnet.control.reliable",
757
14
            FT_BOOLEAN, 8,
758
14
            NULL, DPNET_COMMAND_RELIABLE,
759
14
            NULL, HFILL}
760
14
        },
761
14
        {&hf_dpnet_command_seq,
762
14
            {"Sequential", "dpnet.control.sequential",
763
14
            FT_BOOLEAN, 8,
764
14
            NULL, DPNET_COMMAND_SEQUENTIAL,
765
14
            NULL, HFILL}
766
14
        },
767
14
        {&hf_dpnet_command_poll,
768
14
            {"Poll", "dpnet.control.poll",
769
14
            FT_BOOLEAN, 8,
770
14
            NULL, DPNET_COMMAND_POLL,
771
14
            NULL, HFILL}
772
14
        },
773
14
        {&hf_dpnet_command_new_msg,
774
14
            {"New Message", "dpnet.control.new_msg",
775
14
            FT_BOOLEAN, 8,
776
14
            NULL, DPNET_COMMAND_NEW_MSG,
777
14
            NULL, HFILL}
778
14
        },
779
14
        {&hf_dpnet_command_end_msg,
780
14
            {"End Message", "dpnet.control.end_msg",
781
14
            FT_BOOLEAN, 8,
782
14
            NULL, DPNET_COMMAND_END_MSG,
783
14
            NULL, HFILL}
784
14
        },
785
14
        {&hf_dpnet_command_user1,
786
14
            {"User 1", "dpnet.control.user1",
787
14
            FT_BOOLEAN, 8,
788
14
            NULL, DPNET_COMMAND_USER_1,
789
14
            NULL, HFILL}
790
14
        },
791
14
        {&hf_dpnet_command_user2,
792
14
            {"CFrame", "dpnet.control.cframe",
793
14
            FT_BOOLEAN, 8,
794
14
            NULL, DPNET_COMMAND_CFRAME,
795
14
            NULL, HFILL}
796
14
        },
797
14
        {&hf_dpnet_desc_client_server,
798
14
            {"Client", "dpnet.session.client",
799
14
            FT_BOOLEAN, 16,
800
14
            TFS(&tfs_flags_game_client), SESSION_CLIENT_SERVER,
801
14
            NULL, HFILL}
802
14
        },
803
14
        {&hf_dpnet_desc_migrate_host,
804
14
            {"Migrate", "dpnet.session.migrate",
805
14
            FT_BOOLEAN, 16,
806
14
            TFS(&tfs_flags_migrate), SESSION_MIGRATE_HOST,
807
14
            NULL, HFILL}
808
14
        },
809
14
        {&hf_dpnet_desc_nodpnsvr,
810
14
            {"dpnsvr", "dpnet.session.dpnsvr",
811
14
            FT_BOOLEAN, 16,
812
14
            TFS(&tfs_flags_dpnsvr), SESSION_NODPNSVR,
813
14
            NULL, HFILL}
814
14
        },
815
14
        {&hf_dpnet_desc_req_password,
816
14
            {"Password", "dpnet.session.password",
817
14
            FT_BOOLEAN, 16,
818
14
            TFS(&tfs_flags_password_required), SESSION_REQUIREPASSWORD,
819
14
            NULL, HFILL}
820
14
        },
821
14
        {&hf_dpnet_desc_no_enums,
822
14
            {"Enumeration", "dpnet.session.enumeration",
823
14
            FT_BOOLEAN, 16,
824
14
            TFS(&tfs_flags_enumeration), SESSION_NOENUMS,
825
14
            NULL, HFILL}
826
14
        },
827
14
        {&hf_dpnet_desc_fast_signed,
828
14
            {"Fast signing", "dpnet.session.fast_sign",
829
14
            FT_BOOLEAN, 16,
830
14
            TFS(&tfs_flags_fast), SESSION_FAST_SIGNED,
831
14
            NULL, HFILL}
832
14
        },
833
14
        {&hf_dpnet_desc_full_signed,
834
14
            {"Full signing", "dpnet.session.full_sign",
835
14
            FT_BOOLEAN, 16,
836
14
            TFS(&tfs_flags_full), SESSION_FULL_SIGNED,
837
14
            NULL, HFILL}
838
14
        },
839
14
    };
840
841
    /* Setup protocol subtree array */
842
14
    static int *ett[] = {
843
14
        &ett_dpnet,
844
14
        &ett_dpnet_command_flags,
845
14
        &ett_dpnet_desc_flags
846
14
    };
847
848
849
14
    proto_dpnet = proto_register_protocol ("DirectPlay 8 protocol", "DPNET", "dpnet");
850
851
14
    proto_register_field_array(proto_dpnet, hf, array_length(hf));
852
14
    proto_register_subtree_array(ett, array_length(ett));
853
854
14
    dpnet_handle = register_dissector("dpnet", dissect_dpnet, proto_dpnet);
855
14
}
856
857
void
858
proto_reg_handoff_dpnet(void)
859
14
{
860
14
    dissector_add_uint("udp.port", DPNET_PORT, dpnet_handle);
861
14
}
862
863
/*
864
 * Editor modelines
865
 *
866
 * Local Variables:
867
 * c-basic-offset: 4
868
 * tab-width: 8
869
 * indent-tabs-mode: nil
870
 * End:
871
 *
872
 * ex: set shiftwidth=4 tabstop=8 expandtab:
873
 * :indentSize=4:tabSize=8:noTabs=true:
874
 */