Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-raknet.c
blobaf9078598ce42936b2acabfc516645616cd445f4
1 /*
2 * packet-raknet.c
4 * Routines for RakNet protocol packet disassembly.
6 * Ref: https://github.com/OculusVR/RakNet
8 * Nick Carter <ncarter100@gmail.com>
9 * Copyright 2014 Nick Carter
11 * Wireshark - Network traffic analyzer
12 * By Gerald Combs <gerald@wireshark.org>
13 * Copyright 1998 Gerald Combs
15 * SPDX-License-Identifier: GPL-2.0-or-later
17 #include "config.h"
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>
27 #include "packet-raknet.h"
30 * RakNet Protocol Constants.
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 #define RAKNET_NUMBER_OF_INTERNAL_IDS 10
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;
49 * Dissectors
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;
58 * Expert fields
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;
66 * First byte gives us the packet id
68 static int hf_raknet_offline_message_id;
71 * General fields (fields that are in >1 packet types.
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;
85 * Fields specific to a packet id type
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;
136 * Frame reassembly
138 static reassembly_table raknet_reassembly_table;
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;
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"
177 * Session state
179 typedef struct raknet_session_state {
180 bool use_encryption;
181 dissector_handle_t subdissector;
182 } raknet_session_state_t;
185 * Reliability strings
186 * Ref: ..RakNet/Source/PacketPriority.h
188 * Note that ACK receipts will not be transmitted to the wire. See
189 * ReliabilityLayer::WriteToBitStreamFromInternalPacket()
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" )
198 typedef VALUE_STRING_ENUM(raknet_reliability) raknet_reliability_t;
199 VALUE_STRING_ARRAY(raknet_reliability);
202 * Forward declarations.
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);
210 * Called by dissectors for protocols that run atop RakNet/UDP.
212 void
213 raknet_add_udp_dissector(uint32_t port, const dissector_handle_t handle) {
215 * Register ourselves as the handler for that port number
216 * over TCP.
218 dissector_add_uint("udp.port", port, raknet_handle);
221 * And register them in *our* table for that port.
223 dissector_add_uint("raknet.port", port, handle);
226 void
227 raknet_delete_udp_dissector(uint32_t port, const dissector_handle_t handle) {
228 dissector_delete_uint("udp.port", port, raknet_handle);
229 dissector_delete_uint("raknet.port", port, handle);
232 static raknet_session_state_t*
233 raknet_get_session_state(packet_info *pinfo) {
234 conversation_t* conversation;
235 raknet_session_state_t* state;
237 conversation = find_or_create_conversation(pinfo);
238 state = (raknet_session_state_t*)conversation_get_proto_data(conversation, proto_raknet);
240 if (state == NULL) {
241 state = wmem_new(wmem_file_scope(), raknet_session_state_t);
242 state->use_encryption = false;
243 state->subdissector = NULL;
244 conversation_add_proto_data(conversation, proto_raknet, state);
247 return state;
250 void
251 raknet_conversation_set_dissector(packet_info *pinfo, const dissector_handle_t handle) {
252 raknet_session_state_t *state;
254 state = raknet_get_session_state(pinfo);
255 state->subdissector = handle;
258 static void
259 raknet_dissect_system_address(proto_tree *tree, int hf,
260 packet_info *pinfo, tvbuff_t *tvb, int *offset) {
261 proto_item *ti;
262 proto_tree *sub_tree;
263 uint8_t ip_version;
264 uint32_t v4_addr;
265 uint16_t port;
266 address addr;
267 char *addr_str;
269 /* XXX - does it really make sense to have a string hf that's set to
270 an empty string? */
271 ti = proto_tree_add_string(tree, hf, tvb, *offset, -1, "");
272 sub_tree = proto_item_add_subtree(ti, ett_raknet_system_address);
273 ip_version = tvb_get_uint8(tvb, *offset);
274 proto_tree_add_item(sub_tree, hf_raknet_ip_version, tvb, *offset, 1, ENC_NA);
275 (*offset)++;
276 switch (ip_version) {
277 case 4:
279 * IPv4 addresses are bit-inverted to prevent routers from
280 * changing them. See ..RakNet/Source/BitStream.h
281 * (BitStream::Write)
283 v4_addr = ~tvb_get_ipv4(tvb, *offset);
284 set_address(&addr, AT_IPv4, sizeof(v4_addr), &v4_addr);
285 addr_str = address_to_display(pinfo->pool, &addr);
286 proto_tree_add_ipv4(sub_tree, hf_raknet_ipv4_address, tvb, *offset, 4, v4_addr);
287 *offset += 4;
288 port = tvb_get_ntohs(tvb, *offset);
289 proto_tree_add_item(sub_tree, hf_raknet_port, tvb, *offset, 2, ENC_BIG_ENDIAN);
290 *offset += 2;
291 proto_item_set_len(ti, 1 + 4 + 2);
292 proto_item_append_text(ti, "%s:%" PRIu16, addr_str, port);
293 break;
294 case 6:
295 addr_str = tvb_ip6_to_str(pinfo->pool, tvb, *offset);
296 proto_tree_add_item(sub_tree, hf_raknet_ipv6_address, tvb, *offset, 16, ENC_NA);
297 *offset += 16;
298 port = tvb_get_ntohs(tvb, *offset);
299 proto_tree_add_item(sub_tree, hf_raknet_port, tvb, *offset, 2, ENC_BIG_ENDIAN);
300 *offset += 2;
301 proto_item_set_len(ti, 1 + 16 + 2);
302 proto_item_append_text(ti, "[%s]:%" PRIu16, addr_str, port);
303 break;
304 default:
305 proto_item_set_len(ti, 1);
306 expert_add_info(pinfo, sub_tree, &ei_raknet_ip_ver_invalid);
310 static int
311 raknet_dissect_unconnected_ping(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
312 void *data _U_)
314 proto_tree *sub_tree;
315 int offset;
317 sub_tree = init_raknet_offline_message(tvb, pinfo, tree, &offset);
319 proto_tree_add_item(sub_tree, hf_raknet_timestamp, tvb,
320 offset, 8, ENC_BIG_ENDIAN);
321 offset += 8;
323 proto_tree_add_item(sub_tree, hf_raknet_offline_message_data_id, tvb, offset,
324 16, ENC_NA);
325 offset += 16;
327 proto_tree_add_item(sub_tree, hf_raknet_client_guid, tvb,
328 offset, 8, ENC_NA);
329 offset += 8;
331 return offset;
334 static int
335 raknet_dissect_open_connection_request_1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
336 void *data _U_)
338 proto_tree *sub_tree;
339 int offset;
341 sub_tree = init_raknet_offline_message(tvb, pinfo, tree, &offset);
343 proto_tree_add_item(sub_tree, hf_raknet_offline_message_data_id, tvb, offset,
344 16, ENC_NA);
345 offset += 16;
347 proto_tree_add_item(sub_tree, hf_raknet_raknet_proto_ver, tvb, offset,
348 1, ENC_BIG_ENDIAN);
349 offset += 1;
351 /* -1 read to end of tvb buffer */
352 proto_tree_add_item(sub_tree, hf_raknet_null_padding, tvb, offset,
353 -1, ENC_NA);
355 return tvb_reported_length(tvb);
358 static int
359 raknet_dissect_open_connection_reply_1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
360 void *data _U_)
362 proto_tree *sub_tree;
363 int offset;
364 raknet_session_state_t* state;
366 sub_tree = init_raknet_offline_message(tvb, pinfo, tree, &offset);
369 proto_tree_add_item(sub_tree, hf_raknet_offline_message_data_id, tvb, offset,
370 16, ENC_NA);
371 offset += 16;
373 proto_tree_add_item(sub_tree, hf_raknet_server_guid, tvb, offset,
374 8, ENC_NA);
375 offset += 8;
377 state = raknet_get_session_state(pinfo);
378 state->use_encryption = tvb_get_uint8(tvb, offset) ? true : false;
380 proto_tree_add_item(sub_tree, hf_raknet_use_encryption, tvb,
381 offset, 1, ENC_NA);
382 offset += 1;
384 if (state->use_encryption) {
385 proto_tree_add_item(sub_tree, hf_raknet_cookie, tvb,
386 offset, 4, ENC_BIG_ENDIAN);
387 offset += 4;
389 proto_tree_add_item(sub_tree, hf_raknet_server_public_key, tvb,
390 offset, 64, ENC_NA);
391 offset += 64;
394 proto_tree_add_item(sub_tree, hf_raknet_mtu_size, tvb, offset,
395 2, ENC_BIG_ENDIAN);
396 offset += 2;
398 return offset;
401 static int
402 raknet_dissect_open_connection_request_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
403 void *data _U_)
405 proto_tree *sub_tree;
406 int offset;
407 raknet_session_state_t* state;
409 sub_tree = init_raknet_offline_message(tvb, pinfo, tree, &offset);
411 proto_tree_add_item(sub_tree, hf_raknet_offline_message_data_id, tvb, offset,
412 16, ENC_NA);
413 offset += 16;
415 state = raknet_get_session_state(pinfo);
416 if (state->use_encryption) {
417 bool client_wrote_challenge;
419 proto_tree_add_item(sub_tree, hf_raknet_cookie, tvb, offset,
420 4, ENC_BIG_ENDIAN);
421 offset += 4;
423 client_wrote_challenge = tvb_get_uint8(tvb, offset) ? true : false;
424 proto_tree_add_item(sub_tree, hf_raknet_client_wrote_challenge, tvb, offset,
425 1, ENC_NA);
426 offset += 1;
428 if (client_wrote_challenge) {
429 proto_tree_add_item(sub_tree, hf_raknet_client_challenge, tvb,
430 offset, 64, ENC_NA);
431 offset += 64;
435 raknet_dissect_system_address(
436 sub_tree, hf_raknet_server_address, pinfo, tvb, &offset);
438 proto_tree_add_item(sub_tree, hf_raknet_mtu_size, tvb, offset,
439 2, ENC_BIG_ENDIAN);
440 offset += 2;
442 proto_tree_add_item(sub_tree, hf_raknet_client_guid, tvb, offset,
443 8, ENC_NA);
444 offset += 8;
446 return offset;
449 static int
450 raknet_dissect_open_connection_reply_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
451 void *data _U_)
453 proto_tree *sub_tree;
454 int offset;
455 raknet_session_state_t* state;
457 sub_tree = init_raknet_offline_message(tvb, pinfo, tree, &offset);
459 proto_tree_add_item(sub_tree, hf_raknet_offline_message_data_id, tvb, offset,
460 16, ENC_NA);
461 offset += 16;
463 proto_tree_add_item(sub_tree, hf_raknet_server_guid, tvb, offset,
464 8, ENC_NA);
465 offset += 8;
467 raknet_dissect_system_address(
468 sub_tree, hf_raknet_client_address, pinfo, tvb, &offset);
470 proto_tree_add_item(sub_tree, hf_raknet_mtu_size, tvb, offset,
471 2, ENC_BIG_ENDIAN);
472 offset += 2;
474 state = raknet_get_session_state(pinfo);
475 state->use_encryption = tvb_get_uint8(tvb, offset) ? true : false;
477 proto_tree_add_item(sub_tree, hf_raknet_use_encryption, tvb, offset,
478 1, ENC_NA);
479 offset += 1;
481 if (state->use_encryption) {
482 proto_tree_add_item(sub_tree, hf_raknet_server_answer, tvb, offset,
483 128, ENC_NA);
484 offset += 128;
487 return offset;
490 static int
491 raknet_dissect_incompatible_protocol_version(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
492 void *data _U_)
494 proto_tree *sub_tree;
495 int offset;
497 sub_tree = init_raknet_offline_message(tvb, pinfo, tree, &offset);
499 proto_tree_add_item(sub_tree, hf_raknet_raknet_proto_ver, tvb,
500 offset, 1, ENC_BIG_ENDIAN);
501 offset += 1;
503 proto_tree_add_item(sub_tree, hf_raknet_offline_message_data_id, tvb, offset,
504 16, ENC_NA);
505 offset += 16;
507 proto_tree_add_item(sub_tree, hf_raknet_server_guid, tvb, offset,
508 8, ENC_NA);
509 offset += 8;
511 return offset;
514 static int
515 raknet_dissect_connection_failed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
516 void *data _U_)
518 proto_tree *sub_tree;
519 int offset;
521 sub_tree = init_raknet_offline_message(tvb, pinfo, tree, &offset);
523 proto_tree_add_item(sub_tree, hf_raknet_offline_message_data_id, tvb, offset,
524 16, ENC_NA);
525 offset += 16;
527 proto_tree_add_item(sub_tree, hf_raknet_server_guid, tvb, offset,
528 8, ENC_NA);
529 offset += 8;
531 return offset;
534 static int
535 raknet_dissect_unconnected_pong(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
536 void *data _U_)
538 proto_tree *sub_tree;
539 uint32_t str_size;
540 int offset;
542 sub_tree = init_raknet_offline_message(tvb, pinfo, tree, &offset);
544 proto_tree_add_item(sub_tree, hf_raknet_timestamp, tvb,
545 offset, 8, ENC_BIG_ENDIAN);
546 offset += 8;
548 proto_tree_add_item(sub_tree, hf_raknet_server_guid, tvb, offset,
549 8, ENC_NA);
550 offset += 8;
552 proto_tree_add_item(sub_tree, hf_raknet_offline_message_data_id, tvb, offset,
553 16, ENC_NA);
554 offset += 16;
556 /* raknet precedes strings with a short (2 bytes) holding string length. */
557 proto_tree_add_item_ret_uint(sub_tree, hf_raknet_0x1C_server_id_str_len, tvb,
558 offset, 2, ENC_BIG_ENDIAN, &str_size);
559 offset += 2;
561 proto_tree_add_item(sub_tree, hf_raknet_0x1C_server_id_str, tvb, offset,
562 str_size, ENC_NA|ENC_ASCII);
563 offset += str_size;
565 return offset;
568 static int
569 raknet_dissect_connected_ping(tvbuff_t *tvb, packet_info *pinfo _U_,
570 proto_tree *tree, void* data _U_)
573 int offset = 1;
575 proto_tree_add_item(tree, hf_raknet_timestamp, tvb,
576 offset, 8, ENC_BIG_ENDIAN);
577 offset += 8;
579 return offset;
582 static int
583 raknet_dissect_connected_pong(tvbuff_t *tvb, packet_info *pinfo _U_,
584 proto_tree *tree, void* data _U_)
586 int offset = 1;
588 proto_tree_add_item(tree, hf_raknet_timestamp, tvb,
589 offset, 8, ENC_BIG_ENDIAN);
590 offset += 8;
592 proto_tree_add_item(tree, hf_raknet_timestamp, tvb,
593 offset, 8, ENC_BIG_ENDIAN);
594 offset += 8;
596 return offset;
599 static int
600 raknet_dissect_connection_request(tvbuff_t *tvb, packet_info *pinfo _U_,
601 proto_tree *tree, void* data _U_)
603 int offset = 1;
604 bool use_encryption;
606 proto_tree_add_item(tree, hf_raknet_client_guid, tvb, offset,
607 8, ENC_NA);
608 offset += 8;
610 proto_tree_add_item(tree, hf_raknet_timestamp, tvb,
611 offset, 8, ENC_BIG_ENDIAN);
612 offset += 8;
614 use_encryption = tvb_get_uint8(tvb, offset) ? true : false;
616 proto_tree_add_item(tree, hf_raknet_use_encryption, tvb, offset,
617 1, ENC_NA);
618 offset += 1;
620 if (use_encryption) {
621 bool use_client_key;
623 proto_tree_add_item(tree, hf_raknet_client_proof, tvb, offset,
624 32, ENC_NA);
625 offset += 32;
627 use_client_key = tvb_get_uint8(tvb, offset) ? true : false;
629 proto_tree_add_item(tree, hf_raknet_use_client_key, tvb, offset,
630 1, ENC_NA);
631 offset += 1;
633 if (use_client_key) {
634 proto_tree_add_item(tree, hf_raknet_client_identity, tvb, offset,
635 160, ENC_NA);
636 offset += 160;
640 proto_tree_add_item(tree, hf_raknet_password, tvb, offset,
641 -1, ENC_NA);
643 return tvb_reported_length(tvb);
646 static int
647 raknet_dissect_connection_request_accepted(tvbuff_t *tvb, packet_info *pinfo _U_,
648 proto_tree *tree, void* data _U_)
650 int offset = 1;
651 int i;
653 raknet_dissect_system_address(
654 tree, hf_raknet_client_address, pinfo, tvb, &offset);
656 proto_tree_add_item(tree, hf_raknet_system_index, tvb, offset,
657 2, ENC_BIG_ENDIAN);
658 offset += 2;
660 for (i = 0; i < RAKNET_NUMBER_OF_INTERNAL_IDS; i++) {
661 raknet_dissect_system_address(
662 tree, hf_raknet_internal_address, pinfo, tvb, &offset);
665 proto_tree_add_item(tree, hf_raknet_timestamp, tvb,
666 offset, 8, ENC_BIG_ENDIAN);
667 offset += 8;
669 proto_tree_add_item(tree, hf_raknet_timestamp, tvb,
670 offset, 8, ENC_BIG_ENDIAN);
671 offset += 8;
673 return offset;
676 static int
677 raknet_dissect_new_incoming_connection(tvbuff_t *tvb, packet_info *pinfo,
678 proto_tree *tree, void* data _U_)
681 int offset = 1;
682 int i;
684 raknet_dissect_system_address(
685 tree, hf_raknet_server_address, pinfo, tvb, &offset);
687 for (i = 0; i < RAKNET_NUMBER_OF_INTERNAL_IDS; i++) {
688 raknet_dissect_system_address(
689 tree, hf_raknet_internal_address, pinfo, tvb, &offset);
692 proto_tree_add_item(tree, hf_raknet_timestamp, tvb,
693 offset, 8, ENC_BIG_ENDIAN);
694 offset += 8;
696 proto_tree_add_item(tree, hf_raknet_timestamp, tvb,
697 offset, 8, ENC_BIG_ENDIAN);
698 offset += 8;
701 return offset;
705 * Protocol definition and handlers.
707 struct raknet_handler_entry {
708 value_string vs;
709 dissector_t dissector_fp;
712 static const struct raknet_handler_entry raknet_offline_message_handlers[] = {
714 * Ref: ..RakNet/Source/MessageIdentifiers.h
715 * Ref: ..RakNet/Source/RakPeer.cpp (ProcessOfflineNetworkPacket)
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 },
747 static const struct raknet_handler_entry raknet_system_message_handlers[] = {
749 * Ref: ..RakNet/Source/MessageIdentifiers.h
750 * Ref: ..RakNet/Source/RakPeer.cpp (RakPeer::RunUpdateCycle)
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 },
765 * Look up table from message ID to name.
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];
770 static void
771 raknet_init_message_names(void)
773 unsigned int i;
775 for (i = 0; i < array_length(raknet_offline_message_handlers); i++) {
776 raknet_offline_message_names[i].value = raknet_offline_message_handlers[i].vs.value;
777 raknet_offline_message_names[i].strptr = raknet_offline_message_handlers[i].vs.strptr;
779 raknet_offline_message_names[array_length(raknet_offline_message_handlers)].value = 0;
780 raknet_offline_message_names[array_length(raknet_offline_message_handlers)].strptr = NULL;
782 for (i = 0; i < array_length(raknet_system_message_handlers); i++) {
783 raknet_system_message_names[i].value = raknet_system_message_handlers[i].vs.value;
784 raknet_system_message_names[i].strptr = raknet_system_message_handlers[i].vs.strptr;
786 raknet_system_message_names[array_length(raknet_system_message_handlers)].value = 0;
787 raknet_system_message_names[array_length(raknet_system_message_handlers)].strptr = NULL;
791 * Fill out the Info column and protocol subtree.
793 * Offset is updated for the caller.
795 static proto_tree *
796 init_raknet_offline_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset)
798 proto_tree *sub_tree;
799 proto_item *ti;
800 uint8_t message_id;
802 *offset = 0;
805 * Take buffer start 0 to end -1 as single raknet item.
807 ti = proto_tree_add_item(tree, proto_raknet, tvb, 0, -1, ENC_NA);
808 sub_tree = proto_item_add_subtree(ti, ett_raknet);
810 message_id = tvb_get_uint8(tvb, *offset);
811 proto_tree_add_item(sub_tree, hf_raknet_offline_message_id, tvb, *offset,
812 1, ENC_BIG_ENDIAN);
813 *offset += 1;
815 col_add_str(pinfo->cinfo, COL_INFO,
816 val_to_str(message_id, raknet_offline_message_names, "Unknown offline message: %#x"));
819 * Append description to the raknet item.
821 proto_item_append_text(ti, ", Offline message ID %#x", message_id);
823 return sub_tree;
826 static int
827 raknet_dissect_ACK(tvbuff_t *tvb, packet_info *pinfo,
828 proto_tree *tree, void* data)
830 int offset = 0;
831 proto_tree *sub_tree;
832 uint32_t count;
833 uint32_t i;
835 if (*(bool*)data) {
836 col_set_str(pinfo->cinfo, COL_INFO, "ACK");
838 else {
839 col_set_str(pinfo->cinfo, COL_INFO, "NAK");
842 proto_tree_add_item_ret_uint(tree, hf_raknet_NACK_record_count, tvb,
843 offset, 2, ENC_BIG_ENDIAN, &count);
844 offset += 2;
846 for (i = 0; i < count; i++) {
847 proto_item *ti;
848 uint32_t max;
849 uint32_t min;
851 if (i == 0) {
852 col_append_str(pinfo->cinfo, COL_INFO, " ");
854 else {
855 col_append_str(pinfo->cinfo, COL_INFO, ", ");
858 if (tvb_get_uint8(tvb, offset)) { /* maxEqualToMin */
859 min = tvb_get_uint24(tvb, offset + 1, ENC_LITTLE_ENDIAN);
861 col_append_fstr(pinfo->cinfo, COL_INFO, "#%" PRIu32, min);
863 ti = proto_tree_add_string_format_value(tree, hf_raknet_packet_number_range, tvb,
864 offset, 1 + 3, "",
865 "%" PRIu32 " .. %" PRIu32,
866 min, min);
867 sub_tree = proto_item_add_subtree(ti, ett_raknet_packet_number_range);
869 proto_tree_add_item(sub_tree, hf_raknet_range_max_equal_to_min, tvb,
870 offset, 1, ENC_NA);
871 offset += 1;
873 proto_tree_add_item(sub_tree, hf_raknet_packet_number_min, tvb,
874 offset, 3, ENC_LITTLE_ENDIAN);
875 offset += 3;
877 else {
878 min = tvb_get_uint24(tvb, offset + 1 , ENC_LITTLE_ENDIAN);
879 max = tvb_get_uint24(tvb, offset + 1 + 3, ENC_LITTLE_ENDIAN);
881 col_append_fstr(pinfo->cinfo, COL_INFO,
882 "#%" PRIu32 "..%" PRIu32,
883 min, max);
885 ti = proto_tree_add_string_format_value(tree, hf_raknet_packet_number_range, tvb,
886 offset, 1 + 3 + 3, "",
887 "%" PRIu32 " .. %" PRIu32, min, max);
888 sub_tree = proto_item_add_subtree(ti, ett_raknet_packet_number_range);
890 proto_tree_add_item(sub_tree, hf_raknet_range_max_equal_to_min, tvb,
891 offset, 1, ENC_NA);
892 offset += 1;
894 proto_tree_add_item(sub_tree, hf_raknet_packet_number_min, tvb,
895 offset, 3, ENC_LITTLE_ENDIAN);
896 offset += 3;
898 proto_tree_add_item(sub_tree, hf_raknet_packet_number_max, tvb,
899 offset, 3, ENC_LITTLE_ENDIAN);
900 offset += 3;
904 return tvb_captured_length(tvb);
907 static int
908 raknet_dissect_common_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *raknet_tree, void *data)
910 int offset = 0;
911 bool *has_multiple_messages;
912 proto_item *ti;
913 proto_item *raknet_ti;
914 proto_item *msg_ti;
915 proto_tree *msg_tree;
916 uint64_t msg_flags;
917 uint32_t payload_bits;
918 uint32_t payload_octets;
919 raknet_reliability_t reliability;
920 bool has_split_packet;
921 uint8_t message_id;
922 int message_size;
923 proto_tree *payload_tree;
924 tvbuff_t* next_tvb;
925 bool next_tvb_is_subset;
926 dissector_handle_t next_dissector;
927 int dissected;
928 heur_dtbl_entry_t *hdtbl_entry;
929 static int * const flag_flds[] = {
930 &hf_raknet_message_reliability,
931 &hf_raknet_message_has_split_packet,
932 NULL
935 has_multiple_messages = (bool*)data;
936 raknet_ti = proto_tree_get_parent(raknet_tree);
938 msg_ti = proto_tree_add_item(raknet_tree, hf_raknet_message, tvb, offset, -1, ENC_NA);
939 msg_tree = proto_item_add_subtree(msg_ti, ett_raknet_message);
940 proto_item_append_text(msg_ti, ", ");
942 proto_tree_add_bitmask_ret_uint64(msg_tree, tvb, offset, hf_raknet_message_flags,
943 ett_raknet_message_flags, flag_flds, ENC_NA, &msg_flags);
944 offset += 1;
946 ti = proto_tree_add_item_ret_uint(msg_tree, hf_raknet_payload_length, tvb,
947 offset, 2, ENC_BIG_ENDIAN, &payload_bits);
948 offset += 2;
949 payload_octets = payload_bits / 8 + (payload_bits % 8 > 0); /* ceil(bits / 8) */
950 proto_item_append_text(ti, " bits (%" PRIu32 " octets)", payload_octets);
952 reliability = (raknet_reliability_t)((msg_flags >> 5) & 0x07);
953 has_split_packet = (msg_flags >> 4) & 0x01 ? true : false;
955 if (reliability == RAKNET_RELIABLE ||
956 reliability == RAKNET_RELIABLE_SEQUENCED ||
957 reliability == RAKNET_RELIABLE_ORDERED ) {
959 proto_tree_add_item(msg_tree, hf_raknet_reliable_message_number, tvb,
960 offset, 3, ENC_LITTLE_ENDIAN);
961 offset += 3;
964 if (reliability == RAKNET_UNRELIABLE_SEQUENCED ||
965 reliability == RAKNET_RELIABLE_SEQUENCED) {
967 proto_tree_add_item(msg_tree, hf_raknet_message_sequencing_index, tvb,
968 offset, 3, ENC_LITTLE_ENDIAN);
969 offset += 3;
972 if (reliability == RAKNET_UNRELIABLE_SEQUENCED ||
973 reliability == RAKNET_RELIABLE_SEQUENCED ||
974 reliability == RAKNET_RELIABLE_ORDERED) {
976 proto_tree_add_item(msg_tree, hf_raknet_message_ordering_index, tvb,
977 offset, 3, ENC_LITTLE_ENDIAN);
978 offset += 3;
980 proto_tree_add_item(msg_tree, hf_raknet_message_ordering_channel, tvb,
981 offset, 1, ENC_NA);
982 offset += 1;
985 if (has_split_packet) {
986 bool save_fragmented;
987 uint32_t split_packet_count;
988 uint32_t split_packet_id;
989 uint32_t split_packet_index;
990 fragment_head *frag_msg;
993 proto_tree_add_item_ret_uint(msg_tree, hf_raknet_split_packet_count, tvb,
994 offset, 4, ENC_BIG_ENDIAN, &split_packet_count);
995 offset += 4;
997 proto_tree_add_item_ret_uint(msg_tree, hf_raknet_split_packet_id, tvb,
998 offset, 2, ENC_BIG_ENDIAN, &split_packet_id);
999 offset += 2;
1001 proto_tree_add_item_ret_uint(msg_tree, hf_raknet_split_packet_index, tvb,
1002 offset, 4, ENC_BIG_ENDIAN, &split_packet_index);
1003 offset += 4;
1006 * Reassemble the fragmented packet.
1008 save_fragmented = pinfo->fragmented;
1009 pinfo->fragmented = true;
1011 frag_msg =
1012 fragment_add_seq_check(&raknet_reassembly_table,
1013 tvb, offset, pinfo,
1014 split_packet_id,
1015 NULL,
1016 split_packet_index,
1017 payload_octets,
1018 split_packet_index != split_packet_count - 1);
1020 next_tvb =
1021 process_reassembled_data(tvb, offset, pinfo, "Reassembled packet",
1022 frag_msg, &raknet_frag_items, NULL, msg_tree);
1024 pinfo->fragmented = save_fragmented;
1026 if (next_tvb) {
1028 * Reassembly done. Dissect the message as normal.
1030 wmem_strbuf_t *strbuf;
1032 strbuf = wmem_strbuf_new(pinfo->pool, "");
1033 wmem_strbuf_append_printf(strbuf,
1034 "{Message fragment %" PRIu32 "/%" PRIu32 "; Reassembled} ",
1035 split_packet_index + 1, split_packet_count);
1037 proto_item_append_text(msg_ti, "%s", wmem_strbuf_get_str(strbuf));
1038 col_add_str(pinfo->cinfo, COL_INFO, wmem_strbuf_get_str(strbuf));
1039 col_set_fence(pinfo->cinfo, COL_INFO);
1041 next_tvb_is_subset = false;
1043 else {
1044 wmem_strbuf_t *strbuf;
1046 strbuf = wmem_strbuf_new(pinfo->pool, "");
1047 wmem_strbuf_append_printf(strbuf,
1048 "{Message fragment %" PRIu32 "/%" PRIu32 "}",
1049 split_packet_index + 1, split_packet_count);
1051 proto_item_append_text(msg_ti, "%s", wmem_strbuf_get_str(strbuf));
1052 col_add_str(pinfo->cinfo, COL_INFO, wmem_strbuf_get_str(strbuf));
1054 ti = proto_tree_add_item(msg_tree, hf_raknet_split_packet, tvb, offset,
1055 payload_octets, ENC_NA);
1056 proto_item_append_text(ti, " (%u octets)", payload_octets);
1059 else {
1060 next_tvb = tvb_new_subset_length(tvb, offset, payload_octets);
1061 next_tvb_is_subset = true;
1065 * At this point we can finally check if the packet has multiple
1066 * messages.
1068 if (! *has_multiple_messages) {
1069 *has_multiple_messages =
1070 tvb_reported_length_remaining(tvb, offset) > (int)payload_octets
1071 ? true : false;
1075 * And we finally have the actual size of message.
1077 message_size = offset + payload_octets;
1079 if (!next_tvb) {
1081 * It was an incomplete message fragment.
1083 proto_item_set_len(msg_ti, message_size);
1084 if (raknet_ti) {
1085 proto_item_set_len(raknet_ti, proto_item_get_len(raknet_ti) + message_size);
1087 return message_size;
1090 message_id = tvb_get_uint8(next_tvb, 0);
1093 * Now we want to dissect this message. First we search for a
1094 * dissector from our system message dissector table.
1096 next_dissector =
1097 dissector_get_uint_handle(raknet_system_message_dissectors, message_id);
1099 if (next_dissector) {
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.
1105 ti = proto_tree_add_item(msg_tree, hf_raknet_system_message, next_tvb, 0, -1, ENC_NA);
1106 payload_tree = proto_item_add_subtree(ti, ett_raknet_system_message);
1108 proto_item_append_text(ti, " (%s)",
1109 val_to_str(message_id, raknet_system_message_names, "Unknown ID: %#x"));
1111 proto_item_append_text(msg_ti, "ID %#x (%s)", message_id,
1112 val_to_str_const(message_id, raknet_system_message_names, "Unknown"));
1114 col_add_str(pinfo->cinfo, COL_INFO,
1115 val_to_str(message_id, raknet_system_message_names, "Unknown system message ID: %#x"));
1117 proto_tree_add_item(payload_tree, hf_raknet_system_message_id,
1118 next_tvb, 0, 1, ENC_NA);
1120 dissected =
1121 call_dissector_only(next_dissector, next_tvb, pinfo, payload_tree, data);
1123 proto_item_set_len(msg_ti, message_size);
1124 if (raknet_ti) {
1125 proto_item_set_len(raknet_ti, proto_item_get_len(raknet_ti) + message_size);
1128 if (dissected >= 0) {
1129 return message_size;
1131 else {
1132 return dissected;
1137 * It seems not to be a system message so use a dissector set for
1138 * this conversation if any.
1140 next_dissector =
1141 raknet_get_session_state(pinfo)->subdissector;
1144 * And of course we don't know the name of message.
1146 proto_item_append_text(msg_ti, "ID %#x", message_id);
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.
1153 if (*has_multiple_messages) {
1154 payload_tree = msg_tree;
1156 else {
1157 payload_tree = proto_tree_get_root(raknet_tree);
1160 if (next_dissector) {
1161 dissected =
1162 call_dissector_only(next_dissector, next_tvb, pinfo, payload_tree, data);
1164 if (dissected > 0) {
1165 goto FIX_UP_AND_RETURN;
1167 else {
1168 expert_add_info(pinfo, msg_tree, &ei_raknet_subdissector_failed);
1173 * No dissectors set for this conversation. Look up a dissector
1174 * from the port table.
1176 next_dissector =
1177 dissector_get_uint_handle(raknet_port_dissectors, pinfo->match_uint);
1179 if (next_dissector) {
1180 dissected =
1181 call_dissector_only(next_dissector, next_tvb, pinfo, payload_tree, data);
1183 if (dissected > 0) {
1184 goto FIX_UP_AND_RETURN;
1186 else {
1187 expert_add_info(pinfo, msg_tree, &ei_raknet_subdissector_failed);
1192 * We don't have a subdissector or we have one but id didn't
1193 * dissect the message. Try heuristic subdissectors.
1195 dissected =
1196 dissector_try_heuristic(raknet_heur_subdissectors, next_tvb, pinfo, payload_tree,
1197 &hdtbl_entry, data);
1198 if (!dissected) {
1199 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown message ID: %#x", message_id);
1201 ti = proto_tree_add_expert(msg_tree, pinfo, &ei_raknet_unknown_message_id, next_tvb,
1202 0, 1);
1203 proto_item_append_text(ti, " %#x", message_id);
1206 FIX_UP_AND_RETURN:
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.
1213 if (!*has_multiple_messages && next_tvb_is_subset) {
1214 proto_item_set_len(msg_ti, message_size - payload_octets);
1215 if (raknet_ti) {
1216 proto_item_set_len(raknet_ti, proto_item_get_len(raknet_ti) + message_size - payload_octets);
1219 else {
1220 proto_item_set_len(msg_ti, message_size);
1221 if (raknet_ti) {
1222 proto_item_set_len(raknet_ti, proto_item_get_len(raknet_ti) + message_size);
1225 return message_size;
1228 static int
1229 raknet_dissect_connected_message(tvbuff_t *tvb, packet_info *pinfo,
1230 proto_tree *root_tree, void* data _U_)
1232 raknet_session_state_t* state;
1233 proto_item *ti;
1234 proto_tree *raknet_tree;
1235 int item_size;
1236 int offset = 0;
1237 uint8_t msg_type;
1239 state = raknet_get_session_state(pinfo);
1240 if (state->use_encryption) {
1242 * RakNet uses ChaCha stream cipher to encrypt messages, which
1243 * is currently not supported by this dissector.
1245 col_set_str(pinfo->cinfo, COL_INFO, "Encrypted message");
1247 item_size = tvb_reported_length_remaining(tvb, offset);
1248 ti = proto_tree_add_expert(root_tree, pinfo, &ei_raknet_encrypted_message, tvb,
1249 offset, item_size);
1250 proto_item_append_text(ti, " (%d octets)", item_size);
1251 return tvb_captured_length(tvb);
1254 msg_type = tvb_get_uint8(tvb, offset);
1256 if (!(msg_type & (1 << 7))) { /* !isValid */
1258 * No suitable dissector was registered for this offline
1259 * message.
1261 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown offline message ID: %#x", msg_type);
1262 ti = proto_tree_add_expert(root_tree, pinfo, &ei_raknet_unknown_message_id, tvb,
1263 0, 1);
1264 proto_item_append_text(ti, " %#x", msg_type);
1265 return tvb_captured_length(tvb);
1267 else if (msg_type & (1 << 6)) { /* isACK */
1268 static int * const ack_flds[] = {
1269 &hf_raknet_packet_is_for_connected,
1270 &hf_raknet_packet_is_ACK,
1271 &hf_raknet_packet_has_B_and_AS,
1272 NULL
1275 ti = proto_tree_add_item(root_tree, proto_raknet, tvb, 0, -1, ENC_NA);
1276 proto_item_append_text(ti, ", ACK");
1277 raknet_tree = proto_item_add_subtree(ti, ett_raknet);
1279 proto_tree_add_bitmask(raknet_tree, tvb, offset, hf_raknet_packet_type,
1280 ett_raknet_packet_type, ack_flds, ENC_NA);
1281 offset += 1;
1283 if (msg_type & (1 << 5)) { /* hasBAndAS */
1284 proto_tree_add_item(raknet_tree, hf_raknet_AS, tvb, offset,
1285 4, ENC_BIG_ENDIAN);
1286 offset += 4;
1289 if (raknet_tree) {
1290 bool is_ACK = true;
1291 return raknet_dissect_ACK(tvb_new_subset_remaining(tvb, offset),
1292 pinfo, raknet_tree, &is_ACK);
1294 else {
1295 return tvb_captured_length(tvb);
1298 else if (msg_type & (1 << 5)) { /* isNAK */
1299 static int * const nak_flds[] = {
1300 &hf_raknet_packet_is_for_connected,
1301 &hf_raknet_packet_is_ACK,
1302 &hf_raknet_packet_is_NAK,
1303 NULL
1306 ti = proto_tree_add_item(root_tree, proto_raknet, tvb, 0, -1, ENC_NA);
1307 proto_item_append_text(ti, ", NAK");
1308 raknet_tree = proto_item_add_subtree(ti, ett_raknet);
1310 proto_tree_add_bitmask(raknet_tree, tvb, offset, hf_raknet_packet_type,
1311 ett_raknet_packet_type, nak_flds, ENC_NA);
1312 offset += 1;
1314 if (raknet_tree) {
1315 bool is_ACK = false;
1316 return raknet_dissect_ACK(tvb_new_subset_remaining(tvb, offset),
1317 pinfo, raknet_tree, &is_ACK);
1319 else {
1320 return tvb_captured_length(tvb);
1323 else {
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.
1329 uint32_t packet_number;
1330 bool has_multiple_messages = false;
1331 static int * const common_flds[] = {
1332 &hf_raknet_packet_is_for_connected,
1333 &hf_raknet_packet_is_ACK,
1334 &hf_raknet_packet_is_NAK,
1335 &hf_raknet_packet_is_pair,
1336 &hf_raknet_packet_is_continuous_send,
1337 &hf_raknet_packet_needs_B_and_AS,
1338 NULL
1341 ti = proto_tree_add_item(root_tree, proto_raknet, tvb, 0, 0, ENC_NA);
1342 raknet_tree = proto_item_add_subtree(ti, ett_raknet);
1344 proto_tree_add_bitmask(raknet_tree, tvb, offset, hf_raknet_packet_type,
1345 ett_raknet_packet_type, common_flds, ENC_NA);
1346 offset += 1;
1348 proto_tree_add_item_ret_uint(raknet_tree, hf_raknet_packet_number, tvb,
1349 offset, 3, ENC_LITTLE_ENDIAN, &packet_number);
1350 offset += 3;
1352 proto_item_append_text(ti, ", Message #%" PRIu32, packet_number);
1353 col_add_fstr(pinfo->cinfo, COL_INFO, "#%" PRIu32 ": ", packet_number);
1354 col_set_fence(pinfo->cinfo, COL_INFO);
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.
1361 proto_item_set_len(ti, offset);
1363 while (true) {
1364 int dissected;
1366 dissected = raknet_dissect_common_message(tvb_new_subset_remaining(tvb, offset), pinfo,
1367 raknet_tree, &has_multiple_messages);
1368 if (dissected >= 0) {
1369 offset += dissected;
1371 if (tvb_reported_length_remaining(tvb, offset) > 0) {
1373 * More messages are in the packet.
1375 col_append_str(pinfo->cinfo, COL_INFO, ", ");
1376 col_set_fence(pinfo->cinfo, COL_INFO);
1377 continue;
1379 else {
1381 * It's the end of packet.
1383 break;
1386 else {
1387 return dissected;
1391 return tvb_captured_length(tvb);
1396 * Decode the tvb buffer.
1398 * RakNet is just a dissector. It is invoked by protocols whose applications
1399 * are built using the RakNet libs.
1401 static int
1402 dissect_raknet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1404 uint8_t message_id;
1405 int dissected;
1407 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RakNet");
1408 col_clear(pinfo->cinfo, COL_INFO);
1410 message_id = tvb_get_uint8(tvb, 0);
1412 dissected = dissector_try_uint_with_data(raknet_offline_message_dissectors, message_id, tvb,
1413 pinfo, tree, true, data);
1414 if (!dissected) {
1415 raknet_dissect_connected_message(tvb, pinfo, tree, data);
1418 return tvb_captured_length(tvb);
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.
1426 static bool
1427 test_raknet_heur(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree _U_, void* data _U_)
1429 if (tvb_memeql(tvb, 1 + 8, RAKNET_OFFLINE_MESSAGE_DATA_ID, sizeof(RAKNET_OFFLINE_MESSAGE_DATA_ID)) == 0) {
1430 /* ID_UNCONNECTED_PING */
1431 return true;
1433 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 return true;
1437 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 return true;
1441 else {
1442 return false;
1446 static bool
1447 dissect_raknet_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1449 if (test_raknet_heur(tvb, pinfo, tree, data)) {
1450 conversation_t* conversation;
1452 conversation = find_or_create_conversation(pinfo);
1453 conversation_set_dissector(conversation, raknet_handle);
1455 return call_dissector_only(raknet_handle, tvb, pinfo, tree, data) > 0;
1457 else {
1458 return false;
1462 void
1463 proto_register_raknet(void)
1465 static hf_register_info hf[] = {
1467 * Offline Message ID field.
1469 { &hf_raknet_offline_message_id,
1470 { "RakNet Offline Message ID", "raknet.offline.message.id",
1471 FT_UINT8, BASE_HEX,
1472 VALS(raknet_offline_message_names), 0x0,
1473 NULL, HFILL }
1476 * General fields (fields in >1 packet).
1478 { &hf_raknet_client_guid,
1479 { "RakNet Client GUID", "raknet.client.guid",
1480 FT_BYTES, BASE_NONE,
1481 NULL, 0x0,
1482 NULL, HFILL }
1484 { &hf_raknet_timestamp,
1485 { "RakNet Time since start (ms)", "raknet.timestamp",
1486 FT_UINT64, BASE_DEC,
1487 NULL, 0x0,
1488 NULL, HFILL }
1490 { &hf_raknet_offline_message_data_id,
1491 { "RakNet Offline message data ID", "raknet.offline_message.data_id",
1492 FT_BYTES, BASE_NONE,
1493 NULL, 0x0,
1494 NULL, HFILL }
1496 { &hf_raknet_mtu_size,
1497 { "RakNet MTU size", "raknet.MTU",
1498 FT_UINT16, BASE_DEC,
1499 NULL, 0x0,
1500 NULL, HFILL }
1502 { &hf_raknet_raknet_proto_ver,
1503 { "RakNet RakNet protocol version", "raknet.proto_ver",
1504 FT_UINT8, BASE_DEC,
1505 NULL, 0x0,
1506 NULL, HFILL }
1508 { &hf_raknet_server_guid,
1509 { "RakNet Server GUID", "raknet.server_id",
1510 FT_BYTES, BASE_NONE,
1511 NULL, 0x0,
1512 NULL, HFILL }
1514 { &hf_raknet_ip_version,
1515 { "RakNet IP Version", "raknet.ip.version",
1516 FT_UINT8, BASE_DEC,
1517 NULL, 0x0,
1518 NULL, HFILL }
1520 { &hf_raknet_ipv4_address,
1521 { "RakNet IPv4 Address", "raknet.ip.v4_address",
1522 FT_IPv4, BASE_NONE,
1523 NULL, 0x0,
1524 NULL, HFILL }
1526 { &hf_raknet_ipv6_address,
1527 { "RakNet IPv6 Address", "raknet.ip.v6_address",
1528 FT_IPv6, BASE_NONE,
1529 NULL, 0x0,
1530 NULL, HFILL }
1532 { &hf_raknet_port,
1533 { "RakNet Port", "raknet.port",
1534 FT_UINT16, BASE_DEC,
1535 NULL, 0x0,
1536 NULL, HFILL }
1539 * Packet ID 0x05
1541 { &hf_raknet_null_padding,
1542 { "RakNet Null padding", "raknet.null_padding",
1543 FT_NONE, BASE_NONE,
1544 NULL, 0x0,
1545 NULL, HFILL }
1548 * Packet ID 0x06
1550 { &hf_raknet_use_encryption,
1551 { "RakNet Use encryption", "raknet.use_encryption",
1552 FT_BOOLEAN, BASE_NONE,
1553 NULL, 0x0,
1554 NULL, HFILL }
1556 { &hf_raknet_server_public_key,
1557 { "RakNet Server public key", "raknet.server.public_key",
1558 FT_BYTES, BASE_NONE,
1559 NULL, 0x0,
1560 NULL, HFILL }
1563 * Packet ID 0x07
1565 { &hf_raknet_cookie,
1566 { "RakNet cookie", "raknet.cookie",
1567 FT_UINT32, BASE_HEX,
1568 NULL, 0x0,
1569 NULL, HFILL }
1571 { &hf_raknet_client_wrote_challenge,
1572 { "RakNet Client wrote challenge", "raknet.client.wrote_challenge",
1573 FT_BOOLEAN, BASE_NONE,
1574 NULL, 0x0,
1575 NULL, HFILL }
1577 { &hf_raknet_client_challenge,
1578 { "RakNet Client challenge", "raknet.client.challenge",
1579 FT_BYTES, BASE_NONE,
1580 NULL, 0x0,
1581 NULL, HFILL }
1583 { &hf_raknet_client_address,
1584 { "RakNet Client address", "raknet.client.address",
1585 FT_STRING, BASE_NONE,
1586 NULL, 0x0,
1587 NULL, HFILL }
1589 { &hf_raknet_server_address,
1590 { "RakNet Server address", "raknet.server.address",
1591 FT_STRING, BASE_NONE,
1592 NULL, 0x0,
1593 NULL, HFILL }
1595 { &hf_raknet_server_answer,
1596 { "RakNet Server answer", "raknet.server.answer",
1597 FT_BYTES, BASE_NONE,
1598 NULL, 0x0,
1599 NULL, HFILL }
1602 * Packet ID 0x1C
1604 { &hf_raknet_0x1C_server_id_str_len,
1605 { "RakNet Server ID string len", "raknet.server_id_str_len",
1606 FT_UINT16, BASE_DEC,
1607 NULL, 0x0,
1608 NULL, HFILL }
1610 { &hf_raknet_0x1C_server_id_str,
1611 { "RakNet Server ID string", "raknet.server_id_str",
1612 FT_STRING, BASE_NONE,
1613 NULL, 0x0,
1614 NULL, HFILL }
1616 { &hf_raknet_packet_type,
1617 { "RakNet Packet type", "raknet.packet.type",
1618 FT_UINT8, BASE_HEX,
1619 NULL, 0x0,
1620 NULL, HFILL }
1622 { &hf_raknet_packet_is_for_connected,
1623 { "is for connected peer", "raknet.packet.is_for_connected",
1624 FT_BOOLEAN, 8,
1625 NULL, 0x80,
1626 NULL, HFILL }
1628 { &hf_raknet_packet_is_ACK,
1629 { "is ACK", "raknet.packet.is_ACK",
1630 FT_BOOLEAN, 8,
1631 NULL, 0x40,
1632 NULL, HFILL }
1634 { &hf_raknet_packet_has_B_and_AS,
1635 { "has B and AS", "raknet.packet.has_B_and_AS",
1636 FT_BOOLEAN, 8,
1637 NULL, 0x20,
1638 NULL, HFILL }
1640 { &hf_raknet_packet_is_NAK,
1641 { "is NAK", "raknet.packet.is_NAK",
1642 FT_BOOLEAN, 8,
1643 NULL, 0x20,
1644 NULL, HFILL }
1646 { &hf_raknet_packet_is_pair,
1647 { "is pair", "raknet.packet.is_pair",
1648 FT_BOOLEAN, 8,
1649 NULL, 0x10,
1650 NULL, HFILL }
1652 { &hf_raknet_packet_is_continuous_send,
1653 { "is continuous send", "raknet.packet.is_continuous_send",
1654 FT_BOOLEAN, 8,
1655 NULL, 0x8,
1656 NULL, HFILL }
1658 { &hf_raknet_packet_needs_B_and_AS,
1659 { "needs B and AS", "raknet.packet.needs_B_and_AS",
1660 FT_BOOLEAN, 8,
1661 NULL, 0x4,
1662 NULL, HFILL }
1664 { &hf_raknet_AS,
1665 { "RakNet Data arrival rate", "raknet.AS",
1666 FT_FLOAT, BASE_NONE,
1667 NULL, 0x0,
1668 NULL, HFILL }
1670 { &hf_raknet_NACK_record_count,
1671 { "RakNet ACK/NAK record count", "raknet.NACK.record_count",
1672 FT_UINT16, BASE_DEC,
1673 NULL, 0x0,
1674 NULL, HFILL }
1676 { &hf_raknet_packet_number_range,
1677 { "RakNet Packet sequence number range", "raknet.range.packet_number",
1678 FT_STRING, BASE_NONE,
1679 NULL, 0x0,
1680 NULL, HFILL }
1682 { &hf_raknet_range_max_equal_to_min,
1683 { "RakNet Range max equals to min", "raknet.range.max_equals_to_min",
1684 FT_BOOLEAN, BASE_NONE,
1685 NULL, 0x0,
1686 NULL, HFILL }
1688 { &hf_raknet_packet_number_min,
1689 { "RakNet Packet sequence number min", "raknet.range.packet_number.min",
1690 FT_UINT24, BASE_DEC,
1691 NULL, 0x0,
1692 NULL, HFILL }
1694 { &hf_raknet_packet_number_max,
1695 { "RakNet Packet sequence number max", "raknet.range.packet_number.max",
1696 FT_UINT24, BASE_DEC,
1697 NULL, 0x0,
1698 NULL, HFILL }
1700 { &hf_raknet_packet_number,
1701 { "RakNet Packet sequence number", "raknet.packet_number",
1702 FT_UINT24, BASE_DEC,
1703 NULL, 0x0,
1704 NULL, HFILL }
1706 { &hf_raknet_message,
1707 { "RakNet Message", "raknet.message",
1708 FT_NONE, BASE_NONE,
1709 NULL, 0x0,
1710 NULL, HFILL }
1712 { &hf_raknet_message_flags,
1713 { "RakNet Message flags", "raknet.message.flags",
1714 FT_UINT8, BASE_HEX,
1715 NULL, 0x0,
1716 NULL, HFILL }
1718 { &hf_raknet_message_reliability,
1719 { "reliability", "raknet.message.reliability",
1720 FT_UINT8, BASE_DEC,
1721 VALS(raknet_reliability), 0xE0,
1722 NULL, HFILL }
1724 { &hf_raknet_message_has_split_packet,
1725 { "has split packet", "raknet.message.has_split_packet",
1726 FT_BOOLEAN, 8,
1727 NULL, 0x10,
1728 NULL, HFILL }
1730 { &hf_raknet_payload_length,
1731 { "RakNet Payload length", "raknet.payload.length",
1732 FT_UINT16, BASE_DEC,
1733 NULL, 0x0,
1734 NULL, HFILL }
1736 { &hf_raknet_reliable_message_number,
1737 { "RakNet Reliable message number", "raknet.reliable.number",
1738 FT_UINT24, BASE_DEC,
1739 NULL, 0x0,
1740 NULL, HFILL }
1742 { &hf_raknet_message_sequencing_index,
1743 { "RakNet Message sequencing index", "raknet.sequencing.index",
1744 FT_UINT24, BASE_DEC,
1745 NULL, 0x0,
1746 NULL, HFILL }
1748 { &hf_raknet_message_ordering_index,
1749 { "RakNet Message ordering index", "raknet.ordering.index",
1750 FT_UINT24, BASE_DEC,
1751 NULL, 0x0,
1752 NULL, HFILL }
1754 { &hf_raknet_message_ordering_channel,
1755 { "RakNet Message ordering channel", "raknet.ordering.channel",
1756 FT_UINT8, BASE_DEC,
1757 NULL, 0x0,
1758 NULL, HFILL }
1760 { &hf_raknet_split_packet_count,
1761 { "RakNet Split packet count", "raknet.split.count",
1762 FT_UINT32, BASE_DEC,
1763 NULL, 0x0,
1764 NULL, HFILL }
1766 { &hf_raknet_split_packet_id,
1767 { "RakNet Split packet ID", "raknet.split.id",
1768 FT_UINT16, BASE_DEC,
1769 NULL, 0x0,
1770 NULL, HFILL }
1772 { &hf_raknet_split_packet_index,
1773 { "RakNet Split packet index", "raknet.split.index",
1774 FT_UINT32, BASE_DEC,
1775 NULL, 0x0,
1776 NULL, HFILL }
1778 { &hf_raknet_split_packet,
1779 { "RakNet Split packet", "raknet.split.packet",
1780 FT_NONE, BASE_NONE,
1781 NULL, 0x0,
1782 NULL, HFILL }
1784 { &hf_raknet_system_message,
1785 { "RakNet System message", "raknet.system.message",
1786 FT_NONE, BASE_NONE,
1787 NULL, 0x0,
1788 NULL, HFILL }
1790 { &hf_raknet_system_message_id,
1791 { "RakNet System Message ID", "raknet.system.message.id",
1792 FT_UINT8, BASE_HEX,
1793 VALS(raknet_system_message_names), 0x0,
1794 NULL, HFILL }
1796 { &hf_raknet_client_proof,
1797 { "RakNet Client proof of key", "raknet.client.proof",
1798 FT_BYTES, BASE_NONE,
1799 NULL, 0x0,
1800 NULL, HFILL }
1802 { &hf_raknet_use_client_key,
1803 { "RakNet Use client key", "raknet.use_client_key",
1804 FT_BOOLEAN, BASE_NONE,
1805 NULL, 0x0,
1806 NULL, HFILL }
1808 { &hf_raknet_client_identity,
1809 { "RakNet Client identity", "raknet.client.identity",
1810 FT_BYTES, BASE_NONE,
1811 NULL, 0x0,
1812 NULL, HFILL }
1814 { &hf_raknet_password,
1815 { "RakNet Password", "raknet.password",
1816 FT_BYTES, BASE_NONE,
1817 NULL, 0x0,
1818 NULL, HFILL }
1820 { &hf_raknet_system_index,
1821 { "RakNet System index", "raknet.system.index",
1822 FT_UINT16, BASE_DEC,
1823 NULL, 0x0,
1824 NULL, HFILL }
1826 { &hf_raknet_internal_address,
1827 { "RakNet Internal address", "raknet.internal.address",
1828 FT_STRING, BASE_NONE,
1829 NULL, 0x0,
1830 NULL, HFILL }
1833 * Fragmented packets
1835 { &hf_raknet_fragment,
1836 { "Message fragment", "raknet.fragment",
1837 FT_FRAMENUM, BASE_NONE,
1838 NULL, 0x00,
1839 NULL, HFILL }
1841 { &hf_raknet_fragment_count,
1842 { "Message fragment count", "raknet.fragment.count",
1843 FT_UINT32, BASE_DEC,
1844 NULL, 0x00,
1845 NULL, HFILL }
1847 { &hf_raknet_fragment_error,
1848 { "Message defragmentation error", "raknet.fragment.error",
1849 FT_FRAMENUM, BASE_NONE,
1850 NULL, 0x00,
1851 NULL, HFILL }
1853 { &hf_raknet_fragment_multiple_tails,
1854 { "Message has multiple tail fragments", "raknet.fragment.multiple_tails",
1855 FT_BOOLEAN, BASE_NONE,
1856 NULL, 0x00,
1857 NULL, HFILL }
1859 { &hf_raknet_fragment_overlap,
1860 { "Message fragment overlap", "raknet.fragment.overlap",
1861 FT_BOOLEAN, BASE_NONE,
1862 NULL, 0x00,
1863 NULL, HFILL }
1865 { &hf_raknet_fragment_overlap_conflicts,
1866 { "Message fragment overlapping with conflicting data", "raknet.fragment.overlap.conflicts",
1867 FT_BOOLEAN, BASE_NONE,
1868 NULL, 0x00,
1869 NULL, HFILL }
1871 { &hf_raknet_fragment_too_long_fragment,
1872 { "Message fragment too long", "raknet.fragment.too_long",
1873 FT_BOOLEAN, BASE_NONE,
1874 NULL, 0x00,
1875 NULL, HFILL }
1877 { &hf_raknet_fragments,
1878 { "Message fragments", "raknet.fragments",
1879 FT_NONE, BASE_NONE,
1880 NULL, 0x00,
1881 NULL, HFILL }
1883 { &hf_raknet_reassembled_in,
1884 { "Reassembled message in frame", "raknet.reassembled.in",
1885 FT_FRAMENUM, BASE_NONE,
1886 NULL, 0x00,
1887 NULL, HFILL }
1889 { &hf_raknet_reassembled_length,
1890 { "Reassembled message length", "raknet.reassembled.length",
1891 FT_UINT32, BASE_DEC,
1892 NULL, 0x00,
1893 NULL, HFILL }
1898 * Setup protocol subtree array
1900 static int *ett[] = {
1901 &ett_raknet,
1902 &ett_raknet_system_address,
1903 &ett_raknet_packet_type,
1904 &ett_raknet_packet_number_range,
1905 &ett_raknet_message,
1906 &ett_raknet_message_flags,
1907 &ett_raknet_system_message,
1908 &ett_raknet_fragment,
1909 &ett_raknet_fragments,
1913 * Set up expert info.
1915 static ei_register_info ei[] = {
1916 { &ei_raknet_unknown_message_id,
1917 { "raknet.unknown.id", PI_UNDECODED, PI_WARN,
1918 "RakNet unknown message ID",
1919 EXPFILL }
1921 { &ei_raknet_encrypted_message,
1922 { "raknet.encrypted", PI_DECRYPTION, PI_NOTE,
1923 "RakNet encrypted message",
1924 EXPFILL }
1926 { &ei_raknet_subdissector_failed,
1927 { "raknet.subdissector.failed", PI_MALFORMED, PI_NOTE,
1928 "RakNet message subdissector failed, trying the next candidate or heuristics",
1929 EXPFILL }
1931 { &ei_raknet_ip_ver_invalid,
1932 { "raknet.ip_version.invalid", PI_PROTOCOL, PI_WARN,
1933 "Invalid IP version",
1934 EXPFILL }
1937 expert_module_t *expert_raknet;
1940 * Init data structs.
1942 raknet_init_message_names();
1945 * Register the protocol with Wireshark.
1947 proto_raknet = proto_register_protocol (
1948 "RakNet game networking protocol", /* name */
1949 "RakNet", /* short name */
1950 "raknet" /* abbrev */
1954 * Register expert support.
1956 expert_raknet = expert_register_protocol(proto_raknet);
1957 expert_register_field_array(expert_raknet, ei, array_length(ei));
1960 * Register detailed dissection arrays.
1962 proto_register_field_array(proto_raknet, hf, array_length(hf));
1963 proto_register_subtree_array(ett, array_length(ett));
1966 * Register reassembly table.
1968 reassembly_table_register(&raknet_reassembly_table,
1969 &addresses_ports_reassembly_table_functions);
1972 * For internal use only
1974 raknet_handle =
1975 register_dissector("raknet", dissect_raknet, proto_raknet);
1977 raknet_offline_message_dissectors =
1978 register_dissector_table("raknet.offline.message.id", "RakNet offline messages",
1979 proto_raknet, FT_UINT8, BASE_HEX);
1981 raknet_system_message_dissectors =
1982 register_dissector_table("raknet.system.message.id", "RakNet system messages",
1983 proto_raknet, FT_UINT8, BASE_HEX);
1986 * External protocols may register their port to this table via
1987 * "raknet_add_udp_dissector()".
1989 raknet_port_dissectors =
1990 register_dissector_table("raknet.port", "Port for protocols on top of RakNet",
1991 proto_raknet, FT_UINT16, BASE_DEC);
1994 * ...and their heuristic dissector to this table.
1996 raknet_heur_subdissectors =
1997 register_heur_dissector_list_with_description("raknet", "RakNet fallback", proto_raknet);
2000 void
2001 proto_reg_handoff_raknet(void)
2003 dissector_handle_t raknet_handle_tmp;
2004 unsigned int i;
2006 for (i = 0; i < array_length(raknet_offline_message_handlers); i++) {
2007 raknet_handle_tmp =
2008 create_dissector_handle(raknet_offline_message_handlers[i].dissector_fp,
2009 proto_raknet);
2010 dissector_add_uint("raknet.offline.message.id", raknet_offline_message_handlers[i].vs.value,
2011 raknet_handle_tmp);
2014 for (i = 0; i < array_length(raknet_system_message_handlers); i++) {
2015 raknet_handle_tmp =
2016 create_dissector_handle(raknet_system_message_handlers[i].dissector_fp,
2017 proto_raknet);
2018 dissector_add_uint("raknet.system.message.id", raknet_system_message_handlers[i].vs.value,
2019 raknet_handle_tmp);
2022 heur_dissector_add("udp", dissect_raknet_heur,
2023 "RakNet over UDP", "raknet_udp", proto_raknet, HEURISTIC_ENABLE);
2027 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2029 * Local variables:
2030 * c-basic-offset: 4
2031 * tab-width: 8
2032 * indent-tabs-mode: nil
2033 * End:
2035 * vi: set shiftwidth=4 tabstop=8 expandtab:
2036 * :indentSize=4:tabSize=8:noTabs=true: