Coverage Report

Created: 2026-05-14 06:28

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