Coverage Report

Created: 2025-02-15 06:25

/src/wireshark/epan/dissectors/packet-raknet.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * packet-raknet.c
3
 *
4
 * Routines for RakNet protocol packet disassembly.
5
 *
6
 * Ref: https://github.com/OculusVR/RakNet
7
 *
8
 * Nick Carter <ncarter100@gmail.com>
9
 * Copyright 2014 Nick Carter
10
 *
11
 * Wireshark - Network traffic analyzer
12
 * By Gerald Combs <gerald@wireshark.org>
13
 * Copyright 1998 Gerald Combs
14
 *
15
 * SPDX-License-Identifier: GPL-2.0-or-later
16
 */
17
#include "config.h"
18
19
#include <epan/conversation.h>
20
#include <epan/expert.h>
21
#include <epan/packet.h>
22
#include <epan/reassemble.h>
23
#include <epan/to_str.h>
24
#include <epan/wmem_scopes.h>
25
#include <wsutil/array.h>
26
27
#include "packet-raknet.h"
28
29
/*
30
 * RakNet Protocol Constants.
31
 */
32
static uint8_t RAKNET_OFFLINE_MESSAGE_DATA_ID[16] = {0x00, 0xff, 0xff, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0xfd, 0xfd, 0xfd, 0xfd, 0x12, 0x34, 0x56, 0x78};
33
#define RAKNET_CHALLENGE_LENGTH 64
34
#define RAKNET_ANSWER_LENGTH 128
35
#define RAKNET_PROOF_LENGTH 32
36
#define RAKNET_IDENTITY_LENGTH 160
37
0
#define RAKNET_NUMBER_OF_INTERNAL_IDS 10
38
39
static int proto_raknet;
40
static int ett_raknet; /* Should this node be expanded */
41
static int ett_raknet_system_address;
42
static int ett_raknet_packet_type;
43
static int ett_raknet_packet_number_range;
44
static int ett_raknet_message;
45
static int ett_raknet_message_flags;
46
static int ett_raknet_system_message;
47
48
/*
49
 * Dissectors
50
 */
51
static dissector_handle_t raknet_handle;
52
static dissector_table_t raknet_offline_message_dissectors;
53
static dissector_table_t raknet_system_message_dissectors;
54
static dissector_table_t raknet_port_dissectors;
55
static heur_dissector_list_t raknet_heur_subdissectors;
56
57
/*
58
 * Expert fields
59
 */
60
static expert_field ei_raknet_unknown_message_id;
61
static expert_field ei_raknet_encrypted_message;
62
static expert_field ei_raknet_subdissector_failed;
63
static expert_field ei_raknet_ip_ver_invalid;
64
65
/*
66
 * First byte gives us the packet id
67
 */
68
static int hf_raknet_offline_message_id;
69
70
/*
71
 * General fields (fields that are in >1 packet types.
72
 */
73
static int hf_raknet_client_guid;
74
static int hf_raknet_timestamp;
75
static int hf_raknet_offline_message_data_id;
76
static int hf_raknet_mtu_size;
77
static int hf_raknet_raknet_proto_ver;
78
static int hf_raknet_server_guid;
79
static int hf_raknet_ip_version;
80
static int hf_raknet_ipv4_address;
81
static int hf_raknet_ipv6_address;
82
static int hf_raknet_port;
83
84
/*
85
 * Fields specific to a packet id type
86
 */
87
static int hf_raknet_null_padding;
88
static int hf_raknet_use_encryption;
89
static int hf_raknet_server_public_key;
90
static int hf_raknet_cookie;
91
static int hf_raknet_client_wrote_challenge;
92
static int hf_raknet_client_challenge;
93
static int hf_raknet_client_address;
94
static int hf_raknet_server_address;
95
static int hf_raknet_server_answer;
96
static int hf_raknet_0x1C_server_id_str_len;
97
static int hf_raknet_0x1C_server_id_str;
98
static int hf_raknet_packet_type;
99
static int hf_raknet_packet_is_for_connected;
100
static int hf_raknet_packet_is_ACK;
101
static int hf_raknet_packet_has_B_and_AS;
102
static int hf_raknet_packet_is_NAK;
103
static int hf_raknet_packet_is_pair;
104
static int hf_raknet_packet_is_continuous_send;
105
static int hf_raknet_packet_needs_B_and_AS;
106
static int hf_raknet_AS;
107
static int hf_raknet_NACK_record_count;
108
static int hf_raknet_packet_number_range;
109
static int hf_raknet_range_max_equal_to_min;
110
static int hf_raknet_packet_number_min;
111
static int hf_raknet_packet_number_max;
112
static int hf_raknet_packet_number;
113
static int hf_raknet_message;
114
static int hf_raknet_message_flags;
115
static int hf_raknet_message_reliability;
116
static int hf_raknet_message_has_split_packet;
117
static int hf_raknet_payload_length;
118
static int hf_raknet_reliable_message_number;
119
static int hf_raknet_message_sequencing_index;
120
static int hf_raknet_message_ordering_index;
121
static int hf_raknet_message_ordering_channel;
122
static int hf_raknet_split_packet_count;
123
static int hf_raknet_split_packet_id;
124
static int hf_raknet_split_packet_index;
125
static int hf_raknet_split_packet;
126
static int hf_raknet_system_message;
127
static int hf_raknet_system_message_id;
128
static int hf_raknet_client_proof;
129
static int hf_raknet_use_client_key;
130
static int hf_raknet_client_identity;
131
static int hf_raknet_password;
132
static int hf_raknet_system_index;
133
static int hf_raknet_internal_address;
134
135
/*
136
 * Frame reassembly
137
 */
138
static reassembly_table raknet_reassembly_table;
139
140
static int ett_raknet_fragment;
141
static int ett_raknet_fragments;
142
static int hf_raknet_fragment;
143
static int hf_raknet_fragment_count;
144
static int hf_raknet_fragment_error;
145
static int hf_raknet_fragment_multiple_tails;
146
static int hf_raknet_fragment_overlap;
147
static int hf_raknet_fragment_overlap_conflicts;
148
static int hf_raknet_fragment_too_long_fragment;
149
static int hf_raknet_fragments;
150
static int hf_raknet_reassembled_in;
151
static int hf_raknet_reassembled_length;
152
153
static const fragment_items raknet_frag_items = {
154
    /* Fragment subtrees */
155
    &ett_raknet_fragment,
156
    &ett_raknet_fragments,
157
    /* Fragment fields */
158
    &hf_raknet_fragments,
159
    &hf_raknet_fragment,
160
    &hf_raknet_fragment_overlap,
161
    &hf_raknet_fragment_overlap_conflicts,
162
    &hf_raknet_fragment_multiple_tails,
163
    &hf_raknet_fragment_too_long_fragment,
164
    &hf_raknet_fragment_error,
165
    &hf_raknet_fragment_count,
166
    /* Reassembled in field */
167
    &hf_raknet_reassembled_in,
168
    /* Reassembled length field */
169
    &hf_raknet_reassembled_length,
170
    /* Reassembled data field */
171
    NULL,
172
    /* Tag */
173
    "Message fragments"
174
};
175
176
/*
177
 * Session state
178
 */
179
typedef struct raknet_session_state {
180
    bool use_encryption;
181
    dissector_handle_t subdissector;
182
} raknet_session_state_t;
183
184
/*
185
 * Reliability strings
186
 * Ref: ..RakNet/Source/PacketPriority.h
187
 *
188
 * Note that ACK receipts will not be transmitted to the wire. See
189
 * ReliabilityLayer::WriteToBitStreamFromInternalPacket()
190
 */
191
#define raknet_reliability_VALUE_STRING_LIST(VS)                 \
192
    VS( RAKNET_UNRELIABLE          , 0, "unreliable"           ) \
193
    VS( RAKNET_UNRELIABLE_SEQUENCED, 1, "unreliable sequenced" ) \
194
    VS( RAKNET_RELIABLE            , 2, "reliable"             ) \
195
    VS( RAKNET_RELIABLE_ORDERED    , 3, "reliable ordered"     ) \
196
    VS( RAKNET_RELIABLE_SEQUENCED  , 4, "reliable sequenced"   )
197
198
typedef VALUE_STRING_ENUM(raknet_reliability) raknet_reliability_t;
199
VALUE_STRING_ARRAY(raknet_reliability);
200
201
/*
202
 * Forward declarations.
203
 */
204
void proto_register_raknet(void);
205
void proto_reg_handoff_raknet(void);
206
static proto_tree *init_raknet_offline_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset);
207
208
209
/*
210
 * Called by dissectors for protocols that run atop RakNet/UDP.
211
 */
212
void
213
14
raknet_add_udp_dissector(uint32_t port, const dissector_handle_t handle) {
214
    /*
215
     * Register ourselves as the handler for that port number
216
     * over TCP.
217
     */
218
14
    dissector_add_uint("udp.port", port, raknet_handle);
219
220
    /*
221
     * And register them in *our* table for that port.
222
     */
223
14
    dissector_add_uint("raknet.port", port, handle);
224
14
}
225
226
void
227
0
raknet_delete_udp_dissector(uint32_t port, const dissector_handle_t handle) {
228
0
    dissector_delete_uint("udp.port", port, raknet_handle);
229
0
    dissector_delete_uint("raknet.port", port, handle);
230
0
}
231
232
static raknet_session_state_t*
233
53
raknet_get_session_state(packet_info *pinfo) {
234
53
    conversation_t* conversation;
235
53
    raknet_session_state_t* state;
236
237
53
    conversation = find_or_create_conversation(pinfo);
238
53
    state = (raknet_session_state_t*)conversation_get_proto_data(conversation, proto_raknet);
239
240
53
    if (state == NULL) {
241
19
        state = wmem_new(wmem_file_scope(), raknet_session_state_t);
242
19
        state->use_encryption = false;
243
19
        state->subdissector = NULL;
244
19
        conversation_add_proto_data(conversation, proto_raknet, state);
245
19
    }
246
247
53
    return state;
248
53
}
249
250
void
251
0
raknet_conversation_set_dissector(packet_info *pinfo, const dissector_handle_t handle) {
252
0
    raknet_session_state_t *state;
253
254
0
    state = raknet_get_session_state(pinfo);
255
0
    state->subdissector = handle;
256
0
}
257
258
static void
259
raknet_dissect_system_address(proto_tree *tree, int hf,
260
1
        packet_info *pinfo, tvbuff_t *tvb, int *offset) {
261
1
    proto_item *ti;
262
1
    proto_tree *sub_tree;
263
1
    uint8_t ip_version;
264
1
    uint32_t v4_addr;
265
1
    uint16_t port;
266
1
    address addr;
267
1
    char *addr_str;
268
269
    /* XXX - does it really make sense to have a string hf that's set to
270
       an empty string? */
271
1
    ti = proto_tree_add_string(tree, hf, tvb, *offset, -1, "");
272
1
    sub_tree = proto_item_add_subtree(ti, ett_raknet_system_address);
273
1
    ip_version = tvb_get_uint8(tvb, *offset);
274
1
    proto_tree_add_item(sub_tree, hf_raknet_ip_version, tvb, *offset, 1, ENC_NA);
275
1
    (*offset)++;
276
1
    switch (ip_version) {
277
0
    case 4:
278
        /*
279
         * IPv4 addresses are bit-inverted to prevent routers from
280
         * changing them. See ..RakNet/Source/BitStream.h
281
         * (BitStream::Write)
282
         */
283
0
        v4_addr = ~tvb_get_ipv4(tvb, *offset);
284
0
        set_address(&addr, AT_IPv4, sizeof(v4_addr), &v4_addr);
285
0
        addr_str = address_to_display(pinfo->pool, &addr);
286
0
        proto_tree_add_ipv4(sub_tree, hf_raknet_ipv4_address, tvb, *offset, 4, v4_addr);
287
0
        *offset += 4;
288
0
        port = tvb_get_ntohs(tvb, *offset);
289
0
        proto_tree_add_item(sub_tree, hf_raknet_port, tvb, *offset, 2, ENC_BIG_ENDIAN);
290
0
        *offset += 2;
291
0
        proto_item_set_len(ti, 1 + 4 + 2);
292
0
        proto_item_append_text(ti, "%s:%" PRIu16, addr_str, port);
293
0
        break;
294
0
    case 6:
295
0
        addr_str = tvb_ip6_to_str(pinfo->pool, tvb, *offset);
296
0
        proto_tree_add_item(sub_tree, hf_raknet_ipv6_address, tvb, *offset, 16, ENC_NA);
297
0
        *offset += 16;
298
0
        port = tvb_get_ntohs(tvb, *offset);
299
0
        proto_tree_add_item(sub_tree, hf_raknet_port, tvb, *offset, 2, ENC_BIG_ENDIAN);
300
0
        *offset += 2;
301
0
        proto_item_set_len(ti, 1 + 16 + 2);
302
0
        proto_item_append_text(ti, "[%s]:%" PRIu16, addr_str, port);
303
0
        break;
304
1
    default:
305
1
        proto_item_set_len(ti, 1);
306
1
        expert_add_info(pinfo, sub_tree, &ei_raknet_ip_ver_invalid);
307
1
    }
308
1
}
309
310
static int
311
raknet_dissect_unconnected_ping(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
312
                                void *data _U_)
313
1
{
314
1
    proto_tree *sub_tree;
315
1
    int offset;
316
317
1
    sub_tree = init_raknet_offline_message(tvb, pinfo, tree, &offset);
318
319
1
    proto_tree_add_item(sub_tree, hf_raknet_timestamp, tvb,
320
1
                        offset, 8, ENC_BIG_ENDIAN);
321
1
    offset += 8;
322
323
1
    proto_tree_add_item(sub_tree, hf_raknet_offline_message_data_id, tvb, offset,
324
1
                        16, ENC_NA);
325
1
    offset += 16;
326
327
1
    proto_tree_add_item(sub_tree, hf_raknet_client_guid, tvb,
328
1
                        offset, 8, ENC_NA);
329
1
    offset += 8;
330
331
1
    return offset;
332
1
}
333
334
static int
335
raknet_dissect_open_connection_request_1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
336
                                         void *data _U_)
337
0
{
338
0
    proto_tree *sub_tree;
339
0
    int offset;
340
341
0
    sub_tree = init_raknet_offline_message(tvb, pinfo, tree, &offset);
342
343
0
    proto_tree_add_item(sub_tree, hf_raknet_offline_message_data_id, tvb, offset,
344
0
                        16, ENC_NA);
345
0
    offset += 16;
346
347
0
    proto_tree_add_item(sub_tree, hf_raknet_raknet_proto_ver, tvb, offset,
348
0
                        1, ENC_BIG_ENDIAN);
349
0
    offset += 1;
350
351
    /* -1 read to end of tvb buffer */
352
0
    proto_tree_add_item(sub_tree, hf_raknet_null_padding, tvb, offset,
353
0
                        -1, ENC_NA);
354
355
0
    return tvb_reported_length(tvb);
356
0
}
357
358
static int
359
raknet_dissect_open_connection_reply_1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
360
                                       void *data _U_)
361
1
{
362
1
    proto_tree *sub_tree;
363
1
    int offset;
364
1
    raknet_session_state_t* state;
365
366
1
    sub_tree = init_raknet_offline_message(tvb, pinfo, tree, &offset);
367
368
369
1
    proto_tree_add_item(sub_tree, hf_raknet_offline_message_data_id, tvb, offset,
370
1
                        16, ENC_NA);
371
1
    offset += 16;
372
373
1
    proto_tree_add_item(sub_tree, hf_raknet_server_guid, tvb, offset,
374
1
                        8, ENC_NA);
375
1
    offset += 8;
376
377
1
    state = raknet_get_session_state(pinfo);
378
1
    state->use_encryption = tvb_get_uint8(tvb, offset) ? true : false;
379
380
1
    proto_tree_add_item(sub_tree, hf_raknet_use_encryption, tvb,
381
1
                        offset, 1, ENC_NA);
382
1
    offset += 1;
383
384
1
    if (state->use_encryption) {
385
1
        proto_tree_add_item(sub_tree, hf_raknet_cookie, tvb,
386
1
                            offset, 4, ENC_BIG_ENDIAN);
387
1
        offset += 4;
388
389
1
        proto_tree_add_item(sub_tree, hf_raknet_server_public_key, tvb,
390
1
                            offset, 64, ENC_NA);
391
1
        offset += 64;
392
1
    }
393
394
1
    proto_tree_add_item(sub_tree, hf_raknet_mtu_size, tvb, offset,
395
1
                        2, ENC_BIG_ENDIAN);
396
1
    offset += 2;
397
398
1
    return offset;
399
1
}
400
401
static int
402
raknet_dissect_open_connection_request_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
403
                                         void *data _U_)
404
1
{
405
1
    proto_tree *sub_tree;
406
1
    int offset;
407
1
    raknet_session_state_t* state;
408
409
1
    sub_tree = init_raknet_offline_message(tvb, pinfo, tree, &offset);
410
411
1
    proto_tree_add_item(sub_tree, hf_raknet_offline_message_data_id, tvb, offset,
412
1
                        16, ENC_NA);
413
1
    offset += 16;
414
415
1
    state = raknet_get_session_state(pinfo);
416
1
    if (state->use_encryption) {
417
0
        bool client_wrote_challenge;
418
419
0
        proto_tree_add_item(sub_tree, hf_raknet_cookie, tvb, offset,
420
0
                            4, ENC_BIG_ENDIAN);
421
0
        offset += 4;
422
423
0
        client_wrote_challenge = tvb_get_uint8(tvb, offset) ? true : false;
424
0
        proto_tree_add_item(sub_tree, hf_raknet_client_wrote_challenge, tvb, offset,
425
0
                            1, ENC_NA);
426
0
        offset += 1;
427
428
0
        if (client_wrote_challenge) {
429
0
            proto_tree_add_item(sub_tree, hf_raknet_client_challenge, tvb,
430
0
                                offset, 64, ENC_NA);
431
0
            offset += 64;
432
0
        }
433
0
    }
434
435
1
    raknet_dissect_system_address(
436
1
            sub_tree, hf_raknet_server_address, pinfo, tvb, &offset);
437
438
1
    proto_tree_add_item(sub_tree, hf_raknet_mtu_size, tvb, offset,
439
1
                        2, ENC_BIG_ENDIAN);
440
1
    offset += 2;
441
442
1
    proto_tree_add_item(sub_tree, hf_raknet_client_guid, tvb, offset,
443
1
                        8, ENC_NA);
444
1
    offset += 8;
445
446
1
    return offset;
447
1
}
448
449
static int
450
raknet_dissect_open_connection_reply_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
451
                                       void *data _U_)
452
0
{
453
0
    proto_tree *sub_tree;
454
0
    int offset;
455
0
    raknet_session_state_t* state;
456
457
0
    sub_tree = init_raknet_offline_message(tvb, pinfo, tree, &offset);
458
459
0
    proto_tree_add_item(sub_tree, hf_raknet_offline_message_data_id, tvb, offset,
460
0
                        16, ENC_NA);
461
0
    offset += 16;
462
463
0
    proto_tree_add_item(sub_tree, hf_raknet_server_guid, tvb, offset,
464
0
                        8, ENC_NA);
465
0
    offset += 8;
466
467
0
    raknet_dissect_system_address(
468
0
            sub_tree, hf_raknet_client_address, pinfo, tvb, &offset);
469
470
0
    proto_tree_add_item(sub_tree, hf_raknet_mtu_size, tvb, offset,
471
0
                        2, ENC_BIG_ENDIAN);
472
0
    offset += 2;
473
474
0
    state = raknet_get_session_state(pinfo);
475
0
    state->use_encryption = tvb_get_uint8(tvb, offset) ? true : false;
476
477
0
    proto_tree_add_item(sub_tree, hf_raknet_use_encryption, tvb, offset,
478
0
                        1, ENC_NA);
479
0
    offset += 1;
480
481
0
    if (state->use_encryption) {
482
0
        proto_tree_add_item(sub_tree, hf_raknet_server_answer, tvb, offset,
483
0
                            128, ENC_NA);
484
0
        offset += 128;
485
0
    }
486
487
0
    return offset;
488
0
}
489
490
static int
491
raknet_dissect_incompatible_protocol_version(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
492
                                             void *data _U_)
493
0
{
494
0
    proto_tree *sub_tree;
495
0
    int offset;
496
497
0
    sub_tree = init_raknet_offline_message(tvb, pinfo, tree, &offset);
498
499
0
    proto_tree_add_item(sub_tree, hf_raknet_raknet_proto_ver, tvb,
500
0
                        offset, 1, ENC_BIG_ENDIAN);
501
0
    offset += 1;
502
503
0
    proto_tree_add_item(sub_tree, hf_raknet_offline_message_data_id, tvb, offset,
504
0
                        16, ENC_NA);
505
0
    offset += 16;
506
507
0
    proto_tree_add_item(sub_tree, hf_raknet_server_guid, tvb, offset,
508
0
                        8, ENC_NA);
509
0
    offset += 8;
510
511
0
    return offset;
512
0
}
513
514
static int
515
raknet_dissect_connection_failed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
516
                                 void *data _U_)
517
1
{
518
1
    proto_tree *sub_tree;
519
1
    int offset;
520
521
1
    sub_tree = init_raknet_offline_message(tvb, pinfo, tree, &offset);
522
523
1
    proto_tree_add_item(sub_tree, hf_raknet_offline_message_data_id, tvb, offset,
524
1
                        16, ENC_NA);
525
1
    offset += 16;
526
527
1
    proto_tree_add_item(sub_tree, hf_raknet_server_guid, tvb, offset,
528
1
                        8, ENC_NA);
529
1
    offset += 8;
530
531
1
    return offset;
532
1
}
533
534
static int
535
raknet_dissect_unconnected_pong(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
536
                                void *data _U_)
537
1
{
538
1
    proto_tree *sub_tree;
539
1
    uint32_t str_size;
540
1
    int offset;
541
542
1
    sub_tree = init_raknet_offline_message(tvb, pinfo, tree, &offset);
543
544
1
    proto_tree_add_item(sub_tree, hf_raknet_timestamp, tvb,
545
1
                        offset, 8, ENC_BIG_ENDIAN);
546
1
    offset += 8;
547
548
1
    proto_tree_add_item(sub_tree, hf_raknet_server_guid, tvb, offset,
549
1
                        8, ENC_NA);
550
1
    offset += 8;
551
552
1
    proto_tree_add_item(sub_tree, hf_raknet_offline_message_data_id, tvb, offset,
553
1
                        16, ENC_NA);
554
1
    offset += 16;
555
556
    /* raknet precedes strings with a short (2 bytes) holding string length. */
557
1
    proto_tree_add_item_ret_uint(sub_tree, hf_raknet_0x1C_server_id_str_len, tvb,
558
1
                                 offset, 2, ENC_BIG_ENDIAN, &str_size);
559
1
    offset += 2;
560
561
1
    proto_tree_add_item(sub_tree, hf_raknet_0x1C_server_id_str, tvb, offset,
562
1
                        str_size, ENC_NA|ENC_ASCII);
563
1
    offset += str_size;
564
565
1
    return offset;
566
1
}
567
568
static int
569
raknet_dissect_connected_ping(tvbuff_t *tvb, packet_info *pinfo _U_,
570
                              proto_tree *tree, void* data _U_)
571
1
{
572
573
1
    int offset = 1;
574
575
1
    proto_tree_add_item(tree, hf_raknet_timestamp, tvb,
576
1
                        offset, 8, ENC_BIG_ENDIAN);
577
1
    offset += 8;
578
579
1
    return offset;
580
1
}
581
582
static int
583
raknet_dissect_connected_pong(tvbuff_t *tvb, packet_info *pinfo _U_,
584
                              proto_tree *tree, void* data _U_)
585
5
{
586
5
    int offset = 1;
587
588
5
    proto_tree_add_item(tree, hf_raknet_timestamp, tvb,
589
5
                        offset, 8, ENC_BIG_ENDIAN);
590
5
    offset += 8;
591
592
5
    proto_tree_add_item(tree, hf_raknet_timestamp, tvb,
593
5
                        offset, 8, ENC_BIG_ENDIAN);
594
5
    offset += 8;
595
596
5
    return offset;
597
5
}
598
599
static int
600
raknet_dissect_connection_request(tvbuff_t *tvb, packet_info *pinfo _U_,
601
                                  proto_tree *tree, void* data _U_)
602
0
{
603
0
    int offset = 1;
604
0
    bool use_encryption;
605
606
0
    proto_tree_add_item(tree, hf_raknet_client_guid, tvb, offset,
607
0
                        8, ENC_NA);
608
0
    offset += 8;
609
610
0
    proto_tree_add_item(tree, hf_raknet_timestamp, tvb,
611
0
                        offset, 8, ENC_BIG_ENDIAN);
612
0
    offset += 8;
613
614
0
    use_encryption = tvb_get_uint8(tvb, offset) ? true : false;
615
616
0
    proto_tree_add_item(tree, hf_raknet_use_encryption, tvb, offset,
617
0
                        1, ENC_NA);
618
0
    offset += 1;
619
620
0
    if (use_encryption) {
621
0
        bool use_client_key;
622
623
0
        proto_tree_add_item(tree, hf_raknet_client_proof, tvb, offset,
624
0
                            32, ENC_NA);
625
0
        offset += 32;
626
627
0
        use_client_key = tvb_get_uint8(tvb, offset) ? true : false;
628
629
0
        proto_tree_add_item(tree, hf_raknet_use_client_key, tvb, offset,
630
0
                            1, ENC_NA);
631
0
        offset += 1;
632
633
0
        if (use_client_key) {
634
0
            proto_tree_add_item(tree, hf_raknet_client_identity, tvb, offset,
635
0
                                160, ENC_NA);
636
0
            offset += 160;
637
0
        }
638
0
    }
639
640
0
    proto_tree_add_item(tree, hf_raknet_password, tvb, offset,
641
0
                       -1, ENC_NA);
642
643
0
    return tvb_reported_length(tvb);
644
0
}
645
646
static int
647
raknet_dissect_connection_request_accepted(tvbuff_t *tvb, packet_info *pinfo _U_,
648
                                           proto_tree *tree, void* data _U_)
649
0
{
650
0
    int offset = 1;
651
0
    int i;
652
653
0
    raknet_dissect_system_address(
654
0
            tree, hf_raknet_client_address, pinfo, tvb, &offset);
655
656
0
    proto_tree_add_item(tree, hf_raknet_system_index, tvb, offset,
657
0
                        2, ENC_BIG_ENDIAN);
658
0
    offset += 2;
659
660
0
    for (i = 0; i < RAKNET_NUMBER_OF_INTERNAL_IDS; i++) {
661
0
        raknet_dissect_system_address(
662
0
                tree, hf_raknet_internal_address, pinfo, tvb, &offset);
663
0
    }
664
665
0
    proto_tree_add_item(tree, hf_raknet_timestamp, tvb,
666
0
                        offset, 8, ENC_BIG_ENDIAN);
667
0
    offset += 8;
668
669
0
    proto_tree_add_item(tree, hf_raknet_timestamp, tvb,
670
0
                        offset, 8, ENC_BIG_ENDIAN);
671
0
    offset += 8;
672
673
0
    return offset;
674
0
}
675
676
static int
677
raknet_dissect_new_incoming_connection(tvbuff_t *tvb, packet_info *pinfo,
678
                                       proto_tree *tree, void* data _U_)
679
0
{
680
681
0
    int offset = 1;
682
0
    int i;
683
684
0
    raknet_dissect_system_address(
685
0
            tree, hf_raknet_server_address, pinfo, tvb, &offset);
686
687
0
    for (i = 0; i < RAKNET_NUMBER_OF_INTERNAL_IDS; i++) {
688
0
        raknet_dissect_system_address(
689
0
                tree, hf_raknet_internal_address, pinfo, tvb, &offset);
690
0
    }
691
692
0
    proto_tree_add_item(tree, hf_raknet_timestamp, tvb,
693
0
                        offset, 8, ENC_BIG_ENDIAN);
694
0
    offset += 8;
695
696
0
    proto_tree_add_item(tree, hf_raknet_timestamp, tvb,
697
0
                        offset, 8, ENC_BIG_ENDIAN);
698
0
    offset += 8;
699
700
701
0
    return offset;
702
0
}
703
704
/*
705
 * Protocol definition and handlers.
706
 */
707
struct raknet_handler_entry {
708
    value_string vs;
709
    dissector_t dissector_fp;
710
};
711
712
static const struct raknet_handler_entry raknet_offline_message_handlers[] = {
713
    /*
714
     * Ref: ..RakNet/Source/MessageIdentifiers.h
715
     * Ref: ..RakNet/Source/RakPeer.cpp (ProcessOfflineNetworkPacket)
716
     */
717
    { { 0x1, "Unconnected Ping" },
718
        raknet_dissect_unconnected_ping },
719
    { { 0x2, "Unconnected Ping Open Connections" },
720
        raknet_dissect_unconnected_ping },
721
    { { 0x5, "Open Connection Request 1" },
722
        raknet_dissect_open_connection_request_1 },
723
    { { 0x6, "Open Connection Reply 1" },
724
        raknet_dissect_open_connection_reply_1 },
725
    { { 0x7, "Open Connection Request 2" },
726
        raknet_dissect_open_connection_request_2 },
727
    { { 0x8, "Open Connection Reply 2" },
728
        raknet_dissect_open_connection_reply_2 },
729
    { { 0xD, "Out Of Band Internal" },
730
        raknet_dissect_connection_failed },
731
    { { 0x11, "Connection Attempt Failed" },
732
        raknet_dissect_connection_failed },
733
    { { 0x12, "Already Connected" },
734
        raknet_dissect_connection_failed },
735
    { { 0x14, "No Free Incoming Connections" },
736
        raknet_dissect_connection_failed },
737
    { { 0x17, "Connection Banned" },
738
        raknet_dissect_connection_failed },
739
    { { 0x19, "Incompatible Protocol Version" },
740
        raknet_dissect_incompatible_protocol_version },
741
    { { 0x1A, "IP Recently Connected" },
742
        raknet_dissect_connection_failed },
743
    { { 0x1C, "Unconnected Pong" },
744
        raknet_dissect_unconnected_pong },
745
};
746
747
static const struct raknet_handler_entry raknet_system_message_handlers[] = {
748
    /*
749
     * Ref: ..RakNet/Source/MessageIdentifiers.h
750
     * Ref: ..RakNet/Source/RakPeer.cpp (RakPeer::RunUpdateCycle)
751
     */
752
    { { 0x00, "Connected Ping" },
753
        raknet_dissect_connected_ping },
754
    { { 0x03, "Connected Pong" },
755
        raknet_dissect_connected_pong },
756
    { { 0x09, "Connection Request" },
757
        raknet_dissect_connection_request },
758
    { { 0x10, "Connection Request Accepted" },
759
        raknet_dissect_connection_request_accepted },
760
    { { 0x13, "New Incoming Connection" },
761
        raknet_dissect_new_incoming_connection },
762
};
763
764
/*
765
 * Look up table from message ID to name.
766
 */
767
static value_string raknet_offline_message_names[array_length(raknet_offline_message_handlers)+1];
768
static value_string raknet_system_message_names[array_length(raknet_system_message_handlers)+1];
769
770
static void
771
raknet_init_message_names(void)
772
14
{
773
14
    unsigned int i;
774
775
210
    for (i = 0; i < array_length(raknet_offline_message_handlers); i++) {
776
196
        raknet_offline_message_names[i].value  = raknet_offline_message_handlers[i].vs.value;
777
196
        raknet_offline_message_names[i].strptr = raknet_offline_message_handlers[i].vs.strptr;
778
196
    }
779
14
    raknet_offline_message_names[array_length(raknet_offline_message_handlers)].value  = 0;
780
14
    raknet_offline_message_names[array_length(raknet_offline_message_handlers)].strptr = NULL;
781
782
84
    for (i = 0; i < array_length(raknet_system_message_handlers); i++) {
783
70
        raknet_system_message_names[i].value  = raknet_system_message_handlers[i].vs.value;
784
70
        raknet_system_message_names[i].strptr = raknet_system_message_handlers[i].vs.strptr;
785
70
    }
786
14
    raknet_system_message_names[array_length(raknet_system_message_handlers)].value  = 0;
787
14
    raknet_system_message_names[array_length(raknet_system_message_handlers)].strptr = NULL;
788
14
}
789
790
/*
791
 * Fill out the Info column and protocol subtree.
792
 *
793
 * Offset is updated for the caller.
794
 */
795
static proto_tree *
796
init_raknet_offline_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset)
797
5
{
798
5
    proto_tree *sub_tree;
799
5
    proto_item *ti;
800
5
    uint8_t message_id;
801
802
5
    *offset = 0;
803
804
    /*
805
     * Take buffer start 0 to end -1 as single raknet item.
806
     */
807
5
    ti = proto_tree_add_item(tree, proto_raknet, tvb, 0, -1, ENC_NA);
808
5
    sub_tree = proto_item_add_subtree(ti, ett_raknet);
809
810
5
    message_id = tvb_get_uint8(tvb, *offset);
811
5
    proto_tree_add_item(sub_tree, hf_raknet_offline_message_id, tvb, *offset,
812
5
                        1, ENC_BIG_ENDIAN);
813
5
    *offset += 1;
814
815
5
    col_add_str(pinfo->cinfo, COL_INFO,
816
5
                val_to_str(message_id, raknet_offline_message_names, "Unknown offline message: %#x"));
817
818
    /*
819
     * Append description to the raknet item.
820
     */
821
5
    proto_item_append_text(ti, ", Offline message ID %#x", message_id);
822
823
5
    return sub_tree;
824
5
}
825
826
static int
827
raknet_dissect_ACK(tvbuff_t *tvb, packet_info *pinfo,
828
                   proto_tree *tree, void* data)
829
12
{
830
12
    int offset = 0;
831
12
    proto_tree *sub_tree;
832
12
    uint32_t count;
833
12
    uint32_t i;
834
835
12
    if (*(bool*)data) {
836
10
        col_set_str(pinfo->cinfo, COL_INFO, "ACK");
837
10
    }
838
2
    else {
839
2
        col_set_str(pinfo->cinfo, COL_INFO, "NAK");
840
2
    }
841
842
12
    proto_tree_add_item_ret_uint(tree, hf_raknet_NACK_record_count, tvb,
843
12
                                 offset, 2, ENC_BIG_ENDIAN, &count);
844
12
    offset += 2;
845
846
674
    for (i = 0; i < count; i++) {
847
662
        proto_item *ti;
848
662
        uint32_t max;
849
662
        uint32_t min;
850
851
662
        if (i == 0) {
852
11
            col_append_str(pinfo->cinfo, COL_INFO, " ");
853
11
        }
854
651
        else {
855
651
            col_append_str(pinfo->cinfo, COL_INFO, ", ");
856
651
        }
857
858
662
        if (tvb_get_uint8(tvb, offset)) { /* maxEqualToMin */
859
548
            min = tvb_get_uint24(tvb, offset + 1, ENC_LITTLE_ENDIAN);
860
861
548
            col_append_fstr(pinfo->cinfo, COL_INFO, "#%" PRIu32, min);
862
863
548
            ti = proto_tree_add_string_format_value(tree, hf_raknet_packet_number_range, tvb,
864
548
                                                    offset, 1 + 3, "",
865
548
                                                    "%" PRIu32 " .. %" PRIu32,
866
548
                                                    min, min);
867
548
            sub_tree = proto_item_add_subtree(ti, ett_raknet_packet_number_range);
868
869
548
            proto_tree_add_item(sub_tree, hf_raknet_range_max_equal_to_min, tvb,
870
548
                                offset, 1, ENC_NA);
871
548
            offset += 1;
872
873
548
            proto_tree_add_item(sub_tree, hf_raknet_packet_number_min, tvb,
874
548
                                offset, 3, ENC_LITTLE_ENDIAN);
875
548
            offset += 3;
876
548
        }
877
114
        else {
878
114
            min = tvb_get_uint24(tvb, offset + 1    , ENC_LITTLE_ENDIAN);
879
114
            max = tvb_get_uint24(tvb, offset + 1 + 3, ENC_LITTLE_ENDIAN);
880
881
114
            col_append_fstr(pinfo->cinfo, COL_INFO,
882
114
                            "#%" PRIu32 "..%" PRIu32,
883
114
                            min, max);
884
885
114
            ti = proto_tree_add_string_format_value(tree, hf_raknet_packet_number_range, tvb,
886
114
                                                    offset, 1 + 3 + 3, "",
887
114
                                                    "%" PRIu32 " .. %" PRIu32, min, max);
888
114
            sub_tree = proto_item_add_subtree(ti, ett_raknet_packet_number_range);
889
890
114
            proto_tree_add_item(sub_tree, hf_raknet_range_max_equal_to_min, tvb,
891
114
                                offset, 1, ENC_NA);
892
114
            offset += 1;
893
894
114
            proto_tree_add_item(sub_tree, hf_raknet_packet_number_min, tvb,
895
114
                                offset, 3, ENC_LITTLE_ENDIAN);
896
114
            offset += 3;
897
898
114
            proto_tree_add_item(sub_tree, hf_raknet_packet_number_max, tvb,
899
114
                                offset, 3, ENC_LITTLE_ENDIAN);
900
114
            offset += 3;
901
114
        }
902
662
    }
903
904
12
    return tvb_captured_length(tvb);
905
12
}
906
907
static int
908
raknet_dissect_common_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *raknet_tree, void *data)
909
45
{
910
45
    int offset = 0;
911
45
    bool *has_multiple_messages;
912
45
    proto_item *ti;
913
45
    proto_item *raknet_ti;
914
45
    proto_item *msg_ti;
915
45
    proto_tree *msg_tree;
916
45
    uint64_t msg_flags;
917
45
    uint32_t payload_bits;
918
45
    uint32_t payload_octets;
919
45
    raknet_reliability_t reliability;
920
45
    bool has_split_packet;
921
45
    uint8_t message_id;
922
45
    int message_size;
923
45
    proto_tree *payload_tree;
924
45
    tvbuff_t* next_tvb;
925
45
    bool next_tvb_is_subset;
926
45
    dissector_handle_t next_dissector;
927
45
    int dissected;
928
45
    heur_dtbl_entry_t *hdtbl_entry;
929
45
    static int * const flag_flds[] = {
930
45
        &hf_raknet_message_reliability,
931
45
        &hf_raknet_message_has_split_packet,
932
45
        NULL
933
45
    };
934
935
45
    has_multiple_messages = (bool*)data;
936
45
    raknet_ti = proto_tree_get_parent(raknet_tree);
937
938
45
    msg_ti = proto_tree_add_item(raknet_tree, hf_raknet_message, tvb, offset, -1, ENC_NA);
939
45
    msg_tree = proto_item_add_subtree(msg_ti, ett_raknet_message);
940
45
    proto_item_append_text(msg_ti, ", ");
941
942
45
    proto_tree_add_bitmask_ret_uint64(msg_tree, tvb, offset, hf_raknet_message_flags,
943
45
                                      ett_raknet_message_flags, flag_flds, ENC_NA, &msg_flags);
944
45
    offset += 1;
945
946
45
    ti = proto_tree_add_item_ret_uint(msg_tree, hf_raknet_payload_length, tvb,
947
45
                                      offset, 2, ENC_BIG_ENDIAN, &payload_bits);
948
45
    offset += 2;
949
45
    payload_octets = payload_bits / 8 + (payload_bits % 8 > 0); /* ceil(bits / 8) */
950
45
    proto_item_append_text(ti, " bits (%" PRIu32 " octets)", payload_octets);
951
952
45
    reliability = (raknet_reliability_t)((msg_flags >> 5) & 0x07);
953
45
    has_split_packet = (msg_flags >> 4) & 0x01 ? true : false;
954
955
45
    if (reliability == RAKNET_RELIABLE ||
956
45
        reliability == RAKNET_RELIABLE_SEQUENCED ||
957
45
        reliability == RAKNET_RELIABLE_ORDERED ) {
958
959
19
        proto_tree_add_item(msg_tree, hf_raknet_reliable_message_number, tvb,
960
19
                            offset, 3, ENC_LITTLE_ENDIAN);
961
19
        offset += 3;
962
19
    }
963
964
45
    if (reliability == RAKNET_UNRELIABLE_SEQUENCED ||
965
45
        reliability == RAKNET_RELIABLE_SEQUENCED) {
966
967
1
        proto_tree_add_item(msg_tree, hf_raknet_message_sequencing_index, tvb,
968
1
                            offset, 3, ENC_LITTLE_ENDIAN);
969
1
        offset += 3;
970
1
    }
971
972
45
    if (reliability == RAKNET_UNRELIABLE_SEQUENCED ||
973
45
        reliability == RAKNET_RELIABLE_SEQUENCED ||
974
45
        reliability == RAKNET_RELIABLE_ORDERED) {
975
976
8
        proto_tree_add_item(msg_tree, hf_raknet_message_ordering_index, tvb,
977
8
                            offset, 3, ENC_LITTLE_ENDIAN);
978
8
        offset += 3;
979
980
8
        proto_tree_add_item(msg_tree, hf_raknet_message_ordering_channel, tvb,
981
8
                            offset, 1, ENC_NA);
982
8
        offset += 1;
983
8
    }
984
985
45
    if (has_split_packet) {
986
17
        bool save_fragmented;
987
17
        uint32_t split_packet_count;
988
17
        uint32_t split_packet_id;
989
17
        uint32_t split_packet_index;
990
17
        fragment_head *frag_msg;
991
992
993
17
        proto_tree_add_item_ret_uint(msg_tree, hf_raknet_split_packet_count, tvb,
994
17
                                     offset, 4, ENC_BIG_ENDIAN, &split_packet_count);
995
17
        offset += 4;
996
997
17
        proto_tree_add_item_ret_uint(msg_tree, hf_raknet_split_packet_id, tvb,
998
17
                                     offset, 2, ENC_BIG_ENDIAN, &split_packet_id);
999
17
        offset += 2;
1000
1001
17
        proto_tree_add_item_ret_uint(msg_tree, hf_raknet_split_packet_index, tvb,
1002
17
                                     offset, 4, ENC_BIG_ENDIAN, &split_packet_index);
1003
17
        offset += 4;
1004
1005
        /*
1006
         * Reassemble the fragmented packet.
1007
         */
1008
17
        save_fragmented = pinfo->fragmented;
1009
17
        pinfo->fragmented = true;
1010
1011
17
        frag_msg =
1012
17
            fragment_add_seq_check(&raknet_reassembly_table,
1013
17
                                   tvb, offset, pinfo,
1014
17
                                   split_packet_id,
1015
17
                                   NULL,
1016
17
                                   split_packet_index,
1017
17
                                   payload_octets,
1018
17
                                   split_packet_index != split_packet_count - 1);
1019
1020
17
        next_tvb =
1021
17
            process_reassembled_data(tvb, offset, pinfo, "Reassembled packet",
1022
17
                                     frag_msg, &raknet_frag_items, NULL, msg_tree);
1023
1024
17
        pinfo->fragmented = save_fragmented;
1025
1026
17
        if (next_tvb) {
1027
            /*
1028
             * Reassembly done. Dissect the message as normal.
1029
             */
1030
0
            wmem_strbuf_t *strbuf;
1031
1032
0
            strbuf = wmem_strbuf_new(pinfo->pool, "");
1033
0
            wmem_strbuf_append_printf(strbuf,
1034
0
                                      "{Message fragment %" PRIu32 "/%" PRIu32 "; Reassembled} ",
1035
0
                                      split_packet_index + 1, split_packet_count);
1036
1037
0
            proto_item_append_text(msg_ti, "%s", wmem_strbuf_get_str(strbuf));
1038
0
            col_add_str(pinfo->cinfo, COL_INFO, wmem_strbuf_get_str(strbuf));
1039
0
            col_set_fence(pinfo->cinfo, COL_INFO);
1040
1041
0
            next_tvb_is_subset = false;
1042
0
        }
1043
17
        else {
1044
17
            wmem_strbuf_t *strbuf;
1045
1046
17
            strbuf = wmem_strbuf_new(pinfo->pool, "");
1047
17
            wmem_strbuf_append_printf(strbuf,
1048
17
                                      "{Message fragment %" PRIu32 "/%" PRIu32 "}",
1049
17
                                      split_packet_index + 1, split_packet_count);
1050
1051
17
            proto_item_append_text(msg_ti, "%s", wmem_strbuf_get_str(strbuf));
1052
17
            col_add_str(pinfo->cinfo, COL_INFO, wmem_strbuf_get_str(strbuf));
1053
1054
17
            ti = proto_tree_add_item(msg_tree, hf_raknet_split_packet, tvb, offset,
1055
17
                                     payload_octets, ENC_NA);
1056
17
            proto_item_append_text(ti, " (%u octets)", payload_octets);
1057
17
        }
1058
17
    }
1059
28
    else {
1060
28
        next_tvb = tvb_new_subset_length(tvb, offset, payload_octets);
1061
28
        next_tvb_is_subset = true;
1062
28
    }
1063
1064
    /*
1065
     * At this point we can finally check if the packet has multiple
1066
     * messages.
1067
     */
1068
45
    if (! *has_multiple_messages) {
1069
17
        *has_multiple_messages =
1070
17
            tvb_reported_length_remaining(tvb, offset) > (int)payload_octets
1071
17
            ? true : false;
1072
17
    }
1073
1074
    /*
1075
     * And we finally have the actual size of message.
1076
     */
1077
45
    message_size = offset + payload_octets;
1078
1079
45
    if (!next_tvb) {
1080
        /*
1081
         * It was an incomplete message fragment.
1082
         */
1083
17
        proto_item_set_len(msg_ti, message_size);
1084
17
        if (raknet_ti) {
1085
17
            proto_item_set_len(raknet_ti, proto_item_get_len(raknet_ti) + message_size);
1086
17
        }
1087
17
        return message_size;
1088
17
    }
1089
1090
28
    message_id = tvb_get_uint8(next_tvb, 0);
1091
1092
    /*
1093
     * Now we want to dissect this message. First we search for a
1094
     * dissector from our system message dissector table.
1095
     */
1096
28
    next_dissector =
1097
28
        dissector_get_uint_handle(raknet_system_message_dissectors, message_id);
1098
1099
28
    if (next_dissector) {
1100
        /*
1101
         * We have a subdissector. The protocol of the message is
1102
         * still RakNet (e.g. 0x09 ID_CONNECTION_REQUEST) so we always
1103
         * insert it into our tree.
1104
         */
1105
6
        ti = proto_tree_add_item(msg_tree, hf_raknet_system_message, next_tvb, 0, -1, ENC_NA);
1106
6
        payload_tree = proto_item_add_subtree(ti, ett_raknet_system_message);
1107
1108
6
        proto_item_append_text(ti, " (%s)",
1109
6
                               val_to_str(message_id, raknet_system_message_names, "Unknown ID: %#x"));
1110
1111
6
        proto_item_append_text(msg_ti, "ID %#x (%s)", message_id,
1112
6
                               val_to_str_const(message_id, raknet_system_message_names, "Unknown"));
1113
1114
6
        col_add_str(pinfo->cinfo, COL_INFO,
1115
6
                    val_to_str(message_id, raknet_system_message_names, "Unknown system message ID: %#x"));
1116
1117
6
        proto_tree_add_item(payload_tree, hf_raknet_system_message_id,
1118
6
                            next_tvb, 0, 1, ENC_NA);
1119
1120
6
        dissected =
1121
6
            call_dissector_only(next_dissector, next_tvb, pinfo, payload_tree, data);
1122
1123
6
        proto_item_set_len(msg_ti, message_size);
1124
6
        if (raknet_ti) {
1125
6
            proto_item_set_len(raknet_ti, proto_item_get_len(raknet_ti) + message_size);
1126
6
        }
1127
1128
6
        if (dissected >= 0) {
1129
6
            return message_size;
1130
6
        }
1131
0
        else {
1132
0
            return dissected;
1133
0
        }
1134
6
    }
1135
1136
    /*
1137
     * It seems not to be a system message so use a dissector set for
1138
     * this conversation if any.
1139
     */
1140
22
    next_dissector =
1141
22
        raknet_get_session_state(pinfo)->subdissector;
1142
1143
    /*
1144
     * And of course we don't know the name of message.
1145
     */
1146
22
    proto_item_append_text(msg_ti, "ID %#x", message_id);
1147
1148
    /*
1149
     * The message belongs to a sub-protocol of RakNet so let it place
1150
     * its own protocol layer, but only if the packet has only one
1151
     * message.
1152
     */
1153
22
    if (*has_multiple_messages) {
1154
20
        payload_tree = msg_tree;
1155
20
    }
1156
2
    else {
1157
2
        payload_tree = proto_tree_get_root(raknet_tree);
1158
2
    }
1159
1160
22
    if (next_dissector) {
1161
0
        dissected =
1162
0
            call_dissector_only(next_dissector, next_tvb, pinfo, payload_tree, data);
1163
1164
0
        if (dissected > 0) {
1165
0
            goto FIX_UP_AND_RETURN;
1166
0
        }
1167
0
        else {
1168
0
            expert_add_info(pinfo, msg_tree, &ei_raknet_subdissector_failed);
1169
0
        }
1170
0
    }
1171
1172
    /*
1173
     * No dissectors set for this conversation. Look up a dissector
1174
     * from the port table.
1175
     */
1176
22
    next_dissector =
1177
22
        dissector_get_uint_handle(raknet_port_dissectors, pinfo->match_uint);
1178
1179
22
    if (next_dissector) {
1180
0
        dissected =
1181
0
            call_dissector_only(next_dissector, next_tvb, pinfo, payload_tree, data);
1182
1183
0
        if (dissected > 0) {
1184
0
            goto FIX_UP_AND_RETURN;
1185
0
        }
1186
0
        else {
1187
0
            expert_add_info(pinfo, msg_tree, &ei_raknet_subdissector_failed);
1188
0
        }
1189
0
    }
1190
1191
    /*
1192
     * We don't have a subdissector or we have one but id didn't
1193
     * dissect the message. Try heuristic subdissectors.
1194
     */
1195
22
    dissected =
1196
22
        dissector_try_heuristic(raknet_heur_subdissectors, next_tvb, pinfo, payload_tree,
1197
22
                                &hdtbl_entry, data);
1198
22
    if (!dissected) {
1199
21
        col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown message ID: %#x", message_id);
1200
1201
21
        ti = proto_tree_add_expert(msg_tree, pinfo, &ei_raknet_unknown_message_id, next_tvb,
1202
21
                                   0, 1);
1203
21
        proto_item_append_text(ti, " %#x", message_id);
1204
21
    }
1205
1206
22
  FIX_UP_AND_RETURN:
1207
    /*
1208
     * Fix up the top-level item so that it doesn't include stuff for
1209
     * sub-protocols. In order to do this there must not be multiple
1210
     * messages in the packet, and the message must have been
1211
     * reassembled from fragments.
1212
     */
1213
21
    if (!*has_multiple_messages && next_tvb_is_subset) {
1214
1
        proto_item_set_len(msg_ti, message_size - payload_octets);
1215
1
        if (raknet_ti) {
1216
1
            proto_item_set_len(raknet_ti, proto_item_get_len(raknet_ti) + message_size - payload_octets);
1217
1
        }
1218
1
    }
1219
20
    else {
1220
20
        proto_item_set_len(msg_ti, message_size);
1221
20
        if (raknet_ti) {
1222
20
            proto_item_set_len(raknet_ti, proto_item_get_len(raknet_ti) + message_size);
1223
20
        }
1224
20
    }
1225
21
    return message_size;
1226
22
}
1227
1228
static int
1229
raknet_dissect_connected_message(tvbuff_t *tvb, packet_info *pinfo,
1230
                                 proto_tree *root_tree, void* data _U_)
1231
30
{
1232
30
    raknet_session_state_t* state;
1233
30
    proto_item *ti;
1234
30
    proto_tree *raknet_tree;
1235
30
    int item_size;
1236
30
    int offset = 0;
1237
30
    uint8_t msg_type;
1238
1239
30
    state = raknet_get_session_state(pinfo);
1240
30
    if (state->use_encryption) {
1241
        /*
1242
         * RakNet uses ChaCha stream cipher to encrypt messages, which
1243
         * is currently not supported by this dissector.
1244
         */
1245
0
        col_set_str(pinfo->cinfo, COL_INFO, "Encrypted message");
1246
1247
0
        item_size = tvb_reported_length_remaining(tvb, offset);
1248
0
        ti = proto_tree_add_expert(root_tree, pinfo, &ei_raknet_encrypted_message, tvb,
1249
0
                                   offset, item_size);
1250
0
        proto_item_append_text(ti, " (%d octets)", item_size);
1251
0
        return tvb_captured_length(tvb);
1252
0
    }
1253
1254
30
    msg_type = tvb_get_uint8(tvb, offset);
1255
1256
30
    if (!(msg_type & (1 << 7))) { /* !isValid */
1257
        /*
1258
         * No suitable dissector was registered for this offline
1259
         * message.
1260
         */
1261
1
        col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown offline message ID: %#x", msg_type);
1262
1
        ti = proto_tree_add_expert(root_tree, pinfo, &ei_raknet_unknown_message_id, tvb,
1263
1
                                   0, 1);
1264
1
        proto_item_append_text(ti, " %#x", msg_type);
1265
1
        return tvb_captured_length(tvb);
1266
1
    }
1267
29
    else if (msg_type & (1 << 6)) { /* isACK */
1268
10
        static int * const ack_flds[] = {
1269
10
            &hf_raknet_packet_is_for_connected,
1270
10
            &hf_raknet_packet_is_ACK,
1271
10
            &hf_raknet_packet_has_B_and_AS,
1272
10
            NULL
1273
10
        };
1274
1275
10
        ti = proto_tree_add_item(root_tree, proto_raknet, tvb, 0, -1, ENC_NA);
1276
10
        proto_item_append_text(ti, ", ACK");
1277
10
        raknet_tree = proto_item_add_subtree(ti, ett_raknet);
1278
1279
10
        proto_tree_add_bitmask(raknet_tree, tvb, offset, hf_raknet_packet_type,
1280
10
                               ett_raknet_packet_type, ack_flds, ENC_NA);
1281
10
        offset += 1;
1282
1283
10
        if (msg_type & (1 << 5)) { /* hasBAndAS */
1284
8
            proto_tree_add_item(raknet_tree, hf_raknet_AS, tvb, offset,
1285
8
                                4, ENC_BIG_ENDIAN);
1286
8
            offset += 4;
1287
8
        }
1288
1289
10
        if (raknet_tree) {
1290
10
            bool is_ACK = true;
1291
10
            return raknet_dissect_ACK(tvb_new_subset_remaining(tvb, offset),
1292
10
                                      pinfo, raknet_tree, &is_ACK);
1293
10
        }
1294
0
        else {
1295
0
            return tvb_captured_length(tvb);
1296
0
        }
1297
10
    }
1298
19
    else if (msg_type & (1 << 5)) { /* isNAK */
1299
2
        static int * const nak_flds[] = {
1300
2
            &hf_raknet_packet_is_for_connected,
1301
2
            &hf_raknet_packet_is_ACK,
1302
2
            &hf_raknet_packet_is_NAK,
1303
2
            NULL
1304
2
        };
1305
1306
2
        ti = proto_tree_add_item(root_tree, proto_raknet, tvb, 0, -1, ENC_NA);
1307
2
        proto_item_append_text(ti, ", NAK");
1308
2
        raknet_tree = proto_item_add_subtree(ti, ett_raknet);
1309
1310
2
        proto_tree_add_bitmask(raknet_tree, tvb, offset, hf_raknet_packet_type,
1311
2
                               ett_raknet_packet_type, nak_flds, ENC_NA);
1312
2
        offset += 1;
1313
1314
2
        if (raknet_tree) {
1315
2
            bool is_ACK = false;
1316
2
            return raknet_dissect_ACK(tvb_new_subset_remaining(tvb, offset),
1317
2
                                      pinfo, raknet_tree, &is_ACK);
1318
2
        }
1319
0
        else {
1320
0
            return tvb_captured_length(tvb);
1321
0
        }
1322
2
    }
1323
17
    else {
1324
        /*
1325
         * This is the trickiest part as it's neither ACK nor NAK. The
1326
         * length of its RakNet header varies, and its payload can
1327
         * even be fragmented so we might have to reassemble them.
1328
         */
1329
17
        uint32_t packet_number;
1330
17
        bool has_multiple_messages = false;
1331
17
        static int * const common_flds[] = {
1332
17
            &hf_raknet_packet_is_for_connected,
1333
17
            &hf_raknet_packet_is_ACK,
1334
17
            &hf_raknet_packet_is_NAK,
1335
17
            &hf_raknet_packet_is_pair,
1336
17
            &hf_raknet_packet_is_continuous_send,
1337
17
            &hf_raknet_packet_needs_B_and_AS,
1338
17
            NULL
1339
17
        };
1340
1341
17
        ti = proto_tree_add_item(root_tree, proto_raknet, tvb, 0, 0, ENC_NA);
1342
17
        raknet_tree = proto_item_add_subtree(ti, ett_raknet);
1343
1344
17
        proto_tree_add_bitmask(raknet_tree, tvb, offset, hf_raknet_packet_type,
1345
17
                               ett_raknet_packet_type, common_flds, ENC_NA);
1346
17
        offset += 1;
1347
1348
17
        proto_tree_add_item_ret_uint(raknet_tree, hf_raknet_packet_number, tvb,
1349
17
                                     offset, 3, ENC_LITTLE_ENDIAN, &packet_number);
1350
17
        offset += 3;
1351
1352
17
        proto_item_append_text(ti, ", Message #%" PRIu32, packet_number);
1353
17
        col_add_fstr(pinfo->cinfo, COL_INFO, "#%" PRIu32 ": ", packet_number);
1354
17
        col_set_fence(pinfo->cinfo, COL_INFO);
1355
1356
        /*
1357
         * Set the length of the top-level item to the size of packet
1358
         * header as we don't know the correct size yet. The common
1359
         * message dissector will later resize it.
1360
         */
1361
17
        proto_item_set_len(ti, offset);
1362
1363
45
        while (true) {
1364
45
            int dissected;
1365
1366
45
            dissected = raknet_dissect_common_message(tvb_new_subset_remaining(tvb, offset), pinfo,
1367
45
                                                      raknet_tree, &has_multiple_messages);
1368
45
            if (dissected >= 0) {
1369
44
                offset += dissected;
1370
1371
44
                if (tvb_reported_length_remaining(tvb, offset) > 0) {
1372
                    /*
1373
                     * More messages are in the packet.
1374
                     */
1375
28
                    col_append_str(pinfo->cinfo, COL_INFO, ", ");
1376
28
                    col_set_fence(pinfo->cinfo, COL_INFO);
1377
28
                    continue;
1378
28
                }
1379
16
                else {
1380
                    /*
1381
                     * It's the end of packet.
1382
                     */
1383
16
                    break;
1384
16
                }
1385
44
            }
1386
1
            else {
1387
1
                return dissected;
1388
1
            }
1389
45
        }
1390
1391
16
        return tvb_captured_length(tvb);
1392
17
    }
1393
30
}
1394
1395
/*
1396
 * Decode the tvb buffer.
1397
 *
1398
 * RakNet is just a dissector.  It is invoked by protocols whose applications
1399
 * are built using the RakNet libs.
1400
 */
1401
static int
1402
dissect_raknet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1403
35
{
1404
35
    uint8_t message_id;
1405
35
    int dissected;
1406
1407
35
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "RakNet");
1408
35
    col_clear(pinfo->cinfo, COL_INFO);
1409
1410
35
    message_id = tvb_get_uint8(tvb, 0);
1411
1412
35
    dissected = dissector_try_uint_with_data(raknet_offline_message_dissectors, message_id, tvb,
1413
35
                                       pinfo, tree, true, data);
1414
35
    if (!dissected) {
1415
30
        raknet_dissect_connected_message(tvb, pinfo, tree, data);
1416
30
    }
1417
1418
35
    return tvb_captured_length(tvb);
1419
35
}
1420
1421
/*
1422
 * Applications using RakNet do not always use a fixed port, but since
1423
 * every RakNet sessions start with offline messages we can do
1424
 * heuristics to detect such sessions.
1425
 */
1426
static bool
1427
test_raknet_heur(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree _U_, void* data _U_)
1428
1.23k
{
1429
1.23k
    if (tvb_memeql(tvb, 1 + 8, RAKNET_OFFLINE_MESSAGE_DATA_ID, sizeof(RAKNET_OFFLINE_MESSAGE_DATA_ID)) == 0) {
1430
        /* ID_UNCONNECTED_PING */
1431
7
        return true;
1432
7
    }
1433
1.22k
    else if (tvb_memeql(tvb, 1, RAKNET_OFFLINE_MESSAGE_DATA_ID, sizeof(RAKNET_OFFLINE_MESSAGE_DATA_ID)) == 0) {
1434
        /* ID_OPEN_CONNECTION_REQUEST_1 */
1435
8
        return true;
1436
8
    }
1437
1.22k
    else if (tvb_memeql(tvb, 1 + 8 + 8, RAKNET_OFFLINE_MESSAGE_DATA_ID, sizeof(RAKNET_OFFLINE_MESSAGE_DATA_ID)) == 0) {
1438
        /* ID_UNCONNECTED_PONG */
1439
7
        return true;
1440
7
    }
1441
1.21k
    else {
1442
1.21k
        return false;
1443
1.21k
    }
1444
1.23k
}
1445
1446
static bool
1447
dissect_raknet_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1448
1.23k
{
1449
1.23k
    if (test_raknet_heur(tvb, pinfo, tree, data)) {
1450
22
        conversation_t* conversation;
1451
1452
22
        conversation = find_or_create_conversation(pinfo);
1453
22
        conversation_set_dissector(conversation, raknet_handle);
1454
1455
22
        return call_dissector_only(raknet_handle, tvb, pinfo, tree, data) > 0;
1456
22
    }
1457
1.21k
    else {
1458
1.21k
        return false;
1459
1.21k
    }
1460
1.23k
}
1461
1462
void
1463
proto_register_raknet(void)
1464
14
{
1465
14
    static hf_register_info hf[] = {
1466
        /*
1467
         * Offline Message ID field.
1468
         */
1469
14
        { &hf_raknet_offline_message_id,
1470
14
            { "RakNet Offline Message ID", "raknet.offline.message.id",
1471
14
                FT_UINT8, BASE_HEX,
1472
14
                VALS(raknet_offline_message_names), 0x0,
1473
14
                NULL, HFILL }
1474
14
        },
1475
        /*
1476
         * General fields (fields in >1 packet).
1477
         */
1478
14
        { &hf_raknet_client_guid,
1479
14
            { "RakNet Client GUID", "raknet.client.guid",
1480
14
                FT_BYTES, BASE_NONE,
1481
14
                NULL, 0x0,
1482
14
                NULL, HFILL }
1483
14
        },
1484
14
        { &hf_raknet_timestamp,
1485
14
            { "RakNet Time since start (ms)", "raknet.timestamp",
1486
14
                FT_UINT64, BASE_DEC,
1487
14
                NULL, 0x0,
1488
14
                NULL, HFILL }
1489
14
        },
1490
14
        { &hf_raknet_offline_message_data_id,
1491
14
            { "RakNet Offline message data ID", "raknet.offline_message.data_id",
1492
14
                FT_BYTES, BASE_NONE,
1493
14
                NULL, 0x0,
1494
14
                NULL, HFILL }
1495
14
        },
1496
14
        { &hf_raknet_mtu_size,
1497
14
            { "RakNet MTU size", "raknet.MTU",
1498
14
                FT_UINT16, BASE_DEC,
1499
14
                NULL, 0x0,
1500
14
                NULL, HFILL }
1501
14
        },
1502
14
        { &hf_raknet_raknet_proto_ver,
1503
14
            { "RakNet RakNet protocol version", "raknet.proto_ver",
1504
14
                FT_UINT8, BASE_DEC,
1505
14
                NULL, 0x0,
1506
14
                NULL, HFILL }
1507
14
        },
1508
14
        { &hf_raknet_server_guid,
1509
14
            { "RakNet Server GUID", "raknet.server_id",
1510
14
                FT_BYTES, BASE_NONE,
1511
14
                NULL, 0x0,
1512
14
                NULL, HFILL }
1513
14
        },
1514
14
        { &hf_raknet_ip_version,
1515
14
            { "RakNet IP Version", "raknet.ip.version",
1516
14
                FT_UINT8, BASE_DEC,
1517
14
                NULL, 0x0,
1518
14
                NULL, HFILL }
1519
14
        },
1520
14
        { &hf_raknet_ipv4_address,
1521
14
            { "RakNet IPv4 Address", "raknet.ip.v4_address",
1522
14
                FT_IPv4, BASE_NONE,
1523
14
                NULL, 0x0,
1524
14
                NULL, HFILL }
1525
14
        },
1526
14
        { &hf_raknet_ipv6_address,
1527
14
            { "RakNet IPv6 Address", "raknet.ip.v6_address",
1528
14
                FT_IPv6, BASE_NONE,
1529
14
                NULL, 0x0,
1530
14
                NULL, HFILL }
1531
14
        },
1532
14
        { &hf_raknet_port,
1533
14
            { "RakNet Port", "raknet.port",
1534
14
                FT_UINT16, BASE_DEC,
1535
14
                NULL, 0x0,
1536
14
                NULL, HFILL }
1537
14
        },
1538
        /*
1539
         * Packet ID 0x05
1540
         */
1541
14
        { &hf_raknet_null_padding,
1542
14
            { "RakNet Null padding", "raknet.null_padding",
1543
14
                FT_NONE, BASE_NONE,
1544
14
                NULL, 0x0,
1545
14
                NULL, HFILL }
1546
14
        },
1547
        /*
1548
         * Packet ID 0x06
1549
         */
1550
14
        { &hf_raknet_use_encryption,
1551
14
            { "RakNet Use encryption", "raknet.use_encryption",
1552
14
                FT_BOOLEAN, BASE_NONE,
1553
14
                NULL, 0x0,
1554
14
                NULL, HFILL }
1555
14
        },
1556
14
        { &hf_raknet_server_public_key,
1557
14
            { "RakNet Server public key", "raknet.server.public_key",
1558
14
                FT_BYTES, BASE_NONE,
1559
14
                NULL, 0x0,
1560
14
                NULL, HFILL }
1561
14
        },
1562
        /*
1563
         * Packet ID 0x07
1564
         */
1565
14
        { &hf_raknet_cookie,
1566
14
            { "RakNet cookie", "raknet.cookie",
1567
14
                FT_UINT32, BASE_HEX,
1568
14
                NULL, 0x0,
1569
14
                NULL, HFILL }
1570
14
        },
1571
14
        { &hf_raknet_client_wrote_challenge,
1572
14
            { "RakNet Client wrote challenge", "raknet.client.wrote_challenge",
1573
14
                FT_BOOLEAN, BASE_NONE,
1574
14
                NULL, 0x0,
1575
14
                NULL, HFILL }
1576
14
        },
1577
14
        { &hf_raknet_client_challenge,
1578
14
            { "RakNet Client challenge", "raknet.client.challenge",
1579
14
                FT_BYTES, BASE_NONE,
1580
14
                NULL, 0x0,
1581
14
                NULL, HFILL }
1582
14
        },
1583
14
        { &hf_raknet_client_address,
1584
14
            { "RakNet Client address", "raknet.client.address",
1585
14
                FT_STRING, BASE_NONE,
1586
14
                NULL, 0x0,
1587
14
                NULL, HFILL }
1588
14
        },
1589
14
        { &hf_raknet_server_address,
1590
14
            { "RakNet Server address", "raknet.server.address",
1591
14
                FT_STRING, BASE_NONE,
1592
14
                NULL, 0x0,
1593
14
                NULL, HFILL }
1594
14
        },
1595
14
        { &hf_raknet_server_answer,
1596
14
            { "RakNet Server answer", "raknet.server.answer",
1597
14
                FT_BYTES, BASE_NONE,
1598
14
                NULL, 0x0,
1599
14
                NULL, HFILL }
1600
14
        },
1601
        /*
1602
         * Packet ID 0x1C
1603
         */
1604
14
        { &hf_raknet_0x1C_server_id_str_len,
1605
14
            { "RakNet Server ID string len", "raknet.server_id_str_len",
1606
14
                FT_UINT16, BASE_DEC,
1607
14
                NULL, 0x0,
1608
14
                NULL, HFILL }
1609
14
        },
1610
14
        { &hf_raknet_0x1C_server_id_str,
1611
14
            { "RakNet Server ID string", "raknet.server_id_str",
1612
14
                FT_STRING, BASE_NONE,
1613
14
                NULL, 0x0,
1614
14
                NULL, HFILL }
1615
14
        },
1616
14
        { &hf_raknet_packet_type,
1617
14
            { "RakNet Packet type", "raknet.packet.type",
1618
14
                FT_UINT8, BASE_HEX,
1619
14
                NULL, 0x0,
1620
14
                NULL, HFILL }
1621
14
        },
1622
14
        { &hf_raknet_packet_is_for_connected,
1623
14
            { "is for connected peer", "raknet.packet.is_for_connected",
1624
14
                FT_BOOLEAN, 8,
1625
14
                NULL, 0x80,
1626
14
                NULL, HFILL }
1627
14
        },
1628
14
        { &hf_raknet_packet_is_ACK,
1629
14
            { "is ACK", "raknet.packet.is_ACK",
1630
14
                FT_BOOLEAN, 8,
1631
14
                NULL, 0x40,
1632
14
                NULL, HFILL }
1633
14
        },
1634
14
        { &hf_raknet_packet_has_B_and_AS,
1635
14
            { "has B and AS", "raknet.packet.has_B_and_AS",
1636
14
                FT_BOOLEAN, 8,
1637
14
                NULL, 0x20,
1638
14
                NULL, HFILL }
1639
14
        },
1640
14
        { &hf_raknet_packet_is_NAK,
1641
14
            { "is NAK", "raknet.packet.is_NAK",
1642
14
                FT_BOOLEAN, 8,
1643
14
                NULL, 0x20,
1644
14
                NULL, HFILL }
1645
14
        },
1646
14
        { &hf_raknet_packet_is_pair,
1647
14
            { "is pair", "raknet.packet.is_pair",
1648
14
                FT_BOOLEAN, 8,
1649
14
                NULL, 0x10,
1650
14
                NULL, HFILL }
1651
14
        },
1652
14
        { &hf_raknet_packet_is_continuous_send,
1653
14
            { "is continuous send", "raknet.packet.is_continuous_send",
1654
14
                FT_BOOLEAN, 8,
1655
14
                NULL, 0x8,
1656
14
                NULL, HFILL }
1657
14
        },
1658
14
        { &hf_raknet_packet_needs_B_and_AS,
1659
14
            { "needs B and AS", "raknet.packet.needs_B_and_AS",
1660
14
                FT_BOOLEAN, 8,
1661
14
                NULL, 0x4,
1662
14
                NULL, HFILL }
1663
14
        },
1664
14
        { &hf_raknet_AS,
1665
14
            { "RakNet Data arrival rate", "raknet.AS",
1666
14
                FT_FLOAT, BASE_NONE,
1667
14
                NULL, 0x0,
1668
14
                NULL, HFILL }
1669
14
        },
1670
14
        { &hf_raknet_NACK_record_count,
1671
14
            { "RakNet ACK/NAK record count", "raknet.NACK.record_count",
1672
14
                FT_UINT16, BASE_DEC,
1673
14
                NULL, 0x0,
1674
14
                NULL, HFILL }
1675
14
        },
1676
14
        { &hf_raknet_packet_number_range,
1677
14
            { "RakNet Packet sequence number range", "raknet.range.packet_number",
1678
14
                FT_STRING, BASE_NONE,
1679
14
                NULL, 0x0,
1680
14
                NULL, HFILL }
1681
14
        },
1682
14
        { &hf_raknet_range_max_equal_to_min,
1683
14
            { "RakNet Range max equals to min", "raknet.range.max_equals_to_min",
1684
14
                FT_BOOLEAN, BASE_NONE,
1685
14
                NULL, 0x0,
1686
14
                NULL, HFILL }
1687
14
        },
1688
14
        { &hf_raknet_packet_number_min,
1689
14
            { "RakNet Packet sequence number min", "raknet.range.packet_number.min",
1690
14
                FT_UINT24, BASE_DEC,
1691
14
                NULL, 0x0,
1692
14
                NULL, HFILL }
1693
14
        },
1694
14
        { &hf_raknet_packet_number_max,
1695
14
            { "RakNet Packet sequence number max", "raknet.range.packet_number.max",
1696
14
                FT_UINT24, BASE_DEC,
1697
14
                NULL, 0x0,
1698
14
                NULL, HFILL }
1699
14
        },
1700
14
        { &hf_raknet_packet_number,
1701
14
            { "RakNet Packet sequence number", "raknet.packet_number",
1702
14
                FT_UINT24, BASE_DEC,
1703
14
                NULL, 0x0,
1704
14
                NULL, HFILL }
1705
14
        },
1706
14
        { &hf_raknet_message,
1707
14
            { "RakNet Message", "raknet.message",
1708
14
                FT_NONE, BASE_NONE,
1709
14
                NULL, 0x0,
1710
14
                NULL, HFILL }
1711
14
        },
1712
14
        { &hf_raknet_message_flags,
1713
14
            { "RakNet Message flags", "raknet.message.flags",
1714
14
                FT_UINT8, BASE_HEX,
1715
14
                NULL, 0x0,
1716
14
                NULL, HFILL }
1717
14
        },
1718
14
        { &hf_raknet_message_reliability,
1719
14
            { "reliability", "raknet.message.reliability",
1720
14
                FT_UINT8, BASE_DEC,
1721
14
                VALS(raknet_reliability), 0xE0,
1722
14
                NULL, HFILL }
1723
14
        },
1724
14
        { &hf_raknet_message_has_split_packet,
1725
14
            { "has split packet", "raknet.message.has_split_packet",
1726
14
                FT_BOOLEAN, 8,
1727
14
                NULL, 0x10,
1728
14
                NULL, HFILL }
1729
14
        },
1730
14
        { &hf_raknet_payload_length,
1731
14
            { "RakNet Payload length", "raknet.payload.length",
1732
14
                FT_UINT16, BASE_DEC,
1733
14
                NULL, 0x0,
1734
14
                NULL, HFILL }
1735
14
        },
1736
14
        { &hf_raknet_reliable_message_number,
1737
14
            { "RakNet Reliable message number", "raknet.reliable.number",
1738
14
                FT_UINT24, BASE_DEC,
1739
14
                NULL, 0x0,
1740
14
                NULL, HFILL }
1741
14
        },
1742
14
        { &hf_raknet_message_sequencing_index,
1743
14
            { "RakNet Message sequencing index", "raknet.sequencing.index",
1744
14
                FT_UINT24, BASE_DEC,
1745
14
                NULL, 0x0,
1746
14
                NULL, HFILL }
1747
14
        },
1748
14
        { &hf_raknet_message_ordering_index,
1749
14
            { "RakNet Message ordering index", "raknet.ordering.index",
1750
14
                FT_UINT24, BASE_DEC,
1751
14
                NULL, 0x0,
1752
14
                NULL, HFILL }
1753
14
        },
1754
14
        { &hf_raknet_message_ordering_channel,
1755
14
            { "RakNet Message ordering channel", "raknet.ordering.channel",
1756
14
                FT_UINT8, BASE_DEC,
1757
14
                NULL, 0x0,
1758
14
                NULL, HFILL }
1759
14
        },
1760
14
        { &hf_raknet_split_packet_count,
1761
14
            { "RakNet Split packet count", "raknet.split.count",
1762
14
                FT_UINT32, BASE_DEC,
1763
14
                NULL, 0x0,
1764
14
                NULL, HFILL }
1765
14
        },
1766
14
        { &hf_raknet_split_packet_id,
1767
14
            { "RakNet Split packet ID", "raknet.split.id",
1768
14
                FT_UINT16, BASE_DEC,
1769
14
                NULL, 0x0,
1770
14
                NULL, HFILL }
1771
14
        },
1772
14
        { &hf_raknet_split_packet_index,
1773
14
            { "RakNet Split packet index", "raknet.split.index",
1774
14
                FT_UINT32, BASE_DEC,
1775
14
                NULL, 0x0,
1776
14
                NULL, HFILL }
1777
14
        },
1778
14
        { &hf_raknet_split_packet,
1779
14
            { "RakNet Split packet", "raknet.split.packet",
1780
14
                FT_NONE, BASE_NONE,
1781
14
                NULL, 0x0,
1782
14
                NULL, HFILL }
1783
14
        },
1784
14
        { &hf_raknet_system_message,
1785
14
            { "RakNet System message", "raknet.system.message",
1786
14
                FT_NONE, BASE_NONE,
1787
14
                NULL, 0x0,
1788
14
                NULL, HFILL }
1789
14
        },
1790
14
        { &hf_raknet_system_message_id,
1791
14
            { "RakNet System Message ID", "raknet.system.message.id",
1792
14
                FT_UINT8, BASE_HEX,
1793
14
                VALS(raknet_system_message_names), 0x0,
1794
14
                NULL, HFILL }
1795
14
        },
1796
14
        { &hf_raknet_client_proof,
1797
14
            { "RakNet Client proof of key", "raknet.client.proof",
1798
14
                FT_BYTES, BASE_NONE,
1799
14
                NULL, 0x0,
1800
14
                NULL, HFILL }
1801
14
        },
1802
14
        { &hf_raknet_use_client_key,
1803
14
            { "RakNet Use client key", "raknet.use_client_key",
1804
14
                FT_BOOLEAN, BASE_NONE,
1805
14
                NULL, 0x0,
1806
14
                NULL, HFILL }
1807
14
        },
1808
14
        { &hf_raknet_client_identity,
1809
14
            { "RakNet Client identity", "raknet.client.identity",
1810
14
                FT_BYTES, BASE_NONE,
1811
14
                NULL, 0x0,
1812
14
                NULL, HFILL }
1813
14
        },
1814
14
        { &hf_raknet_password,
1815
14
            { "RakNet Password", "raknet.password",
1816
14
                FT_BYTES, BASE_NONE,
1817
14
                NULL, 0x0,
1818
14
                NULL, HFILL }
1819
14
        },
1820
14
        { &hf_raknet_system_index,
1821
14
            { "RakNet System index", "raknet.system.index",
1822
14
                FT_UINT16, BASE_DEC,
1823
14
                NULL, 0x0,
1824
14
                NULL, HFILL }
1825
14
        },
1826
14
        { &hf_raknet_internal_address,
1827
14
            { "RakNet Internal address", "raknet.internal.address",
1828
14
                FT_STRING, BASE_NONE,
1829
14
                NULL, 0x0,
1830
14
                NULL, HFILL }
1831
14
        },
1832
        /*
1833
         * Fragmented packets
1834
         */
1835
14
        { &hf_raknet_fragment,
1836
14
            { "Message fragment", "raknet.fragment",
1837
14
                FT_FRAMENUM, BASE_NONE,
1838
14
                NULL, 0x00,
1839
14
                NULL, HFILL }
1840
14
        },
1841
14
        { &hf_raknet_fragment_count,
1842
14
            { "Message fragment count", "raknet.fragment.count",
1843
14
                FT_UINT32, BASE_DEC,
1844
14
                NULL, 0x00,
1845
14
                NULL, HFILL }
1846
14
        },
1847
14
        { &hf_raknet_fragment_error,
1848
14
            { "Message defragmentation error", "raknet.fragment.error",
1849
14
                FT_FRAMENUM, BASE_NONE,
1850
14
                NULL, 0x00,
1851
14
                NULL, HFILL }
1852
14
        },
1853
14
        { &hf_raknet_fragment_multiple_tails,
1854
14
            { "Message has multiple tail fragments", "raknet.fragment.multiple_tails",
1855
14
                FT_BOOLEAN, BASE_NONE,
1856
14
                NULL, 0x00,
1857
14
                NULL, HFILL }
1858
14
        },
1859
14
        { &hf_raknet_fragment_overlap,
1860
14
            { "Message fragment overlap", "raknet.fragment.overlap",
1861
14
                FT_BOOLEAN, BASE_NONE,
1862
14
                NULL, 0x00,
1863
14
                NULL, HFILL }
1864
14
        },
1865
14
        { &hf_raknet_fragment_overlap_conflicts,
1866
14
            { "Message fragment overlapping with conflicting data", "raknet.fragment.overlap.conflicts",
1867
14
                FT_BOOLEAN, BASE_NONE,
1868
14
                NULL, 0x00,
1869
14
                NULL, HFILL }
1870
14
        },
1871
14
        { &hf_raknet_fragment_too_long_fragment,
1872
14
            { "Message fragment too long", "raknet.fragment.too_long",
1873
14
                FT_BOOLEAN, BASE_NONE,
1874
14
                NULL, 0x00,
1875
14
                NULL, HFILL }
1876
14
        },
1877
14
        { &hf_raknet_fragments,
1878
14
            { "Message fragments", "raknet.fragments",
1879
14
                FT_NONE, BASE_NONE,
1880
14
                NULL, 0x00,
1881
14
                NULL, HFILL }
1882
14
        },
1883
14
        { &hf_raknet_reassembled_in,
1884
14
            { "Reassembled message in frame", "raknet.reassembled.in",
1885
14
                FT_FRAMENUM, BASE_NONE,
1886
14
                NULL, 0x00,
1887
14
                NULL, HFILL }
1888
14
        },
1889
14
        { &hf_raknet_reassembled_length,
1890
14
            { "Reassembled message length", "raknet.reassembled.length",
1891
14
                FT_UINT32, BASE_DEC,
1892
14
                NULL, 0x00,
1893
14
                NULL, HFILL }
1894
14
        },
1895
14
    };
1896
1897
    /*
1898
     * Setup protocol subtree array
1899
     */
1900
14
    static int *ett[] = {
1901
14
        &ett_raknet,
1902
14
        &ett_raknet_system_address,
1903
14
        &ett_raknet_packet_type,
1904
14
        &ett_raknet_packet_number_range,
1905
14
        &ett_raknet_message,
1906
14
        &ett_raknet_message_flags,
1907
14
        &ett_raknet_system_message,
1908
14
        &ett_raknet_fragment,
1909
14
        &ett_raknet_fragments,
1910
14
    };
1911
1912
    /*
1913
     * Set up expert info.
1914
     */
1915
14
    static ei_register_info ei[] = {
1916
14
        { &ei_raknet_unknown_message_id,
1917
14
          { "raknet.unknown.id", PI_UNDECODED, PI_WARN,
1918
14
            "RakNet unknown message ID",
1919
14
            EXPFILL }
1920
14
        },
1921
14
        { &ei_raknet_encrypted_message,
1922
14
          { "raknet.encrypted", PI_DECRYPTION, PI_NOTE,
1923
14
            "RakNet encrypted message",
1924
14
            EXPFILL }
1925
14
        },
1926
14
        { &ei_raknet_subdissector_failed,
1927
14
          { "raknet.subdissector.failed", PI_MALFORMED, PI_NOTE,
1928
14
            "RakNet message subdissector failed, trying the next candidate or heuristics",
1929
14
            EXPFILL }
1930
14
        },
1931
14
        { &ei_raknet_ip_ver_invalid,
1932
14
          { "raknet.ip_version.invalid", PI_PROTOCOL, PI_WARN,
1933
14
            "Invalid IP version",
1934
14
            EXPFILL }
1935
14
        }
1936
14
    };
1937
14
    expert_module_t *expert_raknet;
1938
1939
    /*
1940
     * Init data structs.
1941
     */
1942
14
    raknet_init_message_names();
1943
1944
    /*
1945
     * Register the protocol with Wireshark.
1946
     */
1947
14
    proto_raknet = proto_register_protocol (
1948
14
            "RakNet game networking protocol", /* name */
1949
14
            "RakNet", /* short name */
1950
14
            "raknet"  /* abbrev */
1951
14
            );
1952
1953
    /*
1954
     * Register expert support.
1955
     */
1956
14
    expert_raknet = expert_register_protocol(proto_raknet);
1957
14
    expert_register_field_array(expert_raknet, ei, array_length(ei));
1958
1959
    /*
1960
     * Register detailed dissection arrays.
1961
     */
1962
14
    proto_register_field_array(proto_raknet, hf, array_length(hf));
1963
14
    proto_register_subtree_array(ett, array_length(ett));
1964
1965
    /*
1966
     * Register reassembly table.
1967
     */
1968
14
    reassembly_table_register(&raknet_reassembly_table,
1969
14
                          &addresses_ports_reassembly_table_functions);
1970
1971
    /*
1972
     * For internal use only
1973
     */
1974
14
    raknet_handle =
1975
14
        register_dissector("raknet", dissect_raknet, proto_raknet);
1976
1977
14
    raknet_offline_message_dissectors =
1978
14
        register_dissector_table("raknet.offline.message.id", "RakNet offline messages",
1979
14
                                 proto_raknet, FT_UINT8, BASE_HEX);
1980
1981
14
    raknet_system_message_dissectors =
1982
14
        register_dissector_table("raknet.system.message.id", "RakNet system messages",
1983
14
                                 proto_raknet, FT_UINT8, BASE_HEX);
1984
1985
    /*
1986
     * External protocols may register their port to this table via
1987
     * "raknet_add_udp_dissector()".
1988
     */
1989
14
    raknet_port_dissectors =
1990
14
        register_dissector_table("raknet.port", "Port for protocols on top of RakNet",
1991
14
                                 proto_raknet, FT_UINT16, BASE_DEC);
1992
1993
    /*
1994
     * ...and their heuristic dissector to this table.
1995
     */
1996
14
    raknet_heur_subdissectors =
1997
14
        register_heur_dissector_list_with_description("raknet", "RakNet fallback", proto_raknet);
1998
14
}
1999
2000
void
2001
proto_reg_handoff_raknet(void)
2002
14
{
2003
14
    dissector_handle_t raknet_handle_tmp;
2004
14
    unsigned int i;
2005
2006
210
    for (i = 0; i < array_length(raknet_offline_message_handlers); i++) {
2007
196
        raknet_handle_tmp =
2008
196
            create_dissector_handle(raknet_offline_message_handlers[i].dissector_fp,
2009
196
                                    proto_raknet);
2010
196
        dissector_add_uint("raknet.offline.message.id", raknet_offline_message_handlers[i].vs.value,
2011
196
                           raknet_handle_tmp);
2012
196
    }
2013
2014
84
    for (i = 0; i < array_length(raknet_system_message_handlers); i++) {
2015
70
        raknet_handle_tmp =
2016
70
            create_dissector_handle(raknet_system_message_handlers[i].dissector_fp,
2017
70
                                    proto_raknet);
2018
70
        dissector_add_uint("raknet.system.message.id", raknet_system_message_handlers[i].vs.value,
2019
70
                           raknet_handle_tmp);
2020
70
    }
2021
2022
14
    heur_dissector_add("udp", dissect_raknet_heur,
2023
14
                       "RakNet over UDP", "raknet_udp", proto_raknet, HEURISTIC_ENABLE);
2024
14
}
2025
2026
/*
2027
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
2028
 *
2029
 * Local variables:
2030
 * c-basic-offset: 4
2031
 * tab-width: 8
2032
 * indent-tabs-mode: nil
2033
 * End:
2034
 *
2035
 * vi: set shiftwidth=4 tabstop=8 expandtab:
2036
 * :indentSize=4:tabSize=8:noTabs=true:
2037
 */