/src/wireshark/epan/dissectors/packet-rtitcp.c
Line | Count | Source |
1 | | /* packet-rtitcp.c |
2 | | * Dissector for the RTI TCP Transport Protocol. |
3 | | * Layer on top of TCP used to send Control messages |
4 | | * to establish and maintain the connections as well as |
5 | | * send RTPS data. |
6 | | * |
7 | | * (c) 2005-2015 Copyright, Real-Time Innovations, Inc. |
8 | | * Real-Time Innovations, Inc. |
9 | | * 232 East Java Drive |
10 | | * Sunnyvale, CA 94089 |
11 | | * |
12 | | * Wireshark - Network traffic analyzer |
13 | | * By Gerald Combs <gerald@wireshark.org> |
14 | | * Copyright 1998 Gerald Combs |
15 | | * |
16 | | * SPDX-License-Identifier: GPL-2.0-or-later |
17 | | */ |
18 | | |
19 | | #include "config.h" |
20 | | |
21 | | #include <epan/packet.h> |
22 | | #include <epan/expert.h> |
23 | | #include <epan/prefs.h> |
24 | | #include <epan/addr_resolv.h> |
25 | | #include <epan/wmem_scopes.h> |
26 | | #include <epan/conversation.h> |
27 | | |
28 | | #include <wsutil/ws_padding_to.h> |
29 | | |
30 | | #include "packet-tcp.h" |
31 | | |
32 | 2.64k | #define RTITCP_MAGIC_NUMBER 0xdd54dd55 |
33 | 0 | #define RTPS_MAGIC_NUMBER 0x52545053 |
34 | 0 | #define RTITCP_CONTROL_MAGIC_COOKIE 0x2112A442 |
35 | 0 | #define RTITCP_CRC_MAGIC_NUMBER 0x43524332 |
36 | | |
37 | | /* A sample #define of the minimum length (in bytes) of the protocol data. |
38 | | * If data is received with fewer than this many bytes it is rejected by |
39 | | * the current dissector. */ |
40 | 0 | #define RTITCP_MIN_LENGTH 8 |
41 | 0 | #define NUMBER_2E30 1073741824 |
42 | | |
43 | | #define IDENTITY_BIND_REQUEST (0x0C01) |
44 | | #define IDENTITY_BIND_INDICATION (0x0C11) |
45 | | #define IDENTITY_BIND_RESPONSE (0x0D01) |
46 | | #define IDENTITY_BIND_ERROR (0x0D11) |
47 | | |
48 | | #define SERVER_LOGICAL_PORT_REQUEST (0x0C02) |
49 | | #define SERVER_LOGICAL_PORT_INDICATION (0x0C12) |
50 | | #define SERVER_LOGICAL_PORT_RESPONSE (0x0D02) |
51 | | #define SERVER_LOGICAL_PORT_ERROR (0x0D12) |
52 | | |
53 | | #define CLIENT_LOGICAL_PORT_REQUEST (0x0C03) |
54 | | #define CLIENT_LOGICAL_PORT_INDICATION (0x0C13) |
55 | | #define CLIENT_LOGICAL_PORT_RESPONSE (0x0D03) |
56 | | #define CLIENT_LOGICAL_PORT_ERROR (0x0D13) |
57 | | |
58 | | #define CONNECTION_BIND_REQUEST (0x0C04) |
59 | | #define CONNECTION_BIND_INDICATION (0x0C14) |
60 | | #define CONNECTION_BIND_RESPONSE (0x0D04) |
61 | | #define CONNECTION_BIND_ERROR (0x0D14) |
62 | | |
63 | | #define SESSION_ID_REQUEST (0x0C05) |
64 | | #define SESSION_ID_INDICATION (0x0C15) |
65 | | #define SESSION_ID_RESPONSE (0x0D05) |
66 | | #define SESSION_ID_ERROR (0x0D15) |
67 | | |
68 | | #define LIVELINESS_REQUEST (0x0C06) |
69 | | #define LIVELINESS_RESPONSE (0x0D06) |
70 | | |
71 | | #define FINALIZE_SESSION_REQUEST (0x0C0F) |
72 | | #define FINALIZE_SESSION_INDICATION (0x0C1F) |
73 | | #define FINALIZE_SESSION_RESPONSE (0x0D0F) |
74 | | #define FINALIZE_SESSION_ERRROR (0x0D1F) |
75 | | |
76 | 0 | #define LOCATOR_KIND_IPV4 (1) |
77 | 0 | #define LOCATOR_KIND_IPV6 (2) |
78 | | |
79 | 0 | #define RTPS_LOCATOR_ADDRESS_ATTRIBUTE_TYPE (0x3D01) |
80 | 0 | #define RTPS_LOCATOR_PORT_ATTRIBUTE_TYPE (0x3D02) |
81 | 0 | #define CONNECTION_TYPE_ATTRIBUTE_TYPE (0x3D03) |
82 | 0 | #define CONNECTION_COOKIE_ATTRIBUTE_TYPE (0x3D04) |
83 | | #define PORT_OPTIONS_ATTRIBUTE_TYPE (0x3D05) |
84 | | #define TRANSPORT_PRIORITY_ATTRIBUTE_TYPE (0x3D06) |
85 | 0 | #define SESSION_ID_ATTRIBUTE_TYPE (0x3D07) |
86 | | |
87 | | #define MAPPED_ADDRESS_ATTRIBUTE_TYPE (0x0001) |
88 | | #define XOR_MAPPED_ADDRESS_ATTRIBUTE_TYPE (0x0020) |
89 | 0 | #define ERROR_CODE_ATTRIBUTE_TYPE (0x0009) |
90 | | #define UNKNOWN_ATTRIBUTES_ATTRIBUTE_TYPE (0x000A) |
91 | | |
92 | | #define SOFTWARE_ATTRIBUTE_TYPE (0x8022) |
93 | | #define ALTERNATE_SERVER_ATTRIBUTE_TYPE (0x8023) |
94 | | |
95 | | #define CLASS_ID_TCPV4_LAN (0x00) |
96 | | #define CLASS_ID_TCPV4_WAN (0x40) |
97 | | #define CLASS_ID_TLSV4_LAN (0x80) |
98 | | #define CLASS_ID_TLSV4_WAN (0xC0) |
99 | | |
100 | | |
101 | | #define NDDS_TRANSPORT_TCPV4_CONTROL_PROTOCOL_OK 0 |
102 | | /* client requested a transport class not supported by the server */ |
103 | | #define NDDS_TRANSPORT_TCPV4_CONTROL_PROTOCOL_ERROR_TRANSPORT_CLASS_MISMATCH 1 |
104 | | /* required attribute is missing */ |
105 | | #define NDDS_TRANSPORT_TCPV4_CONTROL_PROTOCOL_ERROR_ATTRIBUTE_MISSING 2 |
106 | | /* no matching receive resource for requested port */ |
107 | | #define NDDS_TRANSPORT_TCPV4_CONTROL_PROTOCOL_ERROR_NO_MATCHING_RECVRESOURCE 3 |
108 | | /* no matching cookie found on server */ |
109 | | #define NDDS_TRANSPORT_TCPV4_CONTROL_PROTOCOL_ERROR_NO_MATCH_COOKIE 4 |
110 | | /* fatal internal processing error (caller is not responsible) */ |
111 | | #define NDDS_TRANSPORT_TCPV4_CONTROL_PROTOCOL_ERROR_INTERNAL 5 |
112 | | /* the operation should be retried at the first occurrence */ |
113 | | #define NDDS_TRANSPORT_TCPV4_CONTROL_PROTOCOL_ERROR_RETRY 6 |
114 | | #define NDDS_TRANSPORT_TCP_CONTROL_ERROR_CODE_ATTRIBUTE_BAD_REQUEST_ID 400 |
115 | | #define NDDS_TRANSPORT_TCP_CONTROL_ERROR_CODE_ATTRIBUTE_UNKNOWN_ATTRIBUTE_ID 420 |
116 | | #define NDDS_TRANSPORT_TCP_CONTROL_ERROR_CODE_ATTRIBUTE_ALLOCATION_MISMATCH_ID 437 |
117 | | #define NDDS_TRANSPORT_TCP_CONTROL_ERROR_CODE_ATTRIBUTE_UNSUPPORTED_TRANSPORT_PROTOCOL_ID 442 |
118 | | #define NDDS_TRANSPORT_TCP_CONTROL_ERROR_CODE_ATTRIBUTE_CONNECTION_ALREADY_EXISTS_ID 446 |
119 | | #define NDDS_TRANSPORT_TCP_CONTROL_ERROR_CODE_ATTRIBUTE_SERVER_ERROR_ID 500 |
120 | | |
121 | | /* Forward declaration that is needed below if using the |
122 | | * proto_reg_handoff_rtitcp function as a callback for when protocol |
123 | | * preferences get changed. For now we don't have preferences but we |
124 | | * may have them in the future.*/ |
125 | | |
126 | | void proto_reg_handoff_rtitcp(void); |
127 | | void proto_register_rtitcp(void); |
128 | | |
129 | | /* Initialize the protocol and registered fields */ |
130 | | static int proto_rtitcp; |
131 | | static int hf_rtitcp_header_control_byte; |
132 | | static int hf_rtitcp_header_magic_number; |
133 | | static int hf_rtitcp_header_message_length; |
134 | | static int hf_rtitcp_control_transaction_id; |
135 | | static int hf_rtitcp_control_kind; |
136 | | static int hf_rtitcp_control_attribute_type; |
137 | | static int hf_rtitcp_control_attribute_length; |
138 | | static int hf_rtitcp_control_attribute_port; |
139 | | static int hf_rtitcp_attributes_list_length; |
140 | | static int hf_rtitcp_control_magic_cookie; |
141 | | static int hf_rtitcp_control_attribute_connection_cookie; |
142 | | static int hf_rtitcp_control_attribute_connection_type; |
143 | | static int hf_rtitcp_control_attribute_session_id; |
144 | | static int hf_rtitcp_control_attribute_error_code_value; |
145 | | static int hf_rtitcp_control_attribute_error_code_description; |
146 | | static int hf_rtitcp_locator_ipv4; |
147 | | static int hf_rtitcp_locator_port; |
148 | | static int hf_rtitcp_locator_ipv6; |
149 | | static int hf_rtitcp_locator_kind; |
150 | | static int hf_rtitcp_crc_magic_cookie; |
151 | | static int hf_rtitcp_control_crc_value; |
152 | | |
153 | | static int hf_rtitcp_response_in; |
154 | | static int hf_rtitcp_response_to; |
155 | | static int hf_rtitcp_response_time; |
156 | | |
157 | 0 | #define RTITCP_FLAG_NOT_REQUEST 0x0100 |
158 | | |
159 | | typedef struct _rtitcp_transaction_t { |
160 | | uint32_t req_frame; |
161 | | uint32_t rep_frame; |
162 | | nstime_t req_time; |
163 | | } rtitcp_transaction_t; |
164 | | |
165 | | typedef struct _rtitcp_conv_info_t { |
166 | | wmem_map_t *pdus; |
167 | | } rtitcp_conv_info_t; |
168 | | |
169 | | /* Subtree pointers */ |
170 | | static int ett_rtitcp; |
171 | | static int ett_rtitcp_signalling_protocol; |
172 | | static int ett_rtitcp_message; |
173 | | static int ett_rtitcp_attributes_list; |
174 | | static int ett_rtitcp_attribute; |
175 | | |
176 | | static header_field_info *hfi_rtitcp; |
177 | | static heur_dissector_list_t heur_subdissector_list; |
178 | | |
179 | | static const value_string ctrl_message_types_vals[] = { |
180 | | { IDENTITY_BIND_REQUEST, "Identity Bind Request" }, |
181 | | { IDENTITY_BIND_INDICATION, "Identity Bind Indication" }, |
182 | | { IDENTITY_BIND_RESPONSE, "Identity Bind Response" }, |
183 | | { IDENTITY_BIND_ERROR, "Identity Bind Error" }, |
184 | | { SERVER_LOGICAL_PORT_REQUEST, "Server Logical Port Request" }, |
185 | | { SERVER_LOGICAL_PORT_RESPONSE, "Server Logical Port Response" }, |
186 | | { SERVER_LOGICAL_PORT_ERROR, "Server Logical Port Error" }, |
187 | | { CLIENT_LOGICAL_PORT_REQUEST, "Client Logical Port Request" }, |
188 | | { CLIENT_LOGICAL_PORT_RESPONSE, "Client Logical Port Response" }, |
189 | | { CLIENT_LOGICAL_PORT_ERROR, "Client Logical Port Error" }, |
190 | | { CONNECTION_BIND_REQUEST, "Connection Bind Request" }, |
191 | | { CONNECTION_BIND_RESPONSE, "Connection Bind Response" }, |
192 | | { CONNECTION_BIND_ERROR, "Connection Bind Error" }, |
193 | | { SESSION_ID_REQUEST, "Session ID Request" }, |
194 | | { SESSION_ID_INDICATION, "Session ID Indication" }, |
195 | | { SESSION_ID_RESPONSE, "Session ID Response" }, |
196 | | { SESSION_ID_ERROR, "Session ID Error" }, |
197 | | { LIVELINESS_REQUEST, "Liveliness Request" }, |
198 | | { LIVELINESS_RESPONSE, "Liveliness Response" }, |
199 | | { FINALIZE_SESSION_INDICATION, "Finalize Session Indication" }, |
200 | | { 0, NULL } |
201 | | }; |
202 | | |
203 | | static const value_string attribute_types_vals[] = { |
204 | | { RTPS_LOCATOR_ADDRESS_ATTRIBUTE_TYPE, "Locator Address" }, |
205 | | { RTPS_LOCATOR_PORT_ATTRIBUTE_TYPE, "Locator Port" }, |
206 | | { CONNECTION_TYPE_ATTRIBUTE_TYPE, "Connection Type" }, |
207 | | { CONNECTION_COOKIE_ATTRIBUTE_TYPE, "Connection Cookie" }, |
208 | | { PORT_OPTIONS_ATTRIBUTE_TYPE, "Port options" }, |
209 | | { TRANSPORT_PRIORITY_ATTRIBUTE_TYPE, "Transport priority" }, |
210 | | { SESSION_ID_ATTRIBUTE_TYPE, "Session ID" }, |
211 | | { MAPPED_ADDRESS_ATTRIBUTE_TYPE, "Mapped Address" }, |
212 | | { XOR_MAPPED_ADDRESS_ATTRIBUTE_TYPE, "XOR Mapped Address" }, |
213 | | { ERROR_CODE_ATTRIBUTE_TYPE, "Error Code" }, |
214 | | { UNKNOWN_ATTRIBUTES_ATTRIBUTE_TYPE, "Unknown attribute" }, |
215 | | { SOFTWARE_ATTRIBUTE_TYPE, "Software" }, |
216 | | { ALTERNATE_SERVER_ATTRIBUTE_TYPE, "Alternate Server" }, |
217 | | { 0, NULL } |
218 | | }; |
219 | | |
220 | | static const value_string error_code_kind_vals[] = { |
221 | | { NDDS_TRANSPORT_TCPV4_CONTROL_PROTOCOL_OK, |
222 | | "PROTOCOL_OK" }, |
223 | | { NDDS_TRANSPORT_TCPV4_CONTROL_PROTOCOL_ERROR_TRANSPORT_CLASS_MISMATCH, |
224 | | "PROTOCOL_ERROR_TRANSPORT_CLASS_MISMATCH" }, |
225 | | { NDDS_TRANSPORT_TCPV4_CONTROL_PROTOCOL_ERROR_ATTRIBUTE_MISSING, |
226 | | "PROTOCOL_ERROR_ATTRIBUTE_MISSING" }, |
227 | | { NDDS_TRANSPORT_TCPV4_CONTROL_PROTOCOL_ERROR_NO_MATCHING_RECVRESOURCE, |
228 | | "PROTOCOL_ERROR_NO_MATCHING_RECVRESOURCE" }, |
229 | | { NDDS_TRANSPORT_TCPV4_CONTROL_PROTOCOL_ERROR_NO_MATCH_COOKIE, |
230 | | "PROTOCOL_ERROR_NO_MATCH_COOKIE" }, |
231 | | { NDDS_TRANSPORT_TCPV4_CONTROL_PROTOCOL_ERROR_INTERNAL, |
232 | | "PROTOCOL_ERROR_INTERNAL" }, |
233 | | { NDDS_TRANSPORT_TCPV4_CONTROL_PROTOCOL_ERROR_RETRY, |
234 | | "PROTOCOL_ERROR_RETRY" }, |
235 | | { NDDS_TRANSPORT_TCP_CONTROL_ERROR_CODE_ATTRIBUTE_BAD_REQUEST_ID, |
236 | | "ERROR_CODE_ATTRIBUTE_BAD_REQUEST_ID" }, |
237 | | { NDDS_TRANSPORT_TCP_CONTROL_ERROR_CODE_ATTRIBUTE_UNKNOWN_ATTRIBUTE_ID, |
238 | | "ERROR_CODE_ATTRIBUTE_UNKNOWN_ATTRIBUTE_ID" }, |
239 | | { NDDS_TRANSPORT_TCP_CONTROL_ERROR_CODE_ATTRIBUTE_ALLOCATION_MISMATCH_ID, |
240 | | "ERROR_CODE_ATTRIBUTE_ALLOCATION_MISMATCH_ID" }, |
241 | | { NDDS_TRANSPORT_TCP_CONTROL_ERROR_CODE_ATTRIBUTE_UNSUPPORTED_TRANSPORT_PROTOCOL_ID, |
242 | | "ERROR_CODE_ATTRIBUTE_UNSUPPORTED_TRANSPORT_PROTOCOL_ID" }, |
243 | | { NDDS_TRANSPORT_TCP_CONTROL_ERROR_CODE_ATTRIBUTE_CONNECTION_ALREADY_EXISTS_ID, |
244 | | "ERROR_CODE_ATTRIBUTE_CONNECTION_ALREADY_EXISTS_ID" }, |
245 | | { NDDS_TRANSPORT_TCP_CONTROL_ERROR_CODE_ATTRIBUTE_SERVER_ERROR_ID, |
246 | | "ERROR_CODE_ATTRIBUTE_SERVER_ERROR_ID" }, |
247 | | { 0, NULL } |
248 | | }; |
249 | | |
250 | | static const value_string rtitcp_locator_kind_vals[] = { |
251 | | { LOCATOR_KIND_IPV4, "IPV4" }, |
252 | | { LOCATOR_KIND_IPV6, "Unreachable peer" }, |
253 | | { 0, NULL } |
254 | | }; |
255 | | |
256 | | static const value_string rtitcp_attribute_connection_type_vals[] = { |
257 | | { CLASS_ID_TCPV4_LAN, "TCPV4_LAN" }, |
258 | | { CLASS_ID_TCPV4_WAN, "TCPV4_WAN" }, |
259 | | { CLASS_ID_TLSV4_LAN, "TLSV4_LAN" }, |
260 | | { CLASS_ID_TLSV4_WAN, "TLSV4_WAN" }, |
261 | | { 0, NULL } |
262 | | }; |
263 | | |
264 | | static void rtitcp_util_add_error_attribute(proto_tree *attribute, tvbuff_t* tvb, |
265 | 0 | int offset, unsigned size) { |
266 | 0 | proto_tree_add_item(attribute, hf_rtitcp_control_attribute_error_code_value, tvb, offset, 4, ENC_BIG_ENDIAN); |
267 | 0 | proto_tree_add_item(attribute, hf_rtitcp_control_attribute_error_code_description, tvb, offset + 4, |
268 | 0 | size - 4, ENC_ASCII); |
269 | 0 | } |
270 | | |
271 | | static void rtitcp_util_add_locator_t(proto_tree *tree, packet_info *pinfo _U_, tvbuff_t * tvb, |
272 | | int offset, bool little_endian, |
273 | 0 | proto_item * rtitcp_message, bool * first_attribute) { |
274 | 0 | int32_t kind; |
275 | 0 | uint16_t port; |
276 | 0 | kind = tvb_get_uint16(tvb, offset+8, little_endian ? ENC_LITTLE_ENDIAN : ENC_BIG_ENDIAN); |
277 | |
|
278 | 0 | if (kind == 0xFFFF) { |
279 | 0 | kind = LOCATOR_KIND_IPV4; |
280 | 0 | } else { |
281 | 0 | kind = LOCATOR_KIND_IPV6; |
282 | 0 | } |
283 | 0 | proto_tree_add_uint(tree, hf_rtitcp_locator_kind, tvb, offset+8, 2, kind); |
284 | |
|
285 | 0 | if (kind == LOCATOR_KIND_IPV4) { |
286 | 0 | proto_tree_add_item(tree, hf_rtitcp_locator_port, tvb, offset+10, 2, ENC_BIG_ENDIAN); |
287 | 0 | proto_tree_add_item(tree, hf_rtitcp_locator_ipv4, tvb, offset+12, 4, ENC_BIG_ENDIAN); |
288 | |
|
289 | 0 | port = tvb_get_uint16(tvb, offset+10, little_endian ? ENC_LITTLE_ENDIAN : ENC_BIG_ENDIAN); |
290 | 0 | if (*first_attribute) { |
291 | 0 | proto_item_append_text(rtitcp_message," ("); |
292 | 0 | col_append_str(pinfo->cinfo, COL_INFO, " ("); |
293 | 0 | } |
294 | 0 | proto_item_append_text(rtitcp_message, "%s%s:%u", |
295 | 0 | *first_attribute ? "" : ", ", tvb_ip_to_str(pinfo->pool, tvb, offset + 12), port); |
296 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "%s%s:%u", |
297 | 0 | *first_attribute ? "" : ", ", tvb_ip_to_str(pinfo->pool, tvb, offset + 12), port); |
298 | 0 | } else { |
299 | 0 | proto_tree_add_item(tree, hf_rtitcp_locator_ipv6, tvb, offset, 16, ENC_NA); |
300 | 0 | if (*first_attribute) { |
301 | 0 | proto_item_append_text(rtitcp_message," ("); |
302 | 0 | col_append_str(pinfo->cinfo, COL_INFO, " ("); |
303 | 0 | } |
304 | 0 | proto_item_append_text(rtitcp_message, "%s%s", |
305 | 0 | *first_attribute ? "" : ", ", tvb_ip6_to_str(pinfo->pool, tvb, offset)); |
306 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "%s%s", |
307 | 0 | *first_attribute ? "" : ", ", tvb_ip6_to_str(pinfo->pool, tvb, offset)); |
308 | 0 | } |
309 | 0 | } |
310 | | |
311 | | static unsigned dissect_attribute(tvbuff_t *tvb, packet_info *pinfo, |
312 | | proto_tree *attributes_list, unsigned offset, unsigned attributes_list_offset, |
313 | 0 | proto_item * rtitcp_message, bool * first_attribute) { |
314 | |
|
315 | 0 | uint16_t attribute_length, attribute_type; |
316 | 0 | unsigned padding; |
317 | 0 | proto_item *attribute; |
318 | |
|
319 | 0 | attribute_type = tvb_get_uint16(tvb, attributes_list_offset+offset, ENC_BIG_ENDIAN); |
320 | 0 | attribute_length = tvb_get_uint16(tvb, attributes_list_offset+offset+2, ENC_BIG_ENDIAN); |
321 | |
|
322 | 0 | attribute = proto_tree_add_subtree_format(attributes_list, tvb, |
323 | 0 | attributes_list_offset+offset, attribute_length+4, |
324 | 0 | ett_rtitcp_attribute, NULL, "Unknown Attribute"); |
325 | |
|
326 | 0 | proto_tree_add_item(attribute, hf_rtitcp_control_attribute_type, tvb, |
327 | 0 | attributes_list_offset+offset, 2, ENC_BIG_ENDIAN); |
328 | 0 | proto_tree_add_item(attribute, hf_rtitcp_control_attribute_length, tvb, |
329 | 0 | attributes_list_offset+offset+2, 2, ENC_BIG_ENDIAN); |
330 | 0 | proto_item_set_text(attribute,"%s", val_to_str_const(attribute_type, attribute_types_vals, "Unknown attribute")); |
331 | |
|
332 | 0 | switch (attribute_type) { |
333 | 0 | case RTPS_LOCATOR_PORT_ATTRIBUTE_TYPE: { |
334 | 0 | uint32_t port; |
335 | 0 | port = tvb_get_uint32(tvb, attributes_list_offset+offset+4, ENC_BIG_ENDIAN); |
336 | 0 | if (*first_attribute) { |
337 | 0 | proto_item_append_text(rtitcp_message," ("); |
338 | 0 | col_append_str(pinfo->cinfo, COL_INFO, " ("); |
339 | 0 | } |
340 | 0 | proto_item_append_text(rtitcp_message, "%s%u", |
341 | 0 | *first_attribute ? "" : ", ", port); |
342 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "%s%u", |
343 | 0 | *first_attribute ? "" : ", ", port); |
344 | 0 | (*first_attribute) = false; |
345 | 0 | proto_item_append_text(attribute, " (Port = %u)", port); |
346 | 0 | proto_tree_add_item(attribute, hf_rtitcp_control_attribute_port, tvb, |
347 | 0 | attributes_list_offset+offset+4, attribute_length, ENC_BIG_ENDIAN); |
348 | 0 | break; |
349 | 0 | } |
350 | 0 | case RTPS_LOCATOR_ADDRESS_ATTRIBUTE_TYPE: { |
351 | 0 | rtitcp_util_add_locator_t(attribute, pinfo, tvb, attributes_list_offset+offset+4, |
352 | 0 | ENC_BIG_ENDIAN, rtitcp_message, first_attribute); |
353 | 0 | (*first_attribute) = false; |
354 | 0 | break; |
355 | 0 | } |
356 | | |
357 | 0 | case CONNECTION_COOKIE_ATTRIBUTE_TYPE: { |
358 | 0 | proto_tree_add_item(attribute, hf_rtitcp_control_attribute_connection_cookie, |
359 | 0 | tvb, attributes_list_offset+offset+4, attribute_length, ENC_NA); |
360 | 0 | if (*first_attribute) { |
361 | 0 | proto_item_append_text(rtitcp_message," ("); |
362 | 0 | col_append_str(pinfo->cinfo, COL_INFO, " ("); |
363 | 0 | } |
364 | 0 | proto_item_append_text(rtitcp_message, "%s%s", |
365 | 0 | (*first_attribute) ? "" : ", ", |
366 | 0 | tvb_bytes_to_str(pinfo->pool, tvb, attributes_list_offset+offset+4, 16)); |
367 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "%s%s", |
368 | 0 | (*first_attribute) ? "" : ", ", |
369 | 0 | tvb_bytes_to_str(pinfo->pool, tvb, attributes_list_offset+offset+4, 16)); |
370 | 0 | (*first_attribute) = false; |
371 | 0 | break; |
372 | 0 | } |
373 | 0 | case CONNECTION_TYPE_ATTRIBUTE_TYPE: { |
374 | 0 | uint8_t attribute_connection_type = tvb_get_uint8(tvb, attributes_list_offset+offset+4); |
375 | 0 | proto_tree_add_item(attribute, hf_rtitcp_control_attribute_connection_type, tvb, |
376 | 0 | attributes_list_offset+offset+4, attribute_length, ENC_BIG_ENDIAN); |
377 | 0 | if (*first_attribute) { |
378 | 0 | proto_item_append_text(rtitcp_message," ("); |
379 | 0 | col_append_str(pinfo->cinfo, COL_INFO, " ("); |
380 | 0 | } |
381 | 0 | proto_item_append_text(rtitcp_message, "%s%s", |
382 | 0 | (*first_attribute) ? "" : ", ", |
383 | 0 | val_to_str_const(attribute_connection_type, rtitcp_attribute_connection_type_vals, "Unknown attribute")); |
384 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "%s%s", |
385 | 0 | (*first_attribute) ? "" : ", ", |
386 | 0 | val_to_str_const(attribute_connection_type, rtitcp_attribute_connection_type_vals, "Unknown attribute")); |
387 | 0 | (*first_attribute) = false; |
388 | 0 | break; |
389 | 0 | } |
390 | 0 | case SESSION_ID_ATTRIBUTE_TYPE: { |
391 | 0 | proto_tree_add_item(attribute, hf_rtitcp_control_attribute_session_id, tvb, |
392 | 0 | attributes_list_offset+offset+4, attribute_length, ENC_NA); |
393 | 0 | break; |
394 | 0 | } |
395 | 0 | case ERROR_CODE_ATTRIBUTE_TYPE: { |
396 | 0 | rtitcp_util_add_error_attribute(attribute, tvb, attributes_list_offset+offset+4, attribute_length); |
397 | 0 | break; |
398 | 0 | } |
399 | 0 | default: |
400 | 0 | break; |
401 | 0 | } |
402 | | |
403 | 0 | padding = WS_PADDING_TO_4(attribute_length); |
404 | 0 | return (attribute_length+padding+4); |
405 | 0 | } |
406 | | static proto_tree* print_header(proto_tree *tree, proto_tree *rtitcp_message, tvbuff_t *tvb, unsigned offset, |
407 | 0 | uint16_t msg_length, bool printCRC, bool is_data) { |
408 | 0 | proto_item *ti; |
409 | |
|
410 | 0 | if (is_data) { |
411 | 0 | rtitcp_message = proto_tree_add_subtree_format(tree, tvb, offset, msg_length, |
412 | 0 | ett_rtitcp_message, NULL, "RTI TCP Data Message"); |
413 | 0 | } else { |
414 | 0 | rtitcp_message = proto_tree_add_subtree_format(tree, tvb, offset, msg_length, |
415 | 0 | ett_rtitcp_message, NULL, "RTI TCP Control Message"); |
416 | 0 | } |
417 | 0 | if (is_data) { |
418 | 0 | uint32_t msg_length32; |
419 | 0 | proto_tree_add_item(rtitcp_message, hf_rtitcp_header_control_byte, tvb, offset, 1, ENC_BIG_ENDIAN); |
420 | 0 | ti = proto_tree_add_item(rtitcp_message, hf_rtitcp_header_message_length, |
421 | 0 | tvb, offset+1, 3, ENC_BIG_ENDIAN); |
422 | 0 | msg_length32 = tvb_get_uint32(tvb, offset, ENC_BIG_ENDIAN); |
423 | 0 | msg_length32 = msg_length32 % NUMBER_2E30; |
424 | 0 | proto_item_set_text(ti,"RTI TCP Message Length: %d", msg_length32); |
425 | 0 | } else { |
426 | 0 | proto_tree_add_item(rtitcp_message, hf_rtitcp_header_control_byte, tvb, offset, 2, ENC_BIG_ENDIAN); |
427 | 0 | proto_tree_add_item(rtitcp_message, hf_rtitcp_header_message_length, tvb, offset+2, 2, ENC_BIG_ENDIAN); |
428 | 0 | } |
429 | 0 | proto_tree_add_item(rtitcp_message, hf_rtitcp_header_magic_number, tvb, offset+4, 4, ENC_BIG_ENDIAN); |
430 | 0 | if (printCRC) { |
431 | 0 | proto_tree_add_item(rtitcp_message, hf_rtitcp_crc_magic_cookie, tvb, offset+8, 4, ENC_BIG_ENDIAN); |
432 | 0 | proto_tree_add_item(rtitcp_message, hf_rtitcp_control_crc_value, tvb, offset+12, 4, ENC_BIG_ENDIAN); |
433 | 0 | } |
434 | |
|
435 | 0 | return rtitcp_message; |
436 | 0 | } |
437 | | static uint16_t dissect_control_message(proto_tree *rtitcp_tree, tvbuff_t *tvb, packet_info *pinfo, |
438 | 0 | unsigned offset) { |
439 | | |
440 | | /* 0...2...........7...............15.............23...............31 |
441 | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
442 | | * | Not Used | msg_length | |
443 | | * +---------------+---------------+---------------+---------------+ |
444 | | * | RTITCP_MAGIC_NUMBER | |
445 | | * +---------------+---------------+---------------+---------------+ |
446 | | * | control_message_kind | attributes_list_length | |
447 | | * +---------------+---------------+---------------+---------------+ |
448 | | * | RTITCP_CONTROL_MAGIC_COOKIE | |
449 | | * +---------------+---------------+---------------+---------------+ |
450 | | * | | |
451 | | * |- -| |
452 | | * | TRANSACTION_ID | |
453 | | * |- -| |
454 | | * | | |
455 | | * +---------------+---------------+---------------+---------------+ --------------------------------- |
456 | | * | attribute_type | attribute_length .. Repeat | |
457 | | * +---------------+---------------+---------------+---------------+ until | |
458 | | * | ATTRIBUTE (length) | attributes_list_length expires | |
459 | | * +---------------+---------------+---------------+---------------+ --------------------------------*/ |
460 | |
|
461 | 0 | proto_tree *attributes_list, *rtitcp_message = NULL; |
462 | 0 | uint16_t msg_length, control_message_kind, attributes_list_length, header_length; |
463 | 0 | unsigned attributes_list_offset, attribute_offset, offset_header = offset; |
464 | 0 | unsigned attributes_count; |
465 | 0 | bool is_data = false, printCRC = false, first_attribute; |
466 | 0 | char * transaction_id_str; |
467 | 0 | uint64_t seq_num; |
468 | 0 | conversation_t *conversation; |
469 | 0 | rtitcp_conv_info_t *rtitcp_info; |
470 | 0 | rtitcp_transaction_t *rtitcp_trans; |
471 | 0 | uint64_t * conversation_info_key = NULL; |
472 | | |
473 | | /* The header length is 8 if it doesn't contain optional fields */ |
474 | 0 | header_length = 8; |
475 | |
|
476 | 0 | msg_length = tvb_get_uint16(tvb, offset+2, ENC_BIG_ENDIAN); |
477 | 0 | offset += 8; |
478 | | |
479 | | /* Check if CRC is present */ |
480 | 0 | if (tvb_get_ntohl(tvb, offset) == RTITCP_CRC_MAGIC_NUMBER) { |
481 | 0 | printCRC = true; |
482 | 0 | header_length += 8; |
483 | 0 | offset += 8; /* Because of 0xCRC32 + actual CRC (4 bytes) */ |
484 | 0 | } |
485 | | |
486 | | /* Time to print the header */ |
487 | 0 | rtitcp_message = print_header(rtitcp_tree, rtitcp_message, tvb, offset_header, msg_length + header_length, printCRC, is_data); |
488 | | |
489 | | /* Check the control message kind */ |
490 | 0 | control_message_kind = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN); |
491 | 0 | col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", |
492 | 0 | val_to_str_const(control_message_kind,ctrl_message_types_vals, "Unknown control message")); |
493 | 0 | proto_tree_add_uint(rtitcp_message, hf_rtitcp_control_kind, tvb, offset, 2, control_message_kind); |
494 | 0 | proto_item_set_text(rtitcp_message,"RTI TCP Control Message , Kind: %s", |
495 | 0 | val_to_str_const(control_message_kind,ctrl_message_types_vals, "Unknown control message")); |
496 | 0 | offset += 2; |
497 | | |
498 | | /* Take the length in bytes of the attributes list */ |
499 | 0 | attributes_list_length = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN); |
500 | 0 | proto_tree_add_item(rtitcp_message, hf_rtitcp_attributes_list_length, tvb, offset, 2, ENC_BIG_ENDIAN); |
501 | 0 | offset += 2; |
502 | | |
503 | | /* We expect now the RTI TCP Control Magic Cookie */ |
504 | 0 | if (tvb_get_ntohl(tvb, offset) != RTITCP_CONTROL_MAGIC_COOKIE) { |
505 | 0 | return msg_length + header_length; |
506 | 0 | } |
507 | 0 | proto_tree_add_item(rtitcp_message, hf_rtitcp_control_magic_cookie, tvb, offset, 4, ENC_BIG_ENDIAN); |
508 | 0 | offset += 4; |
509 | | |
510 | | /* Now we dissect the transaction id */ |
511 | 0 | proto_tree_add_item(rtitcp_message, hf_rtitcp_control_transaction_id, tvb, offset, 12, ENC_NA); |
512 | 0 | transaction_id_str = tvb_bytes_to_str(pinfo->pool, tvb, offset, 12); |
513 | | |
514 | | /* Get the transaction identifier. Not the whole transaction but the middle part, which |
515 | | * shouldn't coincide */ |
516 | 0 | seq_num = tvb_get_ntoh64(tvb, offset); |
517 | | |
518 | | /* |
519 | | * We need to track some state for this protocol on a per conversation |
520 | | * basis so we can do neat things like request/response tracking |
521 | | */ |
522 | 0 | conversation = find_or_create_conversation(pinfo); |
523 | |
|
524 | 0 | rtitcp_info = (rtitcp_conv_info_t *)conversation_get_proto_data(conversation, proto_rtitcp); |
525 | 0 | if (!rtitcp_info) { |
526 | | /* |
527 | | * No. Attach that information to the conversation, and add |
528 | | * it to the list of information structures. |
529 | | */ |
530 | 0 | rtitcp_info = wmem_new(wmem_file_scope(), rtitcp_conv_info_t); |
531 | 0 | rtitcp_info->pdus=wmem_map_new(wmem_file_scope(), g_int64_hash, g_int64_equal); |
532 | |
|
533 | 0 | conversation_add_proto_data(conversation, proto_rtitcp, rtitcp_info); |
534 | 0 | } |
535 | 0 | if (!pinfo->fd->visited) { |
536 | 0 | if (!(control_message_kind & RTITCP_FLAG_NOT_REQUEST)) { |
537 | | /* This is a request */ |
538 | 0 | rtitcp_trans=wmem_new(wmem_file_scope(), rtitcp_transaction_t); |
539 | 0 | rtitcp_trans->req_frame = pinfo->num; |
540 | 0 | rtitcp_trans->rep_frame = 0; |
541 | 0 | rtitcp_trans->req_time = pinfo->abs_ts; |
542 | 0 | conversation_info_key = wmem_new0(wmem_file_scope(), uint64_t); |
543 | 0 | *conversation_info_key = seq_num; |
544 | 0 | wmem_map_insert(rtitcp_info->pdus, conversation_info_key, (void *)rtitcp_trans); |
545 | 0 | } else { |
546 | 0 | conversation_info_key = &seq_num; |
547 | 0 | rtitcp_trans=(rtitcp_transaction_t *)wmem_map_lookup(rtitcp_info->pdus, conversation_info_key); |
548 | 0 | if (rtitcp_trans) { |
549 | 0 | rtitcp_trans->rep_frame = pinfo->num; |
550 | 0 | } |
551 | 0 | } |
552 | 0 | } else { |
553 | 0 | conversation_info_key = &seq_num; |
554 | 0 | rtitcp_trans=(rtitcp_transaction_t *)wmem_map_lookup(rtitcp_info->pdus, conversation_info_key); |
555 | 0 | } |
556 | 0 | if (!rtitcp_trans) { |
557 | | /* create a "fake" rtitcp_trans structure */ |
558 | 0 | rtitcp_trans=wmem_new(pinfo->pool, rtitcp_transaction_t); |
559 | 0 | rtitcp_trans->req_frame = 0; |
560 | 0 | rtitcp_trans->rep_frame = 0; |
561 | 0 | rtitcp_trans->req_time = pinfo->abs_ts; |
562 | 0 | } |
563 | | |
564 | | /* print state tracking in the tree */ |
565 | 0 | if (!(control_message_kind & RTITCP_FLAG_NOT_REQUEST)) { |
566 | | /* This is a request */ |
567 | 0 | if (rtitcp_trans->rep_frame) { |
568 | 0 | proto_item *it; |
569 | 0 | it = proto_tree_add_uint(rtitcp_message, hf_rtitcp_response_in, |
570 | 0 | tvb, 0, 0, rtitcp_trans->rep_frame); |
571 | 0 | proto_item_set_generated(it); |
572 | 0 | } |
573 | 0 | } else { |
574 | | /* This is a reply */ |
575 | 0 | if (rtitcp_trans->req_frame) { |
576 | 0 | proto_item *it; |
577 | 0 | nstime_t ns; |
578 | 0 | it = proto_tree_add_uint(rtitcp_message, hf_rtitcp_response_to, |
579 | 0 | tvb, 0, 0, rtitcp_trans->req_frame); |
580 | 0 | proto_item_set_generated(it); |
581 | |
|
582 | 0 | nstime_delta(&ns, &pinfo->abs_ts, &rtitcp_trans->req_time); |
583 | 0 | it = proto_tree_add_time(rtitcp_message, hf_rtitcp_response_time, tvb, 0, 0, &ns); |
584 | 0 | proto_item_set_generated(it); |
585 | 0 | } |
586 | 0 | } |
587 | | |
588 | | /* End of feature */ |
589 | 0 | offset += 12; |
590 | | |
591 | | /* Finally, dissect the list of attributes */ |
592 | 0 | attributes_list_offset = 0; |
593 | 0 | attributes_list = proto_tree_add_subtree_format(rtitcp_message, tvb, |
594 | 0 | attributes_list_offset+offset, attributes_list_length, |
595 | 0 | ett_rtitcp_attributes_list, NULL, "Attributes List"); |
596 | |
|
597 | 0 | attributes_count = 0; |
598 | 0 | first_attribute = true; |
599 | 0 | while (attributes_list_offset < attributes_list_length) { |
600 | 0 | ++attributes_count; |
601 | 0 | attribute_offset = dissect_attribute(tvb, pinfo, attributes_list, |
602 | 0 | offset, attributes_list_offset, rtitcp_message, &first_attribute); |
603 | 0 | attributes_list_offset += attribute_offset; |
604 | 0 | } |
605 | 0 | if (!first_attribute) { |
606 | 0 | proto_item_append_text(rtitcp_message,")"); |
607 | 0 | col_append_str(pinfo->cinfo, COL_INFO, ")"); |
608 | 0 | } |
609 | | /* Now that we have the number of attributes, update the text to show it */ |
610 | 0 | proto_item_set_text(attributes_list, "Attributes list [%d attribute%s", |
611 | 0 | attributes_count, attributes_count > 1 ? "s]" : "]"); |
612 | |
|
613 | 0 | proto_item_append_text(rtitcp_message,", Transaction ID: %s, Len: %d", |
614 | 0 | transaction_id_str, msg_length); |
615 | |
|
616 | 0 | return msg_length + header_length; |
617 | 0 | } |
618 | | |
619 | | /* This function dissects all the control messages found */ |
620 | 0 | static unsigned dissect_rtitcp_control_protocol(proto_tree *rtitcp_tree, tvbuff_t *tvb, packet_info *pinfo) { |
621 | 0 | unsigned offset; |
622 | 0 | uint16_t msg_length; |
623 | 0 | uint32_t tvb_len; |
624 | |
|
625 | 0 | offset = 0; |
626 | 0 | tvb_len = tvb_reported_length(tvb); |
627 | |
|
628 | 0 | while (offset < tvb_len) { |
629 | 0 | msg_length = dissect_control_message(rtitcp_tree, tvb, pinfo, offset); |
630 | 0 | offset += msg_length; |
631 | 0 | } |
632 | |
|
633 | 0 | return offset; |
634 | 0 | } |
635 | | |
636 | | static int dissect_rtitcp_common(tvbuff_t *tvb, packet_info *pinfo, |
637 | 0 | proto_tree *tree, void *data _U_) { |
638 | | |
639 | | /* FORMAT OF THE CONTROL MESSAGE |
640 | | |
641 | | 0...2...........7...............15.............23...............31 |
642 | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
643 | | * | control bytes | RTI TCP message length | |
644 | | * +---------------+---------------+---------------+---------------+ |
645 | | * | RTITCP_MAGIC_NUMBER | |
646 | | * +---------------+---------------+---------------+---------------+ |
647 | | * | control_message_kind | attributes_list_length | |
648 | | * +---------------+---------------+---------------+---------------+ |
649 | | * | RTITCP_CONTROL_MAGIC_COOKIE | |
650 | | * +---------------+---------------+---------------+---------------+ |
651 | | * | | |
652 | | * |- -| |
653 | | * | TRANSACTION_ID | |
654 | | * |- -| |
655 | | * | | |
656 | | * +---------------+---------------+---------------+---------------+ --------------------------------- |
657 | | * | attribute_type | attribute_length .. Repeat | |
658 | | * +---------------+---------------+---------------+---------------+ until | |
659 | | * | ATTRIBUTE (length) | attributes_list_length expires | |
660 | | * +---------------+---------------+---------------+---------------+ --------------------------------*/ |
661 | |
|
662 | 0 | proto_item *ti; |
663 | 0 | proto_tree *rtitcp_tree, *rtitcp_message = NULL; |
664 | 0 | unsigned offset, offset_header; |
665 | 0 | uint16_t rtitcp_msg_length, header_length; |
666 | 0 | uint32_t tvb_len, rtitcp_rtps_msg_length; |
667 | 0 | bool printCRC = false, is_data = false; |
668 | 0 | tvbuff_t *next_tvb; |
669 | 0 | heur_dtbl_entry_t *hdtbl_entry; |
670 | |
|
671 | 0 | offset = 0; |
672 | 0 | tvb_len = tvb_reported_length(tvb); |
673 | | |
674 | | /* From this point, we can consider that this is a RTI TCP message */ |
675 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTI-TCP"); |
676 | |
|
677 | 0 | rtitcp_msg_length = tvb_get_uint16(tvb, offset+2, ENC_BIG_ENDIAN); |
678 | |
|
679 | 0 | ti = proto_tree_add_item(tree, proto_rtitcp, tvb, offset, -1, ENC_NA); |
680 | 0 | rtitcp_tree = proto_item_add_subtree(ti, ett_rtitcp); |
681 | |
|
682 | 0 | offset_header = 0; /* Remember the offset that delimits the header */ |
683 | 0 | header_length = 8; /* the header is 8 bytes length + 8 optional (CRC) */ |
684 | 0 | offset += 2; /* First two bytes are CTRL bytes */ |
685 | 0 | offset += 2; /* rtitcp_msg_length */ |
686 | 0 | offset += 4; /* RTITCP_MAGIC_NUMBER has already been checked */ |
687 | | |
688 | | /* if bytes 8 to 12 are RTITCP_CRC_MAGIC_NUMBER, we got a CRC */ |
689 | 0 | if (tvb_get_ntohl(tvb, offset) == RTITCP_CRC_MAGIC_NUMBER) { |
690 | 0 | printCRC = true; /* To specify later that CRC must be printed */ |
691 | 0 | header_length += 8; /* header increases in 8 bytes */ |
692 | 0 | offset += 8; /* Because of 0xCRC32 + actual CRC (4 bytes) */ |
693 | 0 | } |
694 | 0 | proto_item_set_len(ti, rtitcp_msg_length + header_length); |
695 | | |
696 | | /* At this point, offset is 8 or 16 bytes and we have now data. |
697 | | This data can be RTPS or RTI TCP Signaling messages */ |
698 | 0 | if (tvb_get_ntohl(tvb, offset) == RTPS_MAGIC_NUMBER) { |
699 | | |
700 | | /* IMPORTANT NOTE: We assume always one RTPS message per RTITCP message */ |
701 | | /* If the TCP layer has provided us with garbage at the end of the buffer, |
702 | | process only the length specified by rtitcp_msg_length */ |
703 | 0 | if (tvb_len > (uint32_t)(rtitcp_msg_length + header_length)) { |
704 | 0 | tvb_set_reported_length(tvb, (rtitcp_msg_length + header_length)); |
705 | 0 | } |
706 | | |
707 | | /* When we encapsulate RTPS, packet length is given by the 30 less |
708 | | significant bits of the first four bytes */ |
709 | 0 | rtitcp_rtps_msg_length = tvb_get_uint32(tvb, 0, ENC_BIG_ENDIAN); |
710 | 0 | rtitcp_rtps_msg_length = rtitcp_rtps_msg_length % NUMBER_2E30; |
711 | | /* Add RTI TCP Data Message subtree and print header */ |
712 | 0 | is_data = true; |
713 | 0 | rtitcp_message = print_header(rtitcp_tree, rtitcp_message, tvb, offset_header, |
714 | 0 | rtitcp_rtps_msg_length + header_length, printCRC, is_data); |
715 | |
|
716 | 0 | proto_item_set_text(rtitcp_message,"RTI TCP Data Message, Len: %d", |
717 | 0 | rtitcp_rtps_msg_length); |
718 | | |
719 | | /* Take the payload and call the registered sub-dissectors. So far, RTPS */ |
720 | 0 | next_tvb = tvb_new_subset_remaining(tvb, offset); |
721 | 0 | dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, NULL); |
722 | 0 | return tvb_captured_length(tvb); |
723 | |
|
724 | 0 | } else { |
725 | 0 | return dissect_rtitcp_control_protocol(rtitcp_tree, tvb, pinfo); |
726 | 0 | } |
727 | 0 | } |
728 | | |
729 | | static unsigned get_rtitcp_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, |
730 | 0 | int offset, void * data _U_) { |
731 | 0 | uint16_t plen; |
732 | 0 | uint16_t header_length = 8; |
733 | | /* |
734 | | * Get the length of the RTITCP packet. |
735 | | */ |
736 | 0 | plen = tvb_get_uint16(tvb, offset+2, ENC_BIG_ENDIAN); |
737 | | /* |
738 | | * That length doesn't include the header field itself; add that in. |
739 | | */ |
740 | 0 | if (tvb_get_ntohl(tvb, offset+8) == RTITCP_CRC_MAGIC_NUMBER) |
741 | 0 | header_length += 8; |
742 | | /* We don't expect plen to be greater than 0xfff8 since adding the header |
743 | | * exceeds the size */ |
744 | 0 | if (plen >= 0xfff8) |
745 | 0 | return 1; |
746 | | |
747 | 0 | return plen + header_length; |
748 | 0 | } |
749 | | static int dissect_rtitcp(tvbuff_t *tvb, packet_info *pinfo, |
750 | 2.94k | proto_tree *tree, void *data _U_) { |
751 | | |
752 | 2.94k | bool desegmentation = true; |
753 | | |
754 | 2.94k | if (tvb_captured_length(tvb) < 8) |
755 | 306 | return 0; |
756 | | |
757 | | /* Check if the RTITCP_MAGIC_NUMBER is here */ |
758 | 2.64k | if (tvb_get_ntohl(tvb, 4) != RTITCP_MAGIC_NUMBER) |
759 | 2.64k | return 0; |
760 | | |
761 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
762 | |
|
763 | 0 | tcp_dissect_pdus(tvb, pinfo, tree, desegmentation, RTITCP_MIN_LENGTH, |
764 | 0 | get_rtitcp_pdu_len, dissect_rtitcp_common, data); |
765 | |
|
766 | 0 | return tvb_captured_length(tvb); |
767 | | |
768 | 2.64k | } |
769 | | |
770 | | static bool |
771 | | dissect_rtitcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
772 | 2.94k | { |
773 | 2.94k | return dissect_rtitcp(tvb, pinfo, tree, data) > 0; |
774 | 2.94k | } |
775 | | |
776 | | /* Register the protocol with Wireshark. |
777 | | * |
778 | | * This format is required because a script is used to build the C function that |
779 | | * calls all the protocol registration. |
780 | | */ |
781 | | void |
782 | | proto_register_rtitcp(void) |
783 | 14 | { |
784 | | /* module_t *rtitcp_module; */ |
785 | | /* expert_module_t* expert_rtitcp; */ |
786 | | |
787 | 14 | static hf_register_info hf[] = { |
788 | | |
789 | 14 | { &hf_rtitcp_header_control_byte, { |
790 | 14 | "Control Byte", "rtitcp.header.control_byte", |
791 | 14 | FT_UINT16, BASE_HEX, NULL, 0, |
792 | 14 | NULL, HFILL } |
793 | 14 | }, |
794 | | |
795 | 14 | { &hf_rtitcp_header_message_length, { |
796 | 14 | "Message Length", "rtitcp.header.message_length", |
797 | 14 | FT_UINT24, BASE_DEC, NULL, 0, |
798 | 14 | NULL, HFILL } |
799 | 14 | }, |
800 | | |
801 | 14 | { &hf_rtitcp_header_magic_number, { |
802 | 14 | "Magic Cookie", "rtitcp.header.magic_cookie", |
803 | 14 | FT_UINT32, BASE_HEX, NULL, 0, |
804 | 14 | NULL, HFILL } |
805 | 14 | }, |
806 | | |
807 | 14 | { &hf_rtitcp_crc_magic_cookie, { |
808 | 14 | "CRC Magic Cookie", "rtitcp.header.crc_magic_cookie", |
809 | 14 | FT_UINT32, BASE_HEX, NULL, 0, |
810 | 14 | NULL, HFILL } |
811 | 14 | }, |
812 | | |
813 | 14 | { &hf_rtitcp_control_kind, |
814 | 14 | { "Kind", "rtitcp.control.kind", |
815 | 14 | FT_UINT16, BASE_HEX, VALS(ctrl_message_types_vals), 0, |
816 | 14 | NULL, HFILL } |
817 | 14 | }, |
818 | | |
819 | 14 | { &hf_rtitcp_control_magic_cookie, { |
820 | 14 | "Control Magic Cookie", "rtitcp.control.magic_cookie", |
821 | 14 | FT_UINT32, BASE_HEX, NULL, 0, |
822 | 14 | NULL, HFILL } |
823 | 14 | }, |
824 | | |
825 | 14 | { &hf_rtitcp_control_transaction_id, { |
826 | 14 | "Transaction ID", "rtitcp.control.transaction_id", |
827 | 14 | FT_BYTES, BASE_NONE, NULL, 0, |
828 | 14 | NULL, HFILL } |
829 | 14 | }, |
830 | | |
831 | 14 | { &hf_rtitcp_control_attribute_session_id, { |
832 | 14 | "Session ID", "rtitcp.control.attribute.session_id", |
833 | 14 | FT_BYTES, BASE_NONE, NULL, 0, |
834 | 14 | NULL, HFILL } |
835 | 14 | }, |
836 | | |
837 | 14 | { &hf_rtitcp_control_attribute_type, |
838 | 14 | { "Attribute Type", "rtitcp.control.attribute_type", |
839 | 14 | FT_UINT16, BASE_HEX, VALS(attribute_types_vals), 0, |
840 | 14 | NULL, HFILL } |
841 | 14 | }, |
842 | | |
843 | 14 | { &hf_rtitcp_control_attribute_error_code_value, |
844 | 14 | { "Kind", "rtitcp.control.attribute.error_code", |
845 | 14 | FT_UINT32, BASE_HEX, VALS(error_code_kind_vals), 0, |
846 | 14 | NULL, HFILL } |
847 | 14 | }, |
848 | | |
849 | 14 | { &hf_rtitcp_control_attribute_error_code_description, { |
850 | 14 | "Description", "rtitcp.control.attribute.error_code.description", |
851 | 14 | FT_STRING, BASE_NONE, NULL, 0, |
852 | 14 | NULL, HFILL } |
853 | 14 | }, |
854 | | |
855 | 14 | { &hf_rtitcp_control_attribute_connection_cookie, { |
856 | 14 | "Connection Cookie", "rtitcp.control.attribute.connection_cookie", |
857 | 14 | FT_BYTES, BASE_NONE, NULL, 0, |
858 | 14 | NULL, HFILL } |
859 | 14 | }, |
860 | | |
861 | 14 | { &hf_rtitcp_control_attribute_connection_type, { |
862 | 14 | "Class ID", "rtitcp.control_attribute.connection_type", |
863 | 14 | FT_UINT8, BASE_HEX, VALS(rtitcp_attribute_connection_type_vals), 0, |
864 | 14 | NULL, HFILL } |
865 | 14 | }, |
866 | | |
867 | 14 | { &hf_rtitcp_attributes_list_length, { |
868 | 14 | "Attributes list length", "rtitcp.attributes_list_length", |
869 | 14 | FT_UINT16, BASE_DEC, NULL, 0, |
870 | 14 | NULL, HFILL } |
871 | 14 | }, |
872 | | |
873 | 14 | { &hf_rtitcp_control_attribute_length, { |
874 | 14 | "Attribute Length", "rtitcp.control.attribute.length", |
875 | 14 | FT_UINT16, BASE_DEC, NULL, 0, |
876 | 14 | NULL, HFILL } |
877 | 14 | }, |
878 | | |
879 | 14 | { &hf_rtitcp_control_attribute_port, { |
880 | 14 | "Port", "rtitcp.control.attribute_port", |
881 | 14 | FT_UINT32, BASE_DEC, NULL, 0, |
882 | 14 | NULL, HFILL } |
883 | 14 | }, |
884 | | |
885 | 14 | { &hf_rtitcp_locator_kind, |
886 | 14 | { "Kind", "rtitcp.locator.kind", |
887 | 14 | FT_UINT16, BASE_DEC, VALS(rtitcp_locator_kind_vals), 0, |
888 | 14 | NULL, HFILL } |
889 | 14 | }, |
890 | | |
891 | 14 | { &hf_rtitcp_locator_ipv4, |
892 | 14 | { "Address", "rtitcp.locator.ipv4", |
893 | 14 | FT_IPv4, BASE_NONE, NULL, 0, |
894 | 14 | NULL, HFILL } |
895 | 14 | }, |
896 | | |
897 | 14 | { &hf_rtitcp_locator_port, |
898 | 14 | { "Port", "rtitcp.locator.port", |
899 | 14 | FT_UINT16, BASE_DEC, NULL, 0, |
900 | 14 | NULL, HFILL } |
901 | 14 | }, |
902 | | |
903 | 14 | { &hf_rtitcp_locator_ipv6, |
904 | 14 | { "Address", "rtitcp.locator.ipv6", |
905 | 14 | FT_IPv6, BASE_NONE, NULL, 0, |
906 | 14 | NULL, HFILL } |
907 | 14 | }, |
908 | | |
909 | 14 | { &hf_rtitcp_control_crc_value, |
910 | 14 | { "CRC", "rtitcp.control.crc", |
911 | 14 | FT_UINT32, BASE_HEX, NULL, 0, |
912 | 14 | NULL, HFILL } |
913 | 14 | }, |
914 | | |
915 | 14 | { &hf_rtitcp_response_in, |
916 | 14 | { "Response In", "rtitcp.response_in", |
917 | 14 | FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x0, |
918 | 14 | "The response to this RTITCP request is in this frame", HFILL } |
919 | 14 | }, |
920 | | |
921 | 14 | { &hf_rtitcp_response_to, |
922 | 14 | { "Request In", "rtitcp.response_to", |
923 | 14 | FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0, |
924 | 14 | "This is a response to the RTITCP request in this frame", HFILL } |
925 | 14 | }, |
926 | | |
927 | 14 | { &hf_rtitcp_response_time, |
928 | 14 | { "Response Time", "rtitcp.response_time", |
929 | 14 | FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, |
930 | 14 | "The time between the Request and the Reply", HFILL } |
931 | 14 | } |
932 | 14 | }; |
933 | | |
934 | 14 | static int *ett[] = { |
935 | 14 | &ett_rtitcp, |
936 | 14 | &ett_rtitcp_signalling_protocol, |
937 | 14 | &ett_rtitcp_message, |
938 | 14 | &ett_rtitcp_attributes_list, |
939 | 14 | &ett_rtitcp_attribute |
940 | 14 | }; |
941 | | |
942 | | /* Setup protocol expert items */ |
943 | | /* static ei_register_info ei[] = {}; */ |
944 | | |
945 | | /* Register the protocol name and description */ |
946 | 14 | proto_rtitcp = proto_register_protocol("RTI TCP Transport Protocol", |
947 | 14 | "RTITCP", "rtitcp"); |
948 | | |
949 | 14 | hfi_rtitcp = proto_registrar_get_nth(proto_rtitcp); |
950 | | /* Required function calls to register the header fields and subtrees */ |
951 | 14 | proto_register_field_array(proto_rtitcp, hf, array_length(hf)); |
952 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
953 | | |
954 | | /* Required function calls to register expert items */ |
955 | | /* expert_rtitcp = expert_register_protocol(proto_rtitcp); |
956 | | expert_register_field_array(expert_rtitcp, ei, array_length(ei)); */ |
957 | | |
958 | 14 | register_dissector("rtitcp", dissect_rtitcp, proto_rtitcp); |
959 | 14 | heur_subdissector_list = register_heur_dissector_list_with_description("rtitcp", "RTI TCP signalling message", proto_rtitcp); |
960 | | |
961 | 14 | } |
962 | | |
963 | | /* Simpler form of proto_reg_handoff_rtitcp which can be used if there are |
964 | | * no prefs-dependent registration function calls. */ |
965 | | void |
966 | | proto_reg_handoff_rtitcp(void) |
967 | 14 | { |
968 | 14 | heur_dissector_add("tcp", dissect_rtitcp_heur, "RTI TCP Layer" , "rtitcp", proto_rtitcp, HEURISTIC_ENABLE); |
969 | 14 | } |
970 | | |
971 | | /* |
972 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
973 | | * |
974 | | * Local variables: |
975 | | * c-basic-offset: 4 |
976 | | * tab-width: 8 |
977 | | * indent-tabs-mode: nil |
978 | | * End: |
979 | | * |
980 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
981 | | * :indentSize=4:tabSize=8:noTabs=true: |
982 | | */ |