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
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
;
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
;
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
;
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
,
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 */
179 typedef struct raknet_session_state
{
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.
213 raknet_add_udp_dissector(uint32_t port
, const dissector_handle_t handle
) {
215 * Register ourselves as the handler for that port number
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
);
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
);
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
);
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
;
259 raknet_dissect_system_address(proto_tree
*tree
, int hf
,
260 packet_info
*pinfo
, tvbuff_t
*tvb
, int *offset
) {
262 proto_tree
*sub_tree
;
269 /* XXX - does it really make sense to have a string hf that's set to
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
);
276 switch (ip_version
) {
279 * IPv4 addresses are bit-inverted to prevent routers from
280 * changing them. See ..RakNet/Source/BitStream.h
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
);
288 port
= tvb_get_ntohs(tvb
, *offset
);
289 proto_tree_add_item(sub_tree
, hf_raknet_port
, tvb
, *offset
, 2, ENC_BIG_ENDIAN
);
291 proto_item_set_len(ti
, 1 + 4 + 2);
292 proto_item_append_text(ti
, "%s:%" PRIu16
, addr_str
, port
);
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
);
298 port
= tvb_get_ntohs(tvb
, *offset
);
299 proto_tree_add_item(sub_tree
, hf_raknet_port
, tvb
, *offset
, 2, ENC_BIG_ENDIAN
);
301 proto_item_set_len(ti
, 1 + 16 + 2);
302 proto_item_append_text(ti
, "[%s]:%" PRIu16
, addr_str
, port
);
305 proto_item_set_len(ti
, 1);
306 expert_add_info(pinfo
, sub_tree
, &ei_raknet_ip_ver_invalid
);
311 raknet_dissect_unconnected_ping(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
314 proto_tree
*sub_tree
;
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
);
323 proto_tree_add_item(sub_tree
, hf_raknet_offline_message_data_id
, tvb
, offset
,
327 proto_tree_add_item(sub_tree
, hf_raknet_client_guid
, tvb
,
335 raknet_dissect_open_connection_request_1(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
338 proto_tree
*sub_tree
;
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
,
347 proto_tree_add_item(sub_tree
, hf_raknet_raknet_proto_ver
, tvb
, offset
,
351 /* -1 read to end of tvb buffer */
352 proto_tree_add_item(sub_tree
, hf_raknet_null_padding
, tvb
, offset
,
355 return tvb_reported_length(tvb
);
359 raknet_dissect_open_connection_reply_1(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
362 proto_tree
*sub_tree
;
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
,
373 proto_tree_add_item(sub_tree
, hf_raknet_server_guid
, tvb
, offset
,
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
,
384 if (state
->use_encryption
) {
385 proto_tree_add_item(sub_tree
, hf_raknet_cookie
, tvb
,
386 offset
, 4, ENC_BIG_ENDIAN
);
389 proto_tree_add_item(sub_tree
, hf_raknet_server_public_key
, tvb
,
394 proto_tree_add_item(sub_tree
, hf_raknet_mtu_size
, tvb
, offset
,
402 raknet_dissect_open_connection_request_2(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
405 proto_tree
*sub_tree
;
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
,
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
,
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
,
428 if (client_wrote_challenge
) {
429 proto_tree_add_item(sub_tree
, hf_raknet_client_challenge
, tvb
,
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
,
442 proto_tree_add_item(sub_tree
, hf_raknet_client_guid
, tvb
, offset
,
450 raknet_dissect_open_connection_reply_2(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
453 proto_tree
*sub_tree
;
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
,
463 proto_tree_add_item(sub_tree
, hf_raknet_server_guid
, tvb
, offset
,
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
,
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
,
481 if (state
->use_encryption
) {
482 proto_tree_add_item(sub_tree
, hf_raknet_server_answer
, tvb
, offset
,
491 raknet_dissect_incompatible_protocol_version(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
494 proto_tree
*sub_tree
;
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
);
503 proto_tree_add_item(sub_tree
, hf_raknet_offline_message_data_id
, tvb
, offset
,
507 proto_tree_add_item(sub_tree
, hf_raknet_server_guid
, tvb
, offset
,
515 raknet_dissect_connection_failed(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
518 proto_tree
*sub_tree
;
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
,
527 proto_tree_add_item(sub_tree
, hf_raknet_server_guid
, tvb
, offset
,
535 raknet_dissect_unconnected_pong(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
538 proto_tree
*sub_tree
;
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
);
548 proto_tree_add_item(sub_tree
, hf_raknet_server_guid
, tvb
, offset
,
552 proto_tree_add_item(sub_tree
, hf_raknet_offline_message_data_id
, tvb
, offset
,
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
);
561 proto_tree_add_item(sub_tree
, hf_raknet_0x1C_server_id_str
, tvb
, offset
,
562 str_size
, ENC_NA
|ENC_ASCII
);
569 raknet_dissect_connected_ping(tvbuff_t
*tvb
, packet_info
*pinfo _U_
,
570 proto_tree
*tree
, void* data _U_
)
575 proto_tree_add_item(tree
, hf_raknet_timestamp
, tvb
,
576 offset
, 8, ENC_BIG_ENDIAN
);
583 raknet_dissect_connected_pong(tvbuff_t
*tvb
, packet_info
*pinfo _U_
,
584 proto_tree
*tree
, void* data _U_
)
588 proto_tree_add_item(tree
, hf_raknet_timestamp
, tvb
,
589 offset
, 8, ENC_BIG_ENDIAN
);
592 proto_tree_add_item(tree
, hf_raknet_timestamp
, tvb
,
593 offset
, 8, ENC_BIG_ENDIAN
);
600 raknet_dissect_connection_request(tvbuff_t
*tvb
, packet_info
*pinfo _U_
,
601 proto_tree
*tree
, void* data _U_
)
606 proto_tree_add_item(tree
, hf_raknet_client_guid
, tvb
, offset
,
610 proto_tree_add_item(tree
, hf_raknet_timestamp
, tvb
,
611 offset
, 8, ENC_BIG_ENDIAN
);
614 use_encryption
= tvb_get_uint8(tvb
, offset
) ? true : false;
616 proto_tree_add_item(tree
, hf_raknet_use_encryption
, tvb
, offset
,
620 if (use_encryption
) {
623 proto_tree_add_item(tree
, hf_raknet_client_proof
, tvb
, offset
,
627 use_client_key
= tvb_get_uint8(tvb
, offset
) ? true : false;
629 proto_tree_add_item(tree
, hf_raknet_use_client_key
, tvb
, offset
,
633 if (use_client_key
) {
634 proto_tree_add_item(tree
, hf_raknet_client_identity
, tvb
, offset
,
640 proto_tree_add_item(tree
, hf_raknet_password
, tvb
, offset
,
643 return tvb_reported_length(tvb
);
647 raknet_dissect_connection_request_accepted(tvbuff_t
*tvb
, packet_info
*pinfo _U_
,
648 proto_tree
*tree
, void* data _U_
)
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
,
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
);
669 proto_tree_add_item(tree
, hf_raknet_timestamp
, tvb
,
670 offset
, 8, ENC_BIG_ENDIAN
);
677 raknet_dissect_new_incoming_connection(tvbuff_t
*tvb
, packet_info
*pinfo
,
678 proto_tree
*tree
, void* data _U_
)
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
);
696 proto_tree_add_item(tree
, hf_raknet_timestamp
, tvb
,
697 offset
, 8, ENC_BIG_ENDIAN
);
705 * Protocol definition and handlers.
707 struct raknet_handler_entry
{
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];
771 raknet_init_message_names(void)
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.
796 init_raknet_offline_message(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int *offset
)
798 proto_tree
*sub_tree
;
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
,
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
);
827 raknet_dissect_ACK(tvbuff_t
*tvb
, packet_info
*pinfo
,
828 proto_tree
*tree
, void* data
)
831 proto_tree
*sub_tree
;
836 col_set_str(pinfo
->cinfo
, COL_INFO
, "ACK");
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
);
846 for (i
= 0; i
< count
; i
++) {
852 col_append_str(pinfo
->cinfo
, COL_INFO
, " ");
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
,
865 "%" PRIu32
" .. %" PRIu32
,
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
,
873 proto_tree_add_item(sub_tree
, hf_raknet_packet_number_min
, tvb
,
874 offset
, 3, ENC_LITTLE_ENDIAN
);
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
,
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
,
894 proto_tree_add_item(sub_tree
, hf_raknet_packet_number_min
, tvb
,
895 offset
, 3, ENC_LITTLE_ENDIAN
);
898 proto_tree_add_item(sub_tree
, hf_raknet_packet_number_max
, tvb
,
899 offset
, 3, ENC_LITTLE_ENDIAN
);
904 return tvb_captured_length(tvb
);
908 raknet_dissect_common_message(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*raknet_tree
, void *data
)
911 bool *has_multiple_messages
;
913 proto_item
*raknet_ti
;
915 proto_tree
*msg_tree
;
917 uint32_t payload_bits
;
918 uint32_t payload_octets
;
919 raknet_reliability_t reliability
;
920 bool has_split_packet
;
923 proto_tree
*payload_tree
;
925 bool next_tvb_is_subset
;
926 dissector_handle_t next_dissector
;
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
,
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
);
946 ti
= proto_tree_add_item_ret_uint(msg_tree
, hf_raknet_payload_length
, tvb
,
947 offset
, 2, ENC_BIG_ENDIAN
, &payload_bits
);
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
);
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
);
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
);
980 proto_tree_add_item(msg_tree
, hf_raknet_message_ordering_channel
, tvb
,
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
);
997 proto_tree_add_item_ret_uint(msg_tree
, hf_raknet_split_packet_id
, tvb
,
998 offset
, 2, ENC_BIG_ENDIAN
, &split_packet_id
);
1001 proto_tree_add_item_ret_uint(msg_tree
, hf_raknet_split_packet_index
, tvb
,
1002 offset
, 4, ENC_BIG_ENDIAN
, &split_packet_index
);
1006 * Reassemble the fragmented packet.
1008 save_fragmented
= pinfo
->fragmented
;
1009 pinfo
->fragmented
= true;
1012 fragment_add_seq_check(&raknet_reassembly_table
,
1018 split_packet_index
!= split_packet_count
- 1);
1021 process_reassembled_data(tvb
, offset
, pinfo
, "Reassembled packet",
1022 frag_msg
, &raknet_frag_items
, NULL
, msg_tree
);
1024 pinfo
->fragmented
= save_fragmented
;
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;
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
);
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
1068 if (! *has_multiple_messages
) {
1069 *has_multiple_messages
=
1070 tvb_reported_length_remaining(tvb
, offset
) > (int)payload_octets
1075 * And we finally have the actual size of message.
1077 message_size
= offset
+ payload_octets
;
1081 * It was an incomplete message fragment.
1083 proto_item_set_len(msg_ti
, message_size
);
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.
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
);
1121 call_dissector_only(next_dissector
, next_tvb
, pinfo
, payload_tree
, data
);
1123 proto_item_set_len(msg_ti
, message_size
);
1125 proto_item_set_len(raknet_ti
, proto_item_get_len(raknet_ti
) + message_size
);
1128 if (dissected
>= 0) {
1129 return message_size
;
1137 * It seems not to be a system message so use a dissector set for
1138 * this conversation if any.
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
1153 if (*has_multiple_messages
) {
1154 payload_tree
= msg_tree
;
1157 payload_tree
= proto_tree_get_root(raknet_tree
);
1160 if (next_dissector
) {
1162 call_dissector_only(next_dissector
, next_tvb
, pinfo
, payload_tree
, data
);
1164 if (dissected
> 0) {
1165 goto FIX_UP_AND_RETURN
;
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.
1177 dissector_get_uint_handle(raknet_port_dissectors
, pinfo
->match_uint
);
1179 if (next_dissector
) {
1181 call_dissector_only(next_dissector
, next_tvb
, pinfo
, payload_tree
, data
);
1183 if (dissected
> 0) {
1184 goto FIX_UP_AND_RETURN
;
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.
1196 dissector_try_heuristic(raknet_heur_subdissectors
, next_tvb
, pinfo
, payload_tree
,
1197 &hdtbl_entry
, data
);
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
,
1203 proto_item_append_text(ti
, " %#x", message_id
);
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
);
1216 proto_item_set_len(raknet_ti
, proto_item_get_len(raknet_ti
) + message_size
- payload_octets
);
1220 proto_item_set_len(msg_ti
, message_size
);
1222 proto_item_set_len(raknet_ti
, proto_item_get_len(raknet_ti
) + message_size
);
1225 return message_size
;
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
;
1234 proto_tree
*raknet_tree
;
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
,
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
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
,
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
,
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
);
1283 if (msg_type
& (1 << 5)) { /* hasBAndAS */
1284 proto_tree_add_item(raknet_tree
, hf_raknet_AS
, tvb
, offset
,
1291 return raknet_dissect_ACK(tvb_new_subset_remaining(tvb
, offset
),
1292 pinfo
, raknet_tree
, &is_ACK
);
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
,
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
);
1315 bool is_ACK
= false;
1316 return raknet_dissect_ACK(tvb_new_subset_remaining(tvb
, offset
),
1317 pinfo
, raknet_tree
, &is_ACK
);
1320 return tvb_captured_length(tvb
);
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
,
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
);
1348 proto_tree_add_item_ret_uint(raknet_tree
, hf_raknet_packet_number
, tvb
,
1349 offset
, 3, ENC_LITTLE_ENDIAN
, &packet_number
);
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
);
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
);
1381 * It's the end of packet.
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.
1402 dissect_raknet(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
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
);
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.
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 */
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 */
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 */
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;
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",
1472 VALS(raknet_offline_message_names
), 0x0,
1476 * General fields (fields in >1 packet).
1478 { &hf_raknet_client_guid
,
1479 { "RakNet Client GUID", "raknet.client.guid",
1480 FT_BYTES
, BASE_NONE
,
1484 { &hf_raknet_timestamp
,
1485 { "RakNet Time since start (ms)", "raknet.timestamp",
1486 FT_UINT64
, BASE_DEC
,
1490 { &hf_raknet_offline_message_data_id
,
1491 { "RakNet Offline message data ID", "raknet.offline_message.data_id",
1492 FT_BYTES
, BASE_NONE
,
1496 { &hf_raknet_mtu_size
,
1497 { "RakNet MTU size", "raknet.MTU",
1498 FT_UINT16
, BASE_DEC
,
1502 { &hf_raknet_raknet_proto_ver
,
1503 { "RakNet RakNet protocol version", "raknet.proto_ver",
1508 { &hf_raknet_server_guid
,
1509 { "RakNet Server GUID", "raknet.server_id",
1510 FT_BYTES
, BASE_NONE
,
1514 { &hf_raknet_ip_version
,
1515 { "RakNet IP Version", "raknet.ip.version",
1520 { &hf_raknet_ipv4_address
,
1521 { "RakNet IPv4 Address", "raknet.ip.v4_address",
1526 { &hf_raknet_ipv6_address
,
1527 { "RakNet IPv6 Address", "raknet.ip.v6_address",
1533 { "RakNet Port", "raknet.port",
1534 FT_UINT16
, BASE_DEC
,
1541 { &hf_raknet_null_padding
,
1542 { "RakNet Null padding", "raknet.null_padding",
1550 { &hf_raknet_use_encryption
,
1551 { "RakNet Use encryption", "raknet.use_encryption",
1552 FT_BOOLEAN
, BASE_NONE
,
1556 { &hf_raknet_server_public_key
,
1557 { "RakNet Server public key", "raknet.server.public_key",
1558 FT_BYTES
, BASE_NONE
,
1565 { &hf_raknet_cookie
,
1566 { "RakNet cookie", "raknet.cookie",
1567 FT_UINT32
, BASE_HEX
,
1571 { &hf_raknet_client_wrote_challenge
,
1572 { "RakNet Client wrote challenge", "raknet.client.wrote_challenge",
1573 FT_BOOLEAN
, BASE_NONE
,
1577 { &hf_raknet_client_challenge
,
1578 { "RakNet Client challenge", "raknet.client.challenge",
1579 FT_BYTES
, BASE_NONE
,
1583 { &hf_raknet_client_address
,
1584 { "RakNet Client address", "raknet.client.address",
1585 FT_STRING
, BASE_NONE
,
1589 { &hf_raknet_server_address
,
1590 { "RakNet Server address", "raknet.server.address",
1591 FT_STRING
, BASE_NONE
,
1595 { &hf_raknet_server_answer
,
1596 { "RakNet Server answer", "raknet.server.answer",
1597 FT_BYTES
, BASE_NONE
,
1604 { &hf_raknet_0x1C_server_id_str_len
,
1605 { "RakNet Server ID string len", "raknet.server_id_str_len",
1606 FT_UINT16
, BASE_DEC
,
1610 { &hf_raknet_0x1C_server_id_str
,
1611 { "RakNet Server ID string", "raknet.server_id_str",
1612 FT_STRING
, BASE_NONE
,
1616 { &hf_raknet_packet_type
,
1617 { "RakNet Packet type", "raknet.packet.type",
1622 { &hf_raknet_packet_is_for_connected
,
1623 { "is for connected peer", "raknet.packet.is_for_connected",
1628 { &hf_raknet_packet_is_ACK
,
1629 { "is ACK", "raknet.packet.is_ACK",
1634 { &hf_raknet_packet_has_B_and_AS
,
1635 { "has B and AS", "raknet.packet.has_B_and_AS",
1640 { &hf_raknet_packet_is_NAK
,
1641 { "is NAK", "raknet.packet.is_NAK",
1646 { &hf_raknet_packet_is_pair
,
1647 { "is pair", "raknet.packet.is_pair",
1652 { &hf_raknet_packet_is_continuous_send
,
1653 { "is continuous send", "raknet.packet.is_continuous_send",
1658 { &hf_raknet_packet_needs_B_and_AS
,
1659 { "needs B and AS", "raknet.packet.needs_B_and_AS",
1665 { "RakNet Data arrival rate", "raknet.AS",
1666 FT_FLOAT
, BASE_NONE
,
1670 { &hf_raknet_NACK_record_count
,
1671 { "RakNet ACK/NAK record count", "raknet.NACK.record_count",
1672 FT_UINT16
, BASE_DEC
,
1676 { &hf_raknet_packet_number_range
,
1677 { "RakNet Packet sequence number range", "raknet.range.packet_number",
1678 FT_STRING
, BASE_NONE
,
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
,
1688 { &hf_raknet_packet_number_min
,
1689 { "RakNet Packet sequence number min", "raknet.range.packet_number.min",
1690 FT_UINT24
, BASE_DEC
,
1694 { &hf_raknet_packet_number_max
,
1695 { "RakNet Packet sequence number max", "raknet.range.packet_number.max",
1696 FT_UINT24
, BASE_DEC
,
1700 { &hf_raknet_packet_number
,
1701 { "RakNet Packet sequence number", "raknet.packet_number",
1702 FT_UINT24
, BASE_DEC
,
1706 { &hf_raknet_message
,
1707 { "RakNet Message", "raknet.message",
1712 { &hf_raknet_message_flags
,
1713 { "RakNet Message flags", "raknet.message.flags",
1718 { &hf_raknet_message_reliability
,
1719 { "reliability", "raknet.message.reliability",
1721 VALS(raknet_reliability
), 0xE0,
1724 { &hf_raknet_message_has_split_packet
,
1725 { "has split packet", "raknet.message.has_split_packet",
1730 { &hf_raknet_payload_length
,
1731 { "RakNet Payload length", "raknet.payload.length",
1732 FT_UINT16
, BASE_DEC
,
1736 { &hf_raknet_reliable_message_number
,
1737 { "RakNet Reliable message number", "raknet.reliable.number",
1738 FT_UINT24
, BASE_DEC
,
1742 { &hf_raknet_message_sequencing_index
,
1743 { "RakNet Message sequencing index", "raknet.sequencing.index",
1744 FT_UINT24
, BASE_DEC
,
1748 { &hf_raknet_message_ordering_index
,
1749 { "RakNet Message ordering index", "raknet.ordering.index",
1750 FT_UINT24
, BASE_DEC
,
1754 { &hf_raknet_message_ordering_channel
,
1755 { "RakNet Message ordering channel", "raknet.ordering.channel",
1760 { &hf_raknet_split_packet_count
,
1761 { "RakNet Split packet count", "raknet.split.count",
1762 FT_UINT32
, BASE_DEC
,
1766 { &hf_raknet_split_packet_id
,
1767 { "RakNet Split packet ID", "raknet.split.id",
1768 FT_UINT16
, BASE_DEC
,
1772 { &hf_raknet_split_packet_index
,
1773 { "RakNet Split packet index", "raknet.split.index",
1774 FT_UINT32
, BASE_DEC
,
1778 { &hf_raknet_split_packet
,
1779 { "RakNet Split packet", "raknet.split.packet",
1784 { &hf_raknet_system_message
,
1785 { "RakNet System message", "raknet.system.message",
1790 { &hf_raknet_system_message_id
,
1791 { "RakNet System Message ID", "raknet.system.message.id",
1793 VALS(raknet_system_message_names
), 0x0,
1796 { &hf_raknet_client_proof
,
1797 { "RakNet Client proof of key", "raknet.client.proof",
1798 FT_BYTES
, BASE_NONE
,
1802 { &hf_raknet_use_client_key
,
1803 { "RakNet Use client key", "raknet.use_client_key",
1804 FT_BOOLEAN
, BASE_NONE
,
1808 { &hf_raknet_client_identity
,
1809 { "RakNet Client identity", "raknet.client.identity",
1810 FT_BYTES
, BASE_NONE
,
1814 { &hf_raknet_password
,
1815 { "RakNet Password", "raknet.password",
1816 FT_BYTES
, BASE_NONE
,
1820 { &hf_raknet_system_index
,
1821 { "RakNet System index", "raknet.system.index",
1822 FT_UINT16
, BASE_DEC
,
1826 { &hf_raknet_internal_address
,
1827 { "RakNet Internal address", "raknet.internal.address",
1828 FT_STRING
, BASE_NONE
,
1833 * Fragmented packets
1835 { &hf_raknet_fragment
,
1836 { "Message fragment", "raknet.fragment",
1837 FT_FRAMENUM
, BASE_NONE
,
1841 { &hf_raknet_fragment_count
,
1842 { "Message fragment count", "raknet.fragment.count",
1843 FT_UINT32
, BASE_DEC
,
1847 { &hf_raknet_fragment_error
,
1848 { "Message defragmentation error", "raknet.fragment.error",
1849 FT_FRAMENUM
, BASE_NONE
,
1853 { &hf_raknet_fragment_multiple_tails
,
1854 { "Message has multiple tail fragments", "raknet.fragment.multiple_tails",
1855 FT_BOOLEAN
, BASE_NONE
,
1859 { &hf_raknet_fragment_overlap
,
1860 { "Message fragment overlap", "raknet.fragment.overlap",
1861 FT_BOOLEAN
, BASE_NONE
,
1865 { &hf_raknet_fragment_overlap_conflicts
,
1866 { "Message fragment overlapping with conflicting data", "raknet.fragment.overlap.conflicts",
1867 FT_BOOLEAN
, BASE_NONE
,
1871 { &hf_raknet_fragment_too_long_fragment
,
1872 { "Message fragment too long", "raknet.fragment.too_long",
1873 FT_BOOLEAN
, BASE_NONE
,
1877 { &hf_raknet_fragments
,
1878 { "Message fragments", "raknet.fragments",
1883 { &hf_raknet_reassembled_in
,
1884 { "Reassembled message in frame", "raknet.reassembled.in",
1885 FT_FRAMENUM
, BASE_NONE
,
1889 { &hf_raknet_reassembled_length
,
1890 { "Reassembled message length", "raknet.reassembled.length",
1891 FT_UINT32
, BASE_DEC
,
1898 * Setup protocol subtree array
1900 static int *ett
[] = {
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",
1921 { &ei_raknet_encrypted_message
,
1922 { "raknet.encrypted", PI_DECRYPTION
, PI_NOTE
,
1923 "RakNet encrypted message",
1926 { &ei_raknet_subdissector_failed
,
1927 { "raknet.subdissector.failed", PI_MALFORMED
, PI_NOTE
,
1928 "RakNet message subdissector failed, trying the next candidate or heuristics",
1931 { &ei_raknet_ip_ver_invalid
,
1932 { "raknet.ip_version.invalid", PI_PROTOCOL
, PI_WARN
,
1933 "Invalid IP version",
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
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
);
2001 proto_reg_handoff_raknet(void)
2003 dissector_handle_t raknet_handle_tmp
;
2006 for (i
= 0; i
< array_length(raknet_offline_message_handlers
); i
++) {
2008 create_dissector_handle(raknet_offline_message_handlers
[i
].dissector_fp
,
2010 dissector_add_uint("raknet.offline.message.id", raknet_offline_message_handlers
[i
].vs
.value
,
2014 for (i
= 0; i
< array_length(raknet_system_message_handlers
); i
++) {
2016 create_dissector_handle(raknet_system_message_handlers
[i
].dissector_fp
,
2018 dissector_add_uint("raknet.system.message.id", raknet_system_message_handlers
[i
].vs
.value
,
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
2032 * indent-tabs-mode: nil
2035 * vi: set shiftwidth=4 tabstop=8 expandtab:
2036 * :indentSize=4:tabSize=8:noTabs=true: