Coverage Report

Created: 2026-01-02 06:13

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
14
#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
89
raknet_get_session_state(packet_info *pinfo) {
234
89
    conversation_t* conversation;
235
89
    raknet_session_state_t* state;
236
237
89
    conversation = find_or_create_conversation(pinfo);
238
89
    state = (raknet_session_state_t*)conversation_get_proto_data(conversation, proto_raknet);
239
240
89
    if (state == NULL) {
241
34
        state = wmem_new(wmem_file_scope(), raknet_session_state_t);
242
34
        state->use_encryption = false;
243
34
        state->subdissector = NULL;
244
34
        conversation_add_proto_data(conversation, proto_raknet, state);
245
34
    }
246
247
89
    return state;
248
89
}
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
16
        packet_info *pinfo, tvbuff_t *tvb, int *offset) {
261
16
    proto_item *ti;
262
16
    proto_tree *sub_tree;
263
16
    uint8_t ip_version;
264
16
    uint32_t v4_addr;
265
16
    uint16_t port;
266
16
    address addr;
267
16
    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
16
    ti = proto_tree_add_string(tree, hf, tvb, *offset, -1, "");
272
16
    sub_tree = proto_item_add_subtree(ti, ett_raknet_system_address);
273
16
    ip_version = tvb_get_uint8(tvb, *offset);
274
16
    proto_tree_add_item(sub_tree, hf_raknet_ip_version, tvb, *offset, 1, ENC_NA);
275
16
    (*offset)++;
276
16
    switch (ip_version) {
277
1
    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
1
        v4_addr = ~tvb_get_ipv4(tvb, *offset);
284
1
        set_address(&addr, AT_IPv4, sizeof(v4_addr), &v4_addr);
285
1
        addr_str = address_to_display(pinfo->pool, &addr);
286
1
        proto_tree_add_ipv4(sub_tree, hf_raknet_ipv4_address, tvb, *offset, 4, v4_addr);
287
1
        *offset += 4;
288
1
        port = tvb_get_ntohs(tvb, *offset);
289
1
        proto_tree_add_item(sub_tree, hf_raknet_port, tvb, *offset, 2, ENC_BIG_ENDIAN);
290
1
        *offset += 2;
291
1
        proto_item_set_len(ti, 1 + 4 + 2);
292
1
        proto_item_append_text(ti, "%s:%" PRIu16, addr_str, port);
293
1
        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
14
    default:
305
14
        proto_item_set_len(ti, 1);
306
14
        expert_add_info(pinfo, sub_tree, &ei_raknet_ip_ver_invalid);
307
16
    }
308
16
}
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
2
{
338
2
    proto_tree *sub_tree;
339
2
    int offset;
340
341
2
    sub_tree = init_raknet_offline_message(tvb, pinfo, tree, &offset);
342
343
2
    proto_tree_add_item(sub_tree, hf_raknet_offline_message_data_id, tvb, offset,
344
2
                        16, ENC_NA);
345
2
    offset += 16;
346
347
2
    proto_tree_add_item(sub_tree, hf_raknet_raknet_proto_ver, tvb, offset,
348
2
                        1, ENC_BIG_ENDIAN);
349
2
    offset += 1;
350
351
    /* -1 read to end of tvb buffer */
352
2
    proto_tree_add_item(sub_tree, hf_raknet_null_padding, tvb, offset,
353
2
                        -1, ENC_NA);
354
355
2
    return tvb_reported_length(tvb);
356
2
}
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
2
{
362
2
    proto_tree *sub_tree;
363
2
    int offset;
364
2
    raknet_session_state_t* state;
365
366
2
    sub_tree = init_raknet_offline_message(tvb, pinfo, tree, &offset);
367
368
369
2
    proto_tree_add_item(sub_tree, hf_raknet_offline_message_data_id, tvb, offset,
370
2
                        16, ENC_NA);
371
2
    offset += 16;
372
373
2
    proto_tree_add_item(sub_tree, hf_raknet_server_guid, tvb, offset,
374
2
                        8, ENC_NA);
375
2
    offset += 8;
376
377
2
    state = raknet_get_session_state(pinfo);
378
2
    state->use_encryption = tvb_get_uint8(tvb, offset) ? true : false;
379
380
2
    proto_tree_add_item(sub_tree, hf_raknet_use_encryption, tvb,
381
2
                        offset, 1, ENC_NA);
382
2
    offset += 1;
383
384
2
    if (state->use_encryption) {
385
2
        proto_tree_add_item(sub_tree, hf_raknet_cookie, tvb,
386
2
                            offset, 4, ENC_BIG_ENDIAN);
387
2
        offset += 4;
388
389
2
        proto_tree_add_item(sub_tree, hf_raknet_server_public_key, tvb,
390
2
                            offset, 64, ENC_NA);
391
2
        offset += 64;
392
2
    }
393
394
2
    proto_tree_add_item(sub_tree, hf_raknet_mtu_size, tvb, offset,
395
2
                        2, ENC_BIG_ENDIAN);
396
2
    offset += 2;
397
398
2
    return offset;
399
2
}
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
2
{
405
2
    proto_tree *sub_tree;
406
2
    int offset;
407
2
    raknet_session_state_t* state;
408
409
2
    sub_tree = init_raknet_offline_message(tvb, pinfo, tree, &offset);
410
411
2
    proto_tree_add_item(sub_tree, hf_raknet_offline_message_data_id, tvb, offset,
412
2
                        16, ENC_NA);
413
2
    offset += 16;
414
415
2
    state = raknet_get_session_state(pinfo);
416
2
    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
2
    raknet_dissect_system_address(
436
2
            sub_tree, hf_raknet_server_address, pinfo, tvb, &offset);
437
438
2
    proto_tree_add_item(sub_tree, hf_raknet_mtu_size, tvb, offset,
439
2
                        2, ENC_BIG_ENDIAN);
440
2
    offset += 2;
441
442
2
    proto_tree_add_item(sub_tree, hf_raknet_client_guid, tvb, offset,
443
2
                        8, ENC_NA);
444
2
    offset += 8;
445
446
2
    return offset;
447
2
}
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
1
{
494
1
    proto_tree *sub_tree;
495
1
    int offset;
496
497
1
    sub_tree = init_raknet_offline_message(tvb, pinfo, tree, &offset);
498
499
1
    proto_tree_add_item(sub_tree, hf_raknet_raknet_proto_ver, tvb,
500
1
                        offset, 1, ENC_BIG_ENDIAN);
501
1
    offset += 1;
502
503
1
    proto_tree_add_item(sub_tree, hf_raknet_offline_message_data_id, tvb, offset,
504
1
                        16, ENC_NA);
505
1
    offset += 16;
506
507
1
    proto_tree_add_item(sub_tree, hf_raknet_server_guid, tvb, offset,
508
1
                        8, ENC_NA);
509
1
    offset += 8;
510
511
1
    return offset;
512
1
}
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
0
{
538
0
    proto_tree *sub_tree;
539
0
    uint32_t str_size;
540
0
    int offset;
541
542
0
    sub_tree = init_raknet_offline_message(tvb, pinfo, tree, &offset);
543
544
0
    proto_tree_add_item(sub_tree, hf_raknet_timestamp, tvb,
545
0
                        offset, 8, ENC_BIG_ENDIAN);
546
0
    offset += 8;
547
548
0
    proto_tree_add_item(sub_tree, hf_raknet_server_guid, tvb, offset,
549
0
                        8, ENC_NA);
550
0
    offset += 8;
551
552
0
    proto_tree_add_item(sub_tree, hf_raknet_offline_message_data_id, tvb, offset,
553
0
                        16, ENC_NA);
554
0
    offset += 16;
555
556
    /* raknet precedes strings with a short (2 bytes) holding string length. */
557
0
    proto_tree_add_item_ret_uint(sub_tree, hf_raknet_0x1C_server_id_str_len, tvb,
558
0
                                 offset, 2, ENC_BIG_ENDIAN, &str_size);
559
0
    offset += 2;
560
561
0
    proto_tree_add_item(sub_tree, hf_raknet_0x1C_server_id_str, tvb, offset,
562
0
                        str_size, ENC_ASCII);
563
0
    offset += str_size;
564
565
0
    return offset;
566
0
}
567
568
static int
569
raknet_dissect_connected_ping(tvbuff_t *tvb, packet_info *pinfo _U_,
570
                              proto_tree *tree, void* data _U_)
571
9
{
572
573
9
    int offset = 1;
574
575
9
    proto_tree_add_item(tree, hf_raknet_timestamp, tvb,
576
9
                        offset, 8, ENC_BIG_ENDIAN);
577
9
    offset += 8;
578
579
9
    return offset;
580
9
}
581
582
static int
583
raknet_dissect_connected_pong(tvbuff_t *tvb, packet_info *pinfo _U_,
584
                              proto_tree *tree, void* data _U_)
585
13
{
586
13
    int offset = 1;
587
588
13
    proto_tree_add_item(tree, hf_raknet_timestamp, tvb,
589
13
                        offset, 8, ENC_BIG_ENDIAN);
590
13
    offset += 8;
591
592
13
    proto_tree_add_item(tree, hf_raknet_timestamp, tvb,
593
13
                        offset, 8, ENC_BIG_ENDIAN);
594
13
    offset += 8;
595
596
13
    return offset;
597
13
}
598
599
static int
600
raknet_dissect_connection_request(tvbuff_t *tvb, packet_info *pinfo _U_,
601
                                  proto_tree *tree, void* data _U_)
602
3
{
603
3
    int offset = 1;
604
3
    bool use_encryption;
605
606
3
    proto_tree_add_item(tree, hf_raknet_client_guid, tvb, offset,
607
3
                        8, ENC_NA);
608
3
    offset += 8;
609
610
3
    proto_tree_add_item(tree, hf_raknet_timestamp, tvb,
611
3
                        offset, 8, ENC_BIG_ENDIAN);
612
3
    offset += 8;
613
614
3
    use_encryption = tvb_get_uint8(tvb, offset) ? true : false;
615
616
3
    proto_tree_add_item(tree, hf_raknet_use_encryption, tvb, offset,
617
3
                        1, ENC_NA);
618
3
    offset += 1;
619
620
3
    if (use_encryption) {
621
2
        bool use_client_key;
622
623
2
        proto_tree_add_item(tree, hf_raknet_client_proof, tvb, offset,
624
2
                            32, ENC_NA);
625
2
        offset += 32;
626
627
2
        use_client_key = tvb_get_uint8(tvb, offset) ? true : false;
628
629
2
        proto_tree_add_item(tree, hf_raknet_use_client_key, tvb, offset,
630
2
                            1, ENC_NA);
631
2
        offset += 1;
632
633
2
        if (use_client_key) {
634
1
            proto_tree_add_item(tree, hf_raknet_client_identity, tvb, offset,
635
1
                                160, ENC_NA);
636
1
            offset += 160;
637
1
        }
638
2
    }
639
640
3
    proto_tree_add_item(tree, hf_raknet_password, tvb, offset,
641
3
                       -1, ENC_NA);
642
643
3
    return tvb_reported_length(tvb);
644
3
}
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
1
{
650
1
    int offset = 1;
651
1
    int i;
652
653
1
    raknet_dissect_system_address(
654
1
            tree, hf_raknet_client_address, pinfo, tvb, &offset);
655
656
1
    proto_tree_add_item(tree, hf_raknet_system_index, tvb, offset,
657
1
                        2, ENC_BIG_ENDIAN);
658
1
    offset += 2;
659
660
11
    for (i = 0; i < RAKNET_NUMBER_OF_INTERNAL_IDS; i++) {
661
10
        raknet_dissect_system_address(
662
10
                tree, hf_raknet_internal_address, pinfo, tvb, &offset);
663
10
    }
664
665
1
    proto_tree_add_item(tree, hf_raknet_timestamp, tvb,
666
1
                        offset, 8, ENC_BIG_ENDIAN);
667
1
    offset += 8;
668
669
1
    proto_tree_add_item(tree, hf_raknet_timestamp, tvb,
670
1
                        offset, 8, ENC_BIG_ENDIAN);
671
1
    offset += 8;
672
673
1
    return offset;
674
1
}
675
676
static int
677
raknet_dissect_new_incoming_connection(tvbuff_t *tvb, packet_info *pinfo,
678
                                       proto_tree *tree, void* data _U_)
679
1
{
680
681
1
    int offset = 1;
682
1
    int i;
683
684
1
    raknet_dissect_system_address(
685
1
            tree, hf_raknet_server_address, pinfo, tvb, &offset);
686
687
3
    for (i = 0; i < RAKNET_NUMBER_OF_INTERNAL_IDS; i++) {
688
2
        raknet_dissect_system_address(
689
2
                tree, hf_raknet_internal_address, pinfo, tvb, &offset);
690
2
    }
691
692
1
    proto_tree_add_item(tree, hf_raknet_timestamp, tvb,
693
1
                        offset, 8, ENC_BIG_ENDIAN);
694
1
    offset += 8;
695
696
1
    proto_tree_add_item(tree, hf_raknet_timestamp, tvb,
697
1
                        offset, 8, ENC_BIG_ENDIAN);
698
1
    offset += 8;
699
700
701
1
    return offset;
702
1
}
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
9
{
798
9
    proto_tree *sub_tree;
799
9
    proto_item *ti;
800
9
    uint8_t message_id;
801
802
9
    *offset = 0;
803
804
    /*
805
     * Take buffer start 0 to end -1 as single raknet item.
806
     */
807
9
    ti = proto_tree_add_item(tree, proto_raknet, tvb, 0, -1, ENC_NA);
808
9
    sub_tree = proto_item_add_subtree(ti, ett_raknet);
809
810
9
    message_id = tvb_get_uint8(tvb, *offset);
811
9
    proto_tree_add_item(sub_tree, hf_raknet_offline_message_id, tvb, *offset,
812
9
                        1, ENC_BIG_ENDIAN);
813
9
    *offset += 1;
814
815
9
    col_add_str(pinfo->cinfo, COL_INFO,
816
9
                val_to_str(pinfo->pool, message_id, raknet_offline_message_names, "Unknown offline message: %#x"));
817
818
    /*
819
     * Append description to the raknet item.
820
     */
821
9
    proto_item_append_text(ti, ", Offline message ID %#x", message_id);
822
823
9
    return sub_tree;
824
9
}
825
826
static int
827
raknet_dissect_ACK(tvbuff_t *tvb, packet_info *pinfo,
828
                   proto_tree *tree, void* data)
829
23
{
830
23
    int offset = 0;
831
23
    proto_tree *sub_tree;
832
23
    uint32_t count;
833
23
    uint32_t i;
834
835
23
    if (*(bool*)data) {
836
16
        col_set_str(pinfo->cinfo, COL_INFO, "ACK");
837
16
    }
838
7
    else {
839
7
        col_set_str(pinfo->cinfo, COL_INFO, "NAK");
840
7
    }
841
842
23
    proto_tree_add_item_ret_uint(tree, hf_raknet_NACK_record_count, tvb,
843
23
                                 offset, 2, ENC_BIG_ENDIAN, &count);
844
23
    offset += 2;
845
846
586
    for (i = 0; i < count; i++) {
847
563
        proto_item *ti;
848
563
        uint32_t max;
849
563
        uint32_t min;
850
851
563
        if (i == 0) {
852
22
            col_append_str(pinfo->cinfo, COL_INFO, " ");
853
22
        }
854
541
        else {
855
541
            col_append_str(pinfo->cinfo, COL_INFO, ", ");
856
541
        }
857
858
563
        if (tvb_get_uint8(tvb, offset)) { /* maxEqualToMin */
859
458
            min = tvb_get_uint24(tvb, offset + 1, ENC_LITTLE_ENDIAN);
860
861
458
            col_append_fstr(pinfo->cinfo, COL_INFO, "#%" PRIu32, min);
862
863
458
            ti = proto_tree_add_string_format_value(tree, hf_raknet_packet_number_range, tvb,
864
458
                                                    offset, 1 + 3, "",
865
458
                                                    "%" PRIu32 " .. %" PRIu32,
866
458
                                                    min, min);
867
458
            sub_tree = proto_item_add_subtree(ti, ett_raknet_packet_number_range);
868
869
458
            proto_tree_add_item(sub_tree, hf_raknet_range_max_equal_to_min, tvb,
870
458
                                offset, 1, ENC_NA);
871
458
            offset += 1;
872
873
458
            proto_tree_add_item(sub_tree, hf_raknet_packet_number_min, tvb,
874
458
                                offset, 3, ENC_LITTLE_ENDIAN);
875
458
            offset += 3;
876
458
        }
877
105
        else {
878
105
            min = tvb_get_uint24(tvb, offset + 1    , ENC_LITTLE_ENDIAN);
879
105
            max = tvb_get_uint24(tvb, offset + 1 + 3, ENC_LITTLE_ENDIAN);
880
881
105
            col_append_fstr(pinfo->cinfo, COL_INFO,
882
105
                            "#%" PRIu32 "..%" PRIu32,
883
105
                            min, max);
884
885
105
            ti = proto_tree_add_string_format_value(tree, hf_raknet_packet_number_range, tvb,
886
105
                                                    offset, 1 + 3 + 3, "",
887
105
                                                    "%" PRIu32 " .. %" PRIu32, min, max);
888
105
            sub_tree = proto_item_add_subtree(ti, ett_raknet_packet_number_range);
889
890
105
            proto_tree_add_item(sub_tree, hf_raknet_range_max_equal_to_min, tvb,
891
105
                                offset, 1, ENC_NA);
892
105
            offset += 1;
893
894
105
            proto_tree_add_item(sub_tree, hf_raknet_packet_number_min, tvb,
895
105
                                offset, 3, ENC_LITTLE_ENDIAN);
896
105
            offset += 3;
897
898
105
            proto_tree_add_item(sub_tree, hf_raknet_packet_number_max, tvb,
899
105
                                offset, 3, ENC_LITTLE_ENDIAN);
900
105
            offset += 3;
901
105
        }
902
563
    }
903
904
23
    return tvb_captured_length(tvb);
905
23
}
906
907
static int
908
raknet_dissect_common_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *raknet_tree, void *data)
909
80
{
910
80
    int offset = 0;
911
80
    bool *has_multiple_messages;
912
80
    proto_item *ti;
913
80
    proto_item *raknet_ti;
914
80
    proto_item *msg_ti;
915
80
    proto_tree *msg_tree;
916
80
    uint64_t msg_flags;
917
80
    uint32_t payload_bits;
918
80
    uint32_t payload_octets;
919
80
    raknet_reliability_t reliability;
920
80
    bool has_split_packet;
921
80
    uint8_t message_id;
922
80
    int message_size;
923
80
    proto_tree *payload_tree;
924
80
    tvbuff_t* next_tvb;
925
80
    bool next_tvb_is_subset;
926
80
    dissector_handle_t next_dissector;
927
80
    int dissected;
928
80
    heur_dtbl_entry_t *hdtbl_entry;
929
80
    static int * const flag_flds[] = {
930
80
        &hf_raknet_message_reliability,
931
80
        &hf_raknet_message_has_split_packet,
932
80
        NULL
933
80
    };
934
935
80
    has_multiple_messages = (bool*)data;
936
80
    raknet_ti = proto_tree_get_parent(raknet_tree);
937
938
80
    msg_ti = proto_tree_add_item(raknet_tree, hf_raknet_message, tvb, offset, -1, ENC_NA);
939
80
    msg_tree = proto_item_add_subtree(msg_ti, ett_raknet_message);
940
80
    proto_item_append_text(msg_ti, ", ");
941
942
80
    proto_tree_add_bitmask_ret_uint64(msg_tree, tvb, offset, hf_raknet_message_flags,
943
80
                                      ett_raknet_message_flags, flag_flds, ENC_NA, &msg_flags);
944
80
    offset += 1;
945
946
80
    ti = proto_tree_add_item_ret_uint(msg_tree, hf_raknet_payload_length, tvb,
947
80
                                      offset, 2, ENC_BIG_ENDIAN, &payload_bits);
948
80
    offset += 2;
949
80
    payload_octets = payload_bits / 8 + (payload_bits % 8 > 0); /* ceil(bits / 8) */
950
80
    proto_item_append_text(ti, " bits (%" PRIu32 " octets)", payload_octets);
951
952
80
    reliability = (raknet_reliability_t)((msg_flags >> 5) & 0x07);
953
80
    has_split_packet = (msg_flags >> 4) & 0x01 ? true : false;
954
955
80
    if (reliability == RAKNET_RELIABLE ||
956
77
        reliability == RAKNET_RELIABLE_SEQUENCED ||
957
69
        reliability == RAKNET_RELIABLE_ORDERED ) {
958
959
16
        proto_tree_add_item(msg_tree, hf_raknet_reliable_message_number, tvb,
960
16
                            offset, 3, ENC_LITTLE_ENDIAN);
961
16
        offset += 3;
962
16
    }
963
964
80
    if (reliability == RAKNET_UNRELIABLE_SEQUENCED ||
965
76
        reliability == RAKNET_RELIABLE_SEQUENCED) {
966
967
12
        proto_tree_add_item(msg_tree, hf_raknet_message_sequencing_index, tvb,
968
12
                            offset, 3, ENC_LITTLE_ENDIAN);
969
12
        offset += 3;
970
12
    }
971
972
80
    if (reliability == RAKNET_UNRELIABLE_SEQUENCED ||
973
76
        reliability == RAKNET_RELIABLE_SEQUENCED ||
974
68
        reliability == RAKNET_RELIABLE_ORDERED) {
975
976
17
        proto_tree_add_item(msg_tree, hf_raknet_message_ordering_index, tvb,
977
17
                            offset, 3, ENC_LITTLE_ENDIAN);
978
17
        offset += 3;
979
980
17
        proto_tree_add_item(msg_tree, hf_raknet_message_ordering_channel, tvb,
981
17
                            offset, 1, ENC_NA);
982
17
        offset += 1;
983
17
    }
984
985
80
    if (has_split_packet) {
986
19
        bool save_fragmented;
987
19
        uint32_t split_packet_count;
988
19
        uint32_t split_packet_id;
989
19
        uint32_t split_packet_index;
990
19
        fragment_head *frag_msg;
991
992
993
19
        proto_tree_add_item_ret_uint(msg_tree, hf_raknet_split_packet_count, tvb,
994
19
                                     offset, 4, ENC_BIG_ENDIAN, &split_packet_count);
995
19
        offset += 4;
996
997
19
        proto_tree_add_item_ret_uint(msg_tree, hf_raknet_split_packet_id, tvb,
998
19
                                     offset, 2, ENC_BIG_ENDIAN, &split_packet_id);
999
19
        offset += 2;
1000
1001
19
        proto_tree_add_item_ret_uint(msg_tree, hf_raknet_split_packet_index, tvb,
1002
19
                                     offset, 4, ENC_BIG_ENDIAN, &split_packet_index);
1003
19
        offset += 4;
1004
1005
        /*
1006
         * Reassemble the fragmented packet.
1007
         */
1008
19
        save_fragmented = pinfo->fragmented;
1009
19
        pinfo->fragmented = true;
1010
1011
19
        frag_msg =
1012
19
            fragment_add_seq_check(&raknet_reassembly_table,
1013
19
                                   tvb, offset, pinfo,
1014
19
                                   split_packet_id,
1015
19
                                   NULL,
1016
19
                                   split_packet_index,
1017
19
                                   payload_octets,
1018
19
                                   split_packet_index != split_packet_count - 1);
1019
1020
19
        next_tvb =
1021
19
            process_reassembled_data(tvb, offset, pinfo, "Reassembled packet",
1022
19
                                     frag_msg, &raknet_frag_items, NULL, msg_tree);
1023
1024
19
        pinfo->fragmented = save_fragmented;
1025
1026
19
        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
19
        else {
1044
19
            wmem_strbuf_t *strbuf;
1045
1046
19
            strbuf = wmem_strbuf_new(pinfo->pool, "");
1047
19
            wmem_strbuf_append_printf(strbuf,
1048
19
                                      "{Message fragment %" PRIu32 "/%" PRIu32 "}",
1049
19
                                      split_packet_index + 1, split_packet_count);
1050
1051
19
            proto_item_append_text(msg_ti, "%s", wmem_strbuf_get_str(strbuf));
1052
19
            col_add_str(pinfo->cinfo, COL_INFO, wmem_strbuf_get_str(strbuf));
1053
1054
19
            ti = proto_tree_add_item(msg_tree, hf_raknet_split_packet, tvb, offset,
1055
19
                                     payload_octets, ENC_NA);
1056
19
            proto_item_append_text(ti, " (%u octets)", payload_octets);
1057
19
        }
1058
19
    }
1059
61
    else {
1060
61
        next_tvb = tvb_new_subset_length(tvb, offset, payload_octets);
1061
61
        next_tvb_is_subset = true;
1062
61
    }
1063
1064
    /*
1065
     * At this point we can finally check if the packet has multiple
1066
     * messages.
1067
     */
1068
80
    if (! *has_multiple_messages) {
1069
24
        *has_multiple_messages =
1070
24
            tvb_reported_length_remaining(tvb, offset) > (int)payload_octets
1071
24
            ? true : false;
1072
24
    }
1073
1074
    /*
1075
     * And we finally have the actual size of message.
1076
     */
1077
80
    message_size = offset + payload_octets;
1078
1079
80
    if (!next_tvb) {
1080
        /*
1081
         * It was an incomplete message fragment.
1082
         */
1083
18
        proto_item_set_len(msg_ti, message_size);
1084
18
        if (raknet_ti) {
1085
18
            proto_item_set_len(raknet_ti, proto_item_get_len(raknet_ti) + message_size);
1086
18
        }
1087
18
        return message_size;
1088
18
    }
1089
1090
62
    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
62
    next_dissector =
1097
62
        dissector_get_uint_handle(raknet_system_message_dissectors, message_id);
1098
1099
62
    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
27
        ti = proto_tree_add_item(msg_tree, hf_raknet_system_message, next_tvb, 0, -1, ENC_NA);
1106
27
        payload_tree = proto_item_add_subtree(ti, ett_raknet_system_message);
1107
1108
27
        proto_item_append_text(ti, " (%s)",
1109
27
                               val_to_str(pinfo->pool, message_id, raknet_system_message_names, "Unknown ID: %#x"));
1110
1111
27
        proto_item_append_text(msg_ti, "ID %#x (%s)", message_id,
1112
27
                               val_to_str_const(message_id, raknet_system_message_names, "Unknown"));
1113
1114
27
        col_add_str(pinfo->cinfo, COL_INFO,
1115
27
                    val_to_str(pinfo->pool, message_id, raknet_system_message_names, "Unknown system message ID: %#x"));
1116
1117
27
        proto_tree_add_item(payload_tree, hf_raknet_system_message_id,
1118
27
                            next_tvb, 0, 1, ENC_NA);
1119
1120
27
        dissected =
1121
27
            call_dissector_only(next_dissector, next_tvb, pinfo, payload_tree, data);
1122
1123
27
        proto_item_set_len(msg_ti, message_size);
1124
27
        if (raknet_ti) {
1125
24
            proto_item_set_len(raknet_ti, proto_item_get_len(raknet_ti) + message_size);
1126
24
        }
1127
1128
27
        if (dissected >= 0) {
1129
24
            return message_size;
1130
24
        }
1131
3
        else {
1132
3
            return dissected;
1133
3
        }
1134
27
    }
1135
1136
    /*
1137
     * It seems not to be a system message so use a dissector set for
1138
     * this conversation if any.
1139
     */
1140
35
    next_dissector =
1141
35
        raknet_get_session_state(pinfo)->subdissector;
1142
1143
    /*
1144
     * And of course we don't know the name of message.
1145
     */
1146
35
    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
35
    if (*has_multiple_messages) {
1154
31
        payload_tree = msg_tree;
1155
31
    }
1156
4
    else {
1157
4
        payload_tree = proto_tree_get_root(raknet_tree);
1158
4
    }
1159
1160
35
    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
35
    next_dissector =
1177
35
        dissector_get_uint_handle(raknet_port_dissectors, pinfo->match_uint);
1178
1179
35
    if (next_dissector) {
1180
4
        dissected =
1181
4
            call_dissector_only(next_dissector, next_tvb, pinfo, payload_tree, data);
1182
1183
4
        if (dissected > 0) {
1184
0
            goto FIX_UP_AND_RETURN;
1185
0
        }
1186
4
        else {
1187
4
            expert_add_info(pinfo, msg_tree, &ei_raknet_subdissector_failed);
1188
4
        }
1189
4
    }
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
35
    dissected =
1196
35
        dissector_try_heuristic(raknet_heur_subdissectors, next_tvb, pinfo, payload_tree,
1197
35
                                &hdtbl_entry, data);
1198
35
    if (!dissected) {
1199
34
        col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown message ID: %#x", message_id);
1200
1201
34
        ti = proto_tree_add_expert(msg_tree, pinfo, &ei_raknet_unknown_message_id, next_tvb,
1202
34
                                   0, 1);
1203
34
        proto_item_append_text(ti, " %#x", message_id);
1204
34
    }
1205
1206
35
  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
34
    if (!*has_multiple_messages && next_tvb_is_subset) {
1214
3
        proto_item_set_len(msg_ti, message_size - payload_octets);
1215
3
        if (raknet_ti) {
1216
3
            proto_item_set_len(raknet_ti, proto_item_get_len(raknet_ti) + message_size - payload_octets);
1217
3
        }
1218
3
    }
1219
31
    else {
1220
31
        proto_item_set_len(msg_ti, message_size);
1221
31
        if (raknet_ti) {
1222
31
            proto_item_set_len(raknet_ti, proto_item_get_len(raknet_ti) + message_size);
1223
31
        }
1224
31
    }
1225
34
    return message_size;
1226
35
}
1227
1228
static int
1229
raknet_dissect_connected_message(tvbuff_t *tvb, packet_info *pinfo,
1230
                                 proto_tree *root_tree, void* data _U_)
1231
51
{
1232
51
    raknet_session_state_t* state;
1233
51
    proto_item *ti;
1234
51
    proto_tree *raknet_tree;
1235
51
    int item_size;
1236
51
    int offset = 0;
1237
51
    uint8_t msg_type;
1238
1239
51
    state = raknet_get_session_state(pinfo);
1240
51
    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
51
    msg_type = tvb_get_uint8(tvb, offset);
1255
1256
51
    if (!(msg_type & (1 << 7))) { /* !isValid */
1257
        /*
1258
         * No suitable dissector was registered for this offline
1259
         * message.
1260
         */
1261
3
        col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown offline message ID: %#x", msg_type);
1262
3
        ti = proto_tree_add_expert(root_tree, pinfo, &ei_raknet_unknown_message_id, tvb,
1263
3
                                   0, 1);
1264
3
        proto_item_append_text(ti, " %#x", msg_type);
1265
3
        return tvb_captured_length(tvb);
1266
3
    }
1267
48
    else if (msg_type & (1 << 6)) { /* isACK */
1268
17
        static int * const ack_flds[] = {
1269
17
            &hf_raknet_packet_is_for_connected,
1270
17
            &hf_raknet_packet_is_ACK,
1271
17
            &hf_raknet_packet_has_B_and_AS,
1272
17
            NULL
1273
17
        };
1274
1275
17
        ti = proto_tree_add_item(root_tree, proto_raknet, tvb, 0, -1, ENC_NA);
1276
17
        proto_item_append_text(ti, ", ACK");
1277
17
        raknet_tree = proto_item_add_subtree(ti, ett_raknet);
1278
1279
17
        proto_tree_add_bitmask(raknet_tree, tvb, offset, hf_raknet_packet_type,
1280
17
                               ett_raknet_packet_type, ack_flds, ENC_NA);
1281
17
        offset += 1;
1282
1283
17
        if (msg_type & (1 << 5)) { /* hasBAndAS */
1284
9
            proto_tree_add_item(raknet_tree, hf_raknet_AS, tvb, offset,
1285
9
                                4, ENC_BIG_ENDIAN);
1286
9
            offset += 4;
1287
9
        }
1288
1289
17
        if (raknet_tree) {
1290
16
            bool is_ACK = true;
1291
16
            return raknet_dissect_ACK(tvb_new_subset_remaining(tvb, offset),
1292
16
                                      pinfo, raknet_tree, &is_ACK);
1293
16
        }
1294
1
        else {
1295
1
            return tvb_captured_length(tvb);
1296
1
        }
1297
17
    }
1298
31
    else if (msg_type & (1 << 5)) { /* isNAK */
1299
7
        static int * const nak_flds[] = {
1300
7
            &hf_raknet_packet_is_for_connected,
1301
7
            &hf_raknet_packet_is_ACK,
1302
7
            &hf_raknet_packet_is_NAK,
1303
7
            NULL
1304
7
        };
1305
1306
7
        ti = proto_tree_add_item(root_tree, proto_raknet, tvb, 0, -1, ENC_NA);
1307
7
        proto_item_append_text(ti, ", NAK");
1308
7
        raknet_tree = proto_item_add_subtree(ti, ett_raknet);
1309
1310
7
        proto_tree_add_bitmask(raknet_tree, tvb, offset, hf_raknet_packet_type,
1311
7
                               ett_raknet_packet_type, nak_flds, ENC_NA);
1312
7
        offset += 1;
1313
1314
7
        if (raknet_tree) {
1315
7
            bool is_ACK = false;
1316
7
            return raknet_dissect_ACK(tvb_new_subset_remaining(tvb, offset),
1317
7
                                      pinfo, raknet_tree, &is_ACK);
1318
7
        }
1319
0
        else {
1320
0
            return tvb_captured_length(tvb);
1321
0
        }
1322
7
    }
1323
24
    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
24
        uint32_t packet_number;
1330
24
        bool has_multiple_messages = false;
1331
24
        static int * const common_flds[] = {
1332
24
            &hf_raknet_packet_is_for_connected,
1333
24
            &hf_raknet_packet_is_ACK,
1334
24
            &hf_raknet_packet_is_NAK,
1335
24
            &hf_raknet_packet_is_pair,
1336
24
            &hf_raknet_packet_is_continuous_send,
1337
24
            &hf_raknet_packet_needs_B_and_AS,
1338
24
            NULL
1339
24
        };
1340
1341
24
        ti = proto_tree_add_item(root_tree, proto_raknet, tvb, 0, 0, ENC_NA);
1342
24
        raknet_tree = proto_item_add_subtree(ti, ett_raknet);
1343
1344
24
        proto_tree_add_bitmask(raknet_tree, tvb, offset, hf_raknet_packet_type,
1345
24
                               ett_raknet_packet_type, common_flds, ENC_NA);
1346
24
        offset += 1;
1347
1348
24
        proto_tree_add_item_ret_uint(raknet_tree, hf_raknet_packet_number, tvb,
1349
24
                                     offset, 3, ENC_LITTLE_ENDIAN, &packet_number);
1350
24
        offset += 3;
1351
1352
24
        proto_item_append_text(ti, ", Message #%" PRIu32, packet_number);
1353
24
        col_add_fstr(pinfo->cinfo, COL_INFO, "#%" PRIu32 ": ", packet_number);
1354
24
        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
24
        proto_item_set_len(ti, offset);
1362
1363
80
        while (true) {
1364
80
            int dissected;
1365
1366
80
            dissected = raknet_dissect_common_message(tvb_new_subset_remaining(tvb, offset), pinfo,
1367
80
                                                      raknet_tree, &has_multiple_messages);
1368
80
            if (dissected >= 0) {
1369
76
                offset += dissected;
1370
1371
76
                if (tvb_reported_length_remaining(tvb, offset) > 0) {
1372
                    /*
1373
                     * More messages are in the packet.
1374
                     */
1375
56
                    col_append_str(pinfo->cinfo, COL_INFO, ", ");
1376
56
                    col_set_fence(pinfo->cinfo, COL_INFO);
1377
56
                    continue;
1378
56
                }
1379
20
                else {
1380
                    /*
1381
                     * It's the end of packet.
1382
                     */
1383
20
                    break;
1384
20
                }
1385
76
            }
1386
4
            else {
1387
4
                return dissected;
1388
4
            }
1389
80
        }
1390
1391
20
        return tvb_captured_length(tvb);
1392
24
    }
1393
51
}
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
60
{
1404
60
    uint8_t message_id;
1405
60
    int dissected;
1406
1407
60
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "RakNet");
1408
60
    col_clear(pinfo->cinfo, COL_INFO);
1409
1410
60
    message_id = tvb_get_uint8(tvb, 0);
1411
1412
60
    dissected = dissector_try_uint_with_data(raknet_offline_message_dissectors, message_id, tvb,
1413
60
                                       pinfo, tree, true, data);
1414
60
    if (!dissected) {
1415
51
        raknet_dissect_connected_message(tvb, pinfo, tree, data);
1416
51
    }
1417
1418
60
    return tvb_captured_length(tvb);
1419
60
}
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.87k
{
1429
1.87k
    if (tvb_memeql(tvb, 1 + 8, RAKNET_OFFLINE_MESSAGE_DATA_ID, sizeof(RAKNET_OFFLINE_MESSAGE_DATA_ID)) == 0) {
1430
        /* ID_UNCONNECTED_PING */
1431
14
        return true;
1432
14
    }
1433
1.86k
    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
7
        return true;
1436
7
    }
1437
1.85k
    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.85k
    else {
1442
1.85k
        return false;
1443
1.85k
    }
1444
1.87k
}
1445
1446
static bool
1447
dissect_raknet_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1448
1.87k
{
1449
1.87k
    if (test_raknet_heur(tvb, pinfo, tree, data)) {
1450
28
        conversation_t* conversation;
1451
1452
28
        conversation = find_or_create_conversation(pinfo);
1453
28
        conversation_set_dissector(conversation, raknet_handle);
1454
1455
28
        return call_dissector_only(raknet_handle, tvb, pinfo, tree, data) > 0;
1456
28
    }
1457
1.85k
    else {
1458
1.85k
        return false;
1459
1.85k
    }
1460
1.87k
}
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
 */