4 * Routines for Real-Time Publish-Subscribe Protocol (RTPS) dissection
6 * Copyright 2005, Fabrizio Bertocci <fabrizio@rti.com>
7 * Real-Time Innovations, Inc.
8 * 385 Moffett Park Drive
11 * Version 2.1 bug fixes to RTPS_DATA provided by
12 * Twin Oaks Computing, Inc. <contact@twinoakscomputing.com>
13 * 755 Maleta Ln, Ste 203
14 * Castle Rock, CO 80108
18 * Wireshark - Network traffic analyzer
19 * By Gerald Combs <gerald@wireshark.org>
20 * Copyright 1998 Gerald Combs
22 * This program is free software; you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License as published by
24 * the Free Software Foundation; either version 2 of the License, or
25 * (at your option) any later version.
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 * -------------------------------------
38 * This is the RTPS packet dissector for RTPS version 2.x
40 * RTPS protocol was initially developed by Real-Time Innovations, Inc. as wire
41 * protocol for Data Distribution System, and then adopted as a standard by
42 * the Object Management Group (as version 2.0).
44 * Additional information at:
45 * Full OMG DDS Standard Specification:
46 * http://www.omg.org/cgi-bin/doc?ptc/2003-07-07
48 * RTI DDS and RTPS information: http://www.rti.com/resources.html
61 #include <epan/packet.h>
62 #include <epan/addr_resolv.h>
63 #include <epan/prefs.h>
66 #include "packet-rtps2.h"
68 /* Size of the temp buffers used to format various part of the protocol.
69 * Note: Some of those values are bigger than expected. The reason is
70 * because the string buffer can also contains decoded values.
71 * I.e. port size is an integer, but for value 0x0000, it is interpreted
72 * as a string "PORT_INVALID (0x00000000)"
74 #define MAX_FLAG_SIZE (40)
75 #define MAX_GUID_PREFIX_SIZE (128)
76 #define MAX_GUID_SIZE (160)
77 #define MAX_VENDOR_ID_SIZE (128)
78 #define MAX_NTP_TIME_SIZE (128)
79 #define MAX_PORT_SIZE (32)
80 #define MAX_PARAM_SIZE (256)
81 #define MAX_SUMMARY_SIZE (500)
82 #define MAX_LOCATOR_SIZE (200)
83 #define MAX_IPV6_SIZE (100)
84 #define MAX_BITMAP_SIZE (200)
85 #define MAX_LABEL_SIZE (64)
86 #define MAX_IPV4_ADDRESS_SIZE (64)
88 /* Max octets printed on the parameter root for a sequence of octets */
89 #define MAX_SEQ_OCTETS_PRINTED (20)
92 /***************************************************************************/
93 /* Protocol Fields Identifiers */
94 static int proto_rtps = -1;
95 static int hf_rtps_protocol_version = -1;
96 static int hf_rtps_protocol_version_major = -1;
97 static int hf_rtps_protocol_version_minor = -1;
98 static int hf_rtps_vendor_id = -1;
100 static int hf_rtps_domain_id = -1;
101 static int hf_rtps_participant_idx = -1;
102 static int hf_rtps_nature_type = -1;
104 static int hf_rtps_guid_prefix = -1;
105 static int hf_rtps_host_id = -1;
106 static int hf_rtps_app_id = -1;
107 static int hf_rtps_counter = -1;
109 static int hf_rtps_sm_id = -1;
110 static int hf_rtps_sm_flags = -1;
111 static int hf_rtps_sm_octets_to_next_header = -1;
112 static int hf_rtps_sm_guid_prefix = -1;
113 static int hf_rtps_sm_host_id = -1;
114 static int hf_rtps_sm_app_id = -1;
115 static int hf_rtps_sm_instance_id = -1;
116 static int hf_rtps_sm_app_kind = -1;
117 static int hf_rtps_sm_counter = -1;
118 static int hf_rtps_sm_entity_id = -1;
119 static int hf_rtps_sm_entity_id_key = -1;
120 static int hf_rtps_sm_entity_id_kind = -1;
121 static int hf_rtps_sm_rdentity_id = -1;
122 static int hf_rtps_sm_rdentity_id_key = -1;
123 static int hf_rtps_sm_rdentity_id_kind = -1;
124 static int hf_rtps_sm_wrentity_id = -1;
125 static int hf_rtps_sm_wrentity_id_key = -1;
126 static int hf_rtps_sm_wrentity_id_kind = -1;
127 static int hf_rtps_sm_seq_number = -1;
129 static int hf_rtps_parameter_id = -1;
130 static int hf_rtps_parameter_length = -1;
131 static int hf_rtps_param_ntpt = -1;
132 static int hf_rtps_param_ntpt_sec = -1;
133 static int hf_rtps_param_ntpt_fraction = -1;
134 static int hf_rtps_param_topic_name = -1;
135 static int hf_rtps_param_entity_name = -1;
136 static int hf_rtps_param_strength = -1;
137 static int hf_rtps_param_type_name = -1;
138 static int hf_rtps_param_user_data = -1;
139 static int hf_rtps_param_group_data = -1;
140 static int hf_rtps_param_topic_data = -1;
141 static int hf_rtps_param_content_filter_name = -1;
142 static int hf_rtps_param_related_topic_name = -1;
143 static int hf_rtps_param_filter_name = -1;
144 static int hf_rtps_issue_data = -1;
145 static int hf_rtps_param_status_info = -1;
148 /* Subtree identifiers */
149 static gint ett_rtps = -1;
150 static gint ett_rtps_default_mapping = -1;
151 static gint ett_rtps_proto_version = -1;
152 static gint ett_rtps_submessage = -1;
153 static gint ett_rtps_parameter_sequence = -1;
154 static gint ett_rtps_parameter = -1;
155 static gint ett_rtps_flags = -1;
156 static gint ett_rtps_entity = -1;
157 static gint ett_rtps_rdentity = -1;
158 static gint ett_rtps_wrentity = -1;
159 static gint ett_rtps_guid_prefix = -1;
160 static gint ett_rtps_part_message_data = -1;
161 static gint ett_rtps_part_message_guid = -1;
162 static gint ett_rtps_locator_udp_v4 = -1;
163 static gint ett_rtps_locator = -1;
164 static gint ett_rtps_locator_list = -1;
165 static gint ett_rtps_ntp_time = -1;
166 static gint ett_rtps_bitmap = -1;
167 static gint ett_rtps_seq_string = -1;
168 static gint ett_rtps_seq_ulong = -1;
169 static gint ett_rtps_serialized_data = -1;
170 static gint ett_rtps_sample_info_list = -1;
171 static gint ett_rtps_sample_info = -1;
172 static gint ett_rtps_sample_batch_list = -1;
173 static gint ett_rtps_locator_filter_channel = -1;
174 static gint ett_rtps_locator_filter_locator = -1;
176 /***************************************************************************/
177 /* Value-to-String Tables */
178 static const value_string entity_id_vals[] = {
179 { ENTITYID_UNKNOWN, "ENTITYID_UNKNOWN" },
180 { ENTITYID_PARTICIPANT, "ENTITYID_PARTICIPANT" },
181 { ENTITYID_SEDP_BUILTIN_TOPIC_WRITER, "ENTITYID_SEDP_BUILTIN_TOPIC_WRITER" },
182 { ENTITYID_SEDP_BUILTIN_TOPIC_READER, "ENTITYID_SEDP_BUILTIN_TOPIC_READER" },
183 { ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER, "ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER" },
184 { ENTITYID_SEDP_BUILTIN_PUBLICATIONS_READER, "ENTITYID_SEDP_BUILTIN_PUBLICATIONS_READER" },
185 { ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER, "ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER" },
186 { ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_READER, "ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_READER" },
187 { ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER, "ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER" },
188 { ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER, "ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER" },
189 { ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER, "ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER" },
190 { ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER, "ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER" },
192 /* Deprecated Items */
193 { ENTITYID_APPLICATIONS_WRITER, "writerApplications [DEPRECATED]" },
194 { ENTITYID_APPLICATIONS_READER, "readerApplications [DEPRECATED]" },
195 { ENTITYID_CLIENTS_WRITER, "writerClients [DEPRECATED]" },
196 { ENTITYID_CLIENTS_READER, "readerClients [DEPRECATED]" },
197 { ENTITYID_SERVICES_WRITER, "writerServices [DEPRECATED]" },
198 { ENTITYID_SERVICES_READER, "readerServices [DEPRECATED]" },
199 { ENTITYID_MANAGERS_WRITER, "writerManagers [DEPRECATED]" },
200 { ENTITYID_MANAGERS_READER, "readerManagers [DEPRECATED]" },
201 { ENTITYID_APPLICATION_SELF, "applicationSelf [DEPRECATED]" },
202 { ENTITYID_APPLICATION_SELF_WRITER, "writerApplicationSelf [DEPRECATED]" },
203 { ENTITYID_APPLICATION_SELF_READER, "readerApplicationSelf [DEPRECATED]" },
207 static const value_string entity_kind_vals [] = {
208 { ENTITYKIND_APPDEF_UNKNOWN, "Application-defined unknown kind" },
209 { ENTITYKIND_APPDEF_PARTICIPANT, "Application-defined participant" },
210 { ENTITYKIND_APPDEF_WRITER_WITH_KEY, "Application-defined writer (with key)" },
211 { ENTITYKIND_APPDEF_WRITER_NO_KEY, "Application-defined writer (no key)" },
212 { ENTITYKIND_APPDEF_READER_WITH_KEY, "Application-defined reader (with key)" },
213 { ENTITYKIND_APPDEF_READER_NO_KEY, "Application-defined reader (no key)" },
214 { ENTITYKIND_BUILTIN_PARTICIPANT, "Built-in participant" },
215 { ENTITYKIND_BUILTIN_WRITER_WITH_KEY, "Built-in writer (with key)" },
216 { ENTITYKIND_BUILTIN_WRITER_NO_KEY, "Built-in writer (no key)" },
217 { ENTITYKIND_BUILTIN_READER_WITH_KEY, "Built-in reader (with key)" },
218 { ENTITYKIND_BUILTIN_READER_NO_KEY, "Built-in reader (no key)" },
223 static const value_string nature_type_vals[] = {
224 { PORT_METATRAFFIC_UNICAST, "UNICAST_METATRAFFIC"},
225 { PORT_METATRAFFIC_MULTICAST, "MULTICAST_METATRAFFIC"},
226 { PORT_USERTRAFFIC_UNICAST, "UNICAST_USERTRAFFIC"},
227 { PORT_USERTRAFFIC_MULTICAST, "MULTICAST_USERTRAFFIC"},
232 static const value_string app_kind_vals[] = {
233 { APPKIND_UNKNOWN, "APPKIND_UNKNOWN" },
234 { APPKIND_MANAGED_APPLICATION, "ManagedApplication" },
235 { APPKIND_MANAGER, "Manager" },
240 static const value_string submessage_id_vals[] = {
241 { SUBMESSAGE_PAD, "PAD" },
242 { SUBMESSAGE_RTPS_DATA, "DATA" },
243 { SUBMESSAGE_RTPS_DATA_FRAG, "DATA_FRAG" },
244 { SUBMESSAGE_RTPS_DATA_BATCH, "DATA_BATCH" },
245 { SUBMESSAGE_ACKNACK, "ACKNACK" },
246 { SUBMESSAGE_HEARTBEAT, "HEARTBEAT" },
247 { SUBMESSAGE_GAP, "GAP" },
248 { SUBMESSAGE_INFO_TS, "INFO_TS" },
249 { SUBMESSAGE_INFO_SRC, "INFO_SRC" },
250 { SUBMESSAGE_INFO_REPLY_IP4, "INFO_REPLY_IP4" },
251 { SUBMESSAGE_INFO_DST, "INFO_DST" },
252 { SUBMESSAGE_INFO_REPLY, "INFO_REPLY" },
253 { SUBMESSAGE_NACK_FRAG, "NACK_FRAG" },
254 { SUBMESSAGE_HEARTBEAT_FRAG, "HEARTBEAT_FRAG" },
255 { SUBMESSAGE_ACKNACK_BATCH, "ACKNACK_BATCH" },
256 { SUBMESSAGE_HEARTBEAT_BATCH, "HEARTBEAT_BATCH" },
257 { SUBMESSAGE_ACKNACK_SESSION, "ACKNACK_SESSION" },
258 { SUBMESSAGE_HEARTBEAT_SESSION, "HEARTBEAT_SESSION" },
259 { SUBMESSAGE_RTPS_DATA_SESSION, "DATA_SESSION" },
260 /* Deprecated submessages */
261 { SUBMESSAGE_DATA, "DATA_deprecated" },
262 { SUBMESSAGE_NOKEY_DATA, "NOKEY_DATA_deprecated" },
263 { SUBMESSAGE_DATA_FRAG, "DATA_FRAG_deprecated" },
264 { SUBMESSAGE_NOKEY_DATA_FRAG, "NOKEY_DATA_FRAG_deprecated" },
268 static const value_string typecode_kind_vals[] = {
269 { RTI_CDR_TK_NULL, "(unknown)" },
270 { RTI_CDR_TK_SHORT, "short" },
271 { RTI_CDR_TK_LONG, "long" },
272 { RTI_CDR_TK_USHORT, "unsigned short" },
273 { RTI_CDR_TK_ULONG, "unsigned long" },
274 { RTI_CDR_TK_FLOAT, "float" },
275 { RTI_CDR_TK_DOUBLE, "double" },
276 { RTI_CDR_TK_BOOLEAN, "boolean" },
277 { RTI_CDR_TK_CHAR, "char" },
278 { RTI_CDR_TK_OCTET, "octet" },
279 { RTI_CDR_TK_STRUCT, "struct" },
280 { RTI_CDR_TK_UNION, "union" },
281 { RTI_CDR_TK_ENUM, "enum" },
282 { RTI_CDR_TK_STRING, "string" },
283 { RTI_CDR_TK_SEQUENCE, "sequence" },
284 { RTI_CDR_TK_ARRAY, "array" },
285 { RTI_CDR_TK_ALIAS, "alias" },
286 { RTI_CDR_TK_LONGLONG, "long long" },
287 { RTI_CDR_TK_ULONGLONG, "unsigned long long" },
288 { RTI_CDR_TK_LONGDOUBLE, "long double" },
289 { RTI_CDR_TK_WCHAR, "wchar" },
290 { RTI_CDR_TK_WSTRING, "wstring" },
294 static const value_string parameter_id_vals[] = {
295 { PID_PAD, "PID_PAD" },
296 { PID_SENTINEL, "PID_SENTINEL" },
297 { PID_PARTICIPANT_LEASE_DURATION, "PID_PARTICIPANT_LEASE_DURATION" },
298 { PID_TIME_BASED_FILTER, "PID_TIME_BASED_FILTER" },
299 { PID_TOPIC_NAME, "PID_TOPIC_NAME" },
300 { PID_OWNERSHIP_STRENGTH, "PID_OWNERSHIP_STRENGTH" },
301 { PID_TYPE_NAME, "PID_TYPE_NAME" },
302 { PID_METATRAFFIC_MULTICAST_IPADDRESS,"PID_METATRAFFIC_MULTICAST_IPADDRESS"},
303 { PID_DEFAULT_UNICAST_IPADDRESS, "PID_DEFAULT_UNICAST_IPADDRESS" },
304 { PID_METATRAFFIC_UNICAST_PORT, "PID_METATRAFFIC_UNICAST_PORT" },
305 { PID_DEFAULT_UNICAST_PORT, "PID_DEFAULT_UNICAST_PORT" },
306 { PID_MULTICAST_IPADDRESS, "PID_MULTICAST_IPADDRESS" },
307 { PID_PROTOCOL_VERSION, "PID_PROTOCOL_VERSION" },
308 { PID_VENDOR_ID, "PID_VENDOR_ID" },
309 { PID_RELIABILITY, "PID_RELIABILITY" },
310 { PID_LIVELINESS, "PID_LIVELINESS" },
311 { PID_DURABILITY, "PID_DURABILITY" },
312 { PID_DURABILITY_SERVICE, "PID_DURABILITY_SERVICE" },
313 { PID_OWNERSHIP, "PID_OWNERSHIP" },
314 { PID_PRESENTATION, "PID_PRESENTATION" },
315 { PID_DEADLINE, "PID_DEADLINE" },
316 { PID_DESTINATION_ORDER, "PID_DESTINATION_ORDER" },
317 { PID_LATENCY_BUDGET, "PID_LATENCY_BUDGET" },
318 { PID_PARTITION, "PID_PARTITION" },
319 { PID_LIFESPAN, "PID_LIFESPAN" },
320 { PID_USER_DATA, "PID_USER_DATA" },
321 { PID_GROUP_DATA, "PID_GROUP_DATA" },
322 { PID_TOPIC_DATA, "PID_TOPIC_DATA" },
323 { PID_UNICAST_LOCATOR, "PID_UNICAST_LOCATOR" },
324 { PID_MULTICAST_LOCATOR, "PID_MULTICAST_LOCATOR" },
325 { PID_DEFAULT_UNICAST_LOCATOR, "PID_DEFAULT_UNICAST_LOCATOR" },
326 { PID_METATRAFFIC_UNICAST_LOCATOR, "PID_METATRAFFIC_UNICAST_LOCATOR " },
327 { PID_METATRAFFIC_MULTICAST_LOCATOR, "PID_METATRAFFIC_MULTICAST_LOCATOR" },
328 { PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT, "PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT" },
329 { PID_CONTENT_FILTER_PROPERTY, "PID_CONTENT_FILTER_PROPERTY" },
330 { PID_PROPERTY_LIST, "PID_PROPERTY_LIST" },
331 { PID_HISTORY, "PID_HISTORY" },
332 { PID_RESOURCE_LIMIT, "PID_RESOURCE_LIMIT" },
333 { PID_EXPECTS_INLINE_QOS, "PID_EXPECTS_INLINE_QOS" },
334 { PID_PARTICIPANT_BUILTIN_ENDPOINTS, "PID_PARTICIPANT_BUILTIN_ENDPOINTS" },
335 { PID_METATRAFFIC_UNICAST_IPADDRESS, "PID_METATRAFFIC_UNICAST_IPADDRESS" },
336 { PID_METATRAFFIC_MULTICAST_PORT, "PID_METATRAFFIC_MULTICAST_PORT" },
337 { PID_DEFAULT_MULTICAST_LOCATOR, "PID_DEFAULT_MULTICAST_LOCATOR" },
338 { PID_TRANSPORT_PRIORITY, "PID_TRANSPORT_PRIORITY" },
339 { PID_PARTICIPANT_GUID, "PID_PARTICIPANT_GUID" },
340 { PID_PARTICIPANT_ENTITY_ID, "PID_PARTICIPANT_ENTITY_ID" },
341 { PID_GROUP_GUID, "PID_GROUP_GUID" },
342 { PID_GROUP_ENTITY_ID, "PID_GROUP_ENTITY_ID" },
343 { PID_CONTENT_FILTER_INFO, "PID_CONTENT_FILTER_INFO" },
344 { PID_COHERENT_SET, "PID_COHERENT_SET" },
345 { PID_DIRECTED_WRITE, "PID_DIRECTED_WRITE" },
346 { PID_BUILTIN_ENDPOINT_SET, "PID_BUILTIN_ENDPOINT_SET" },
347 { PID_PROPERTY_LIST_OLD, "PID_PROPERTY_LIST" },
348 { PID_ENDPOINT_GUID, "PID_ENDPOINT_GUID" },
349 { PID_TYPE_MAX_SIZE_SERIALIZED, "PID_TYPE_MAX_SIZE_SERIALIZED" },
350 { PID_ORIGINAL_WRITER_INFO, "PID_ORIGINAL_WRITER_INFO" },
351 { PID_ENTITY_NAME, "PID_ENTITY_NAME" },
352 { PID_KEY_HASH, "PID_KEY_HASH" },
353 { PID_STATUS_INFO, "PID_STATUS_INFO" },
355 /* Vendor specific: RTI */
356 { PID_PRODUCT_VERSION, "PID_PRODUCT_VERSION" },
357 { PID_PLUGIN_PROMISCUITY_KIND, "PID_PLUGIN_PROMISCUITY_KIND" },
358 { PID_ENTITY_VIRTUAL_GUID, "PID_ENTITY_VIRTUAL_GUID" },
359 { PID_SERVICE_KIND, "PID_SERVICE_KIND" },
360 { PID_TYPECODE, "PID_TYPECODE" },
361 { PID_DISABLE_POSITIVE_ACKS, "PID_DISABLE_POSITIVE_ACKS" },
362 { PID_LOCATOR_FILTER_LIST, "PID_LOCATOR_FILTER_LIST" },
364 /* The following PID are deprecated */
365 { PID_DEADLINE_OFFERED, "PID_DEADLINE_OFFERED [deprecated]" },
366 { PID_PERSISTENCE, "PID_PERSISTENCE [deprecated]" },
367 { PID_TYPE_CHECKSUM, "PID_TYPE_CHECKSUM [deprecated]" },
368 { PID_TYPE2_NAME, "PID_TYPE2_NAME [deprecated]" },
369 { PID_TYPE2_CHECKSUM, "PID_TYPE2_CHECKSUM [deprecated]" },
370 { PID_IS_RELIABLE, "PID_IS_RELIABLE [deprecated]" },
371 { PID_EXPECTS_ACK, "PID_EXPECTS_ACK [deprecated]" },
372 { PID_MANAGER_KEY, "PID_MANAGER_KEY [deprecated]" },
373 { PID_SEND_QUEUE_SIZE, "PID_SEND_QUEUE_SIZE [deprecated]" },
374 { PID_RELIABILITY_ENABLED, "PID_RELIABILITY_ENABLED [deprecated]" },
375 { PID_VARGAPPS_SEQUENCE_NUMBER_LAST, "PID_VARGAPPS_SEQUENCE_NUMBER_LAST [deprecated]" },
376 { PID_RECV_QUEUE_SIZE, "PID_RECV_QUEUE_SIZE [deprecated]" },
377 { PID_RELIABILITY_OFFERED, "PID_RELIABILITY_OFFERED [deprecated]" },
378 { PID_LIVELINESS_OFFERED, "PID_LIVELINESS_OFFERED [deprecated]" },
379 { PID_PRESENTATION_OFFERED, "PID_PRESENTATION_OFFERED [deprecated]" },
380 { PID_OWNERSHIP_OFFERED, "PID_OWNERSHIP_OFFERED [deprecated]" },
381 { PID_DESTINATION_ORDER_OFFERED, "PID_DESTINATION_ORDER_OFFERED [deprecated]" },
382 { PID_LATENCY_BUDGET_OFFERED, "PID_LATENCY_BUDGET_OFFERED [deprecated]" },
383 { PID_PARTITION_OFFERED, "PID_PARTITION_OFFERED [deprecated]" },
387 static const value_string liveliness_qos_vals[] = {
388 { LIVELINESS_AUTOMATIC, "AUTOMATIC_LIVELINESS_QOS" },
389 { LIVELINESS_BY_PARTICIPANT, "MANUAL_BY_PARTICIPANT_LIVELINESS_QOS" },
390 { LIVELINESS_BY_TOPIC, "MANUAL_BY_TOPIC_LIVELINESS_QOS" },
394 static const value_string durability_qos_vals[] = {
395 { DURABILITY_VOLATILE, "VOLATILE_DURABILITY_QOS" },
396 { DURABILITY_TRANSIENT_LOCAL, "TRANSIENT_LOCAL_DURABILITY_QOS" },
397 { DURABILITY_TRANSIENT, "TRANSIENT_DURABILITY_QOS" },
398 { DURABILITY_PERSISTENT, "PERSISTENT_DURABILITY_QOS" },
402 static const value_string ownership_qos_vals[] = {
403 { OWNERSHIP_SHARED, "SHARED_OWNERSHIP_QOS" },
404 { OWNERSHIP_EXCLUSIVE, "EXCLUSIVE_OWNERSHIP_QOS" },
408 static const value_string presentation_qos_vals[] = {
409 { PRESENTATION_INSTANCE, "INSTANCE_PRESENTATION_QOS" },
410 { PRESENTATION_TOPIC, "TOPIC_PRESENTATION_QOS" },
411 { PRESENTATION_GROUP, "GROUP_PRESENTATION_QOS" },
415 static const value_string history_qos_vals[] = {
416 { HISTORY_KIND_KEEP_LAST, "KEEP_LAST_HISTORY_QOS" },
417 { HISTORY_KIND_KEEP_ALL, "KEEP_ALL_HISTORY_QOS" },
421 static const value_string reliability_qos_vals[] = {
422 { RELIABILITY_BEST_EFFORT, "BEST_EFFORT_RELIABILITY_QOS" },
423 { RELIABILITY_RELIABLE, "RELIABLE_RELIABILITY_QOS" },
427 static const value_string destination_order_qos_vals[] = {
428 { BY_RECEPTION_TIMESTAMP, "BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS" },
429 { BY_SOURCE_TIMESTAMP, "BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS" },
434 static const value_string encapsulation_id_vals[] = {
435 { ENCAPSULATION_CDR_BE, "CDR_BE" },
436 { ENCAPSULATION_CDR_LE, "CDR_LE" },
437 { ENCAPSULATION_PL_CDR_BE, "PL_CDR_BE" },
438 { ENCAPSULATION_PL_CDR_LE, "PL_CDR_LE" },
442 static const value_string plugin_promiscuity_kind_vals[] = {
443 { 0x0001, "MATCHING_REMOTE_ENTITIES_PROMISCUITY" },
444 { 0xffff, "ALL_REMOTE_ENTITIES_PROMISCUITY" },
448 static const value_string service_kind_vals[] = {
449 { 0x00000000, "NO_SERVICE_QOS" },
450 { 0x00000001, "PERSISTENCE_SERVICE_QOS" },
454 static const value_string participant_message_data_kind [] = {
455 { PARTICIPANT_MESSAGE_DATA_KIND_UNKNOWN, "PARTICIPANT_MESSAGE_DATA_KIND_UNKNOWN" },
456 { PARTICIPANT_MESSAGE_DATA_KIND_AUTOMATIC_LIVELINESS_UPDATE, "PARTICIPANT_MESSAGE_DATA_KIND_AUTOMATIC_LIVELINESS_UPDATE" },
457 { PARTICIPANT_MESSAGE_DATA_KIND_MANUAL_LIVELINESS_UPDATE, "PARTICIPANT_MESSAGE_DATA_KIND_MANUAL_LIVELINESS_UPDATE" },
463 /* Flag Decoding defintions ***********************************************/
464 struct Flag_definition {
466 const char *description;
469 #define RESERVEDFLAG_CHAR ('_')
470 #define RESERVEDFLAG_STRING ("reserved bit")
472 static const struct Flag_definition PAD_FLAGS[] = {
473 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
474 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
475 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
476 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 4 */
477 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 3 */
478 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 2 */
479 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 1 */
480 { 'E', "Endianness bit" } /* Bit 0 */
483 static const struct Flag_definition DATA_FLAGS[] = {
484 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
485 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
486 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
487 { 'I', "Status info flag" }, /* Bit 4 */
488 { 'H', "Hash key flag" }, /* Bit 3 */
489 { 'D', "Data present" }, /* Bit 2 */
490 { 'Q', "Inline QoS" }, /* Bit 1 */
491 { 'E', "Endianness bit" } /* Bit 0 */
494 static const struct Flag_definition NOKEY_DATA_FLAGS[] = {
495 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
496 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
497 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
498 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 4 */
499 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 3 */
500 { 'H', "Key Hash" }, /* Bit 2 */
501 { 'Q', "Inline QoS" }, /* Bit 1 */
502 { 'E', "Endianness bit" } /* Bit 0 */
505 static const struct Flag_definition ACKNACK_FLAGS[] = {
506 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
507 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
508 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
509 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 4 */
510 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 3 */
511 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 2 */
512 { 'F', "Final flag" }, /* Bit 1 */
513 { 'E', "Endianness bit" } /* Bit 0 */
516 static const struct Flag_definition GAP_FLAGS[] = {
517 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
518 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
519 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
520 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 4 */
521 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 3 */
522 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 2 */
523 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 1 */
524 { 'E', "Endianness bit" } /* Bit 0 */
527 static const struct Flag_definition HEARTBEAT_FLAGS[] = {
528 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
529 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
530 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
531 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 4 */
532 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 3 */
533 { 'L', "Liveliness flag" }, /* Bit 2 */
534 { 'F', "Final flag" }, /* Bit 1 */
535 { 'E', "Endianness bit" } /* Bit 0 */
538 static const struct Flag_definition HEARTBEAT_BATCH_FLAGS[] = {
539 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
540 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
541 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
542 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 4 */
543 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 3 */
544 { 'L', "Liveliness flag" }, /* Bit 2 */
545 { 'F', "Final flag" }, /* Bit 1 */
546 { 'E', "Endianness bit" } /* Bit 0 */
549 static const struct Flag_definition INFO_TS_FLAGS[] = {
550 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
551 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
552 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
553 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 4 */
554 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 3 */
555 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 2 */
556 { 'I', "Invalidate flag" }, /* Bit 1 */
557 { 'E', "Endianness bit" } /* Bit 0 */
560 static const struct Flag_definition INFO_SRC_FLAGS[] = {
561 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
562 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
563 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
564 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 4 */
565 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 3 */
566 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 2 */
567 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 1 */
568 { 'E', "Endianness bit" } /* Bit 0 */
571 static const struct Flag_definition INFO_REPLY_IP4_FLAGS[] = {
572 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
573 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
574 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
575 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 4 */
576 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 3 */
577 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 2 */
578 { 'M', "Multicast flag" }, /* Bit 1 */
579 { 'E', "Endianness bit" } /* Bit 0 */
582 static const struct Flag_definition INFO_DST_FLAGS[] = {
583 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
584 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
585 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
586 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 4 */
587 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 3 */
588 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 2 */
589 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 1 */
590 { 'E', "Endianness bit" } /* Bit 0 */
593 static const struct Flag_definition INFO_REPLY_FLAGS[] = {
594 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
595 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
596 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
597 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 4 */
598 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 3 */
599 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 2 */
600 { 'M', "Multicast flag" }, /* Bit 1 */
601 { 'E', "Endianness bit" } /* Bit 0 */
604 static const struct Flag_definition NOKEY_DATA_FRAG_FLAGS[] = {
605 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
606 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
607 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
608 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 4 */
609 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 3 */
610 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 2 */
611 { 'Q', "Inline QoS" }, /* Bit 1 */
612 { 'E', "Endianness bit" } /* Bit 0 */
615 static const struct Flag_definition HEARTBEAT_FRAG_FLAGS[] = {
616 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
617 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
618 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
619 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 4 */
620 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 3 */
621 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 2 */
622 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 1 */
623 { 'E', "Endianness bit" } /* Bit 0 */
626 static const struct Flag_definition NACK_FLAGS[] = {
627 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
628 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
629 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
630 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 4 */
631 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 3 */
632 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 2 */
633 { 'F', "Final flag" }, /* Bit 1 */
634 { 'E', "Endianness bit" } /* Bit 0 */
637 static const struct Flag_definition DATA_FRAG_FLAGS[] = {
638 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
639 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
640 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
641 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 4 */
642 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 3 */
643 { 'H', "Hash key flag" }, /* Bit 2 */
644 { 'Q', "Inline QoS" }, /* Bit 1 */
645 { 'E', "Endianness bit" } /* Bit 0 */
648 static const struct Flag_definition NACK_FRAG_FLAGS[] = {
649 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
650 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
651 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
652 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 4 */
653 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 3 */
654 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 2 */
655 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 1 */
656 { 'E', "Endianness bit" } /* Bit 0 */
659 static const struct Flag_definition RTPS_DATA_FLAGS[] = {
660 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
661 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
662 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
663 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 4 */
664 { 'K', "Serialized Key" }, /* Bit 3 */
665 { 'D', "Data present" }, /* Bit 2 */
666 { 'Q', "Inline QoS" }, /* Bit 1 */
667 { 'E', "Endianness bit" } /* Bit 0 */
670 static const struct Flag_definition RTPS_DATA_FRAG_FLAGS[] = {
671 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
672 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
673 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
674 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 4 */
675 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 3 */
676 { 'K', "Serialized Key" }, /* Bit 2 */
677 { 'Q', "Inline QoS" }, /* Bit 1 */
678 { 'E', "Endianness bit" } /* Bit 0 */
681 static const struct Flag_definition RTPS_DATA_BATCH_FLAGS[] = {
682 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
683 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
684 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
685 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 4 */
686 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 3 */
687 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 2 */
688 { 'Q', "Inline QoS" }, /* Bit 1 */
689 { 'E', "Endianness bit" } /* Bit 0 */
692 static const struct Flag_definition RTPS_SAMPLE_INFO_FLAGS16[] = {
693 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 15 */
694 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 14 */
695 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 13 */
696 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 12 */
697 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 11 */
698 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 10 */
699 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 9 */
700 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 8 */
701 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
702 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
703 { 'K', "Serialized Key" }, /* Bit 5 */
704 { 'I', "Invalid sample" }, /* Bit 4 */
705 { 'D', "Data present" }, /* Bit 3 */
706 { 'O', "OffsetSN present" }, /* Bit 2 */
707 { 'Q', "Inline QoS" }, /* Bit 1 */
708 { 'T', "Timestamp present" } /* Bit 0 */
712 /***************************************************************************/
718 /***************************************************************************
719 * Function prototypes
720 * ~~~~~~~~~~~~~~~~~~~
723 /* Utility to add elements to the protocol tree */
724 static void rtps_util_format_ipv6(guint8 *, guint8 *, gint);
725 static void rtps_util_add_protocol_version(proto_tree *, tvbuff_t *, gint);
726 static void rtps_util_add_vendor_id(proto_tree *, tvbuff_t *,
727 gint, guint8 *, gint);
728 static void rtps_util_add_locator_t(proto_tree *, tvbuff_t *,
729 gint, int, const guint8 *, guint8 *, gint);
730 static int rtps_util_add_locator_list(proto_tree *, tvbuff_t *,
731 gint, const guint8 *, int);
732 static void rtps_util_add_ipv4_address_t(proto_tree *, tvbuff_t *,
733 gint, int, const guint8 *, guint8 *, gint);
734 static void rtps_util_add_locator_udp_v4(proto_tree *, tvbuff_t *,
735 gint, const guint8 *, int);
736 static void rtps_util_add_guid_prefix(proto_tree *, tvbuff_t *,
737 gint, int, int, int, int, const guint8 *,
739 static void rtps_util_add_entity_id(proto_tree *, tvbuff_t *,
740 gint, int, int, int, int, const char *, guint32 *);
741 static void rtps_util_add_generic_entity_id(proto_tree *, tvbuff_t *,
744 static void rtps_util_add_generic_guid(proto_tree *, tvbuff_t *,
745 gint, const char *, guint8 *, gint);
746 static guint64 rtps_util_add_seq_number(proto_tree *, tvbuff_t *,
747 gint, int, const char *);
748 static void rtps_util_add_ntp_time(proto_tree *, tvbuff_t *,
749 gint, int, const char *, guint8 *, gint);
750 static gint rtps_util_add_string(proto_tree *, tvbuff_t *,
751 gint, int, int, const guint8 *, guint8 *, size_t);
752 static guint32 rtps_util_add_long(proto_tree *, tvbuff_t *,
753 gint, int, int, gboolean, gboolean, const char *,
755 static guint16 rtps_util_add_short(proto_tree *, tvbuff_t *,
756 gint, int, int, gboolean, gboolean, const char *,
758 static void rtps_util_add_port(proto_tree *, tvbuff_t *,
759 gint, int, char *, guint8 *, gint);
760 static void rtps_util_add_boolean(proto_tree *, tvbuff_t *,
761 gint, char *, guint8 *, size_t);
762 static void rtps_util_add_durability_service_qos(proto_tree *, tvbuff_t *,
763 gint, int, guint8 *, gint);
764 static void rtps_util_add_liveliness_qos(proto_tree *, tvbuff_t *,
765 gint, int, guint8 *, gint);
766 static void rtps_util_add_kind_qos(proto_tree *, tvbuff_t *,
767 gint, int, char *, const value_string *, guint8 *, size_t);
768 static gint rtps_util_add_seq_string(proto_tree *, tvbuff_t *,
769 gint, int, int, char *, guint8 *, gint);
770 static void rtps_util_add_seq_octets(proto_tree *, tvbuff_t *,
771 gint, int, int, int, guint8 *, gint);
772 static int rtps_util_add_bitmap(proto_tree *, tvbuff_t *,
773 gint, int, const char *);
774 static int rtps_util_add_fragment_number_set(proto_tree *, tvbuff_t *,
775 gint, int, const char *, gint);
776 static void rtps_util_decode_flags(proto_tree *, tvbuff_t *,
777 gint, guint8, const struct Flag_definition *);
778 static void rtps_util_decode_flags_16bit(proto_tree *, tvbuff_t *,
779 gint, guint16, const struct Flag_definition *);
780 static gint rtps_util_add_seq_ulong(proto_tree *, tvbuff_t *,
781 gint, int, int, int, int, char *);
782 static void rtps_util_add_extra_flags(proto_tree *, tvbuff_t *,
785 /* The data (payload) dissector */
786 static void dissect_serialized_data(proto_tree *, tvbuff_t *,
787 gint, int, const char *, guint16 vendor_id);
789 static void dissect_octet_seq(proto_tree *, tvbuff_t *,
792 /* The data (payload) dissector for parameter sequences */
793 static gint dissect_parameter_sequence(proto_tree *, tvbuff_t *,
794 gint, int, int, const char *, guint32 *, guint16 vendor_id);
799 /* Sub-message dissector functions */
800 #define DECLARE_DISSECTOR_SUBMESSAGE(sm) \
801 static void dissect_## sm (tvbuff_t *tvb, gint offset, guint8 flags, \
802 gboolean little_endian, int next_submsg_offset, \
803 proto_tree *rtps_submessage_tree, \
804 char *info_summary_text, guint16 vendor_id)
805 DECLARE_DISSECTOR_SUBMESSAGE(PAD);
806 DECLARE_DISSECTOR_SUBMESSAGE(DATA);
807 DECLARE_DISSECTOR_SUBMESSAGE(DATA_FRAG);
808 DECLARE_DISSECTOR_SUBMESSAGE(NOKEY_DATA);
809 DECLARE_DISSECTOR_SUBMESSAGE(NOKEY_DATA_FRAG);
810 DECLARE_DISSECTOR_SUBMESSAGE(NACK_FRAG);
811 DECLARE_DISSECTOR_SUBMESSAGE(ACKNACK);
812 DECLARE_DISSECTOR_SUBMESSAGE(HEARTBEAT);
813 DECLARE_DISSECTOR_SUBMESSAGE(HEARTBEAT_FRAG);
814 DECLARE_DISSECTOR_SUBMESSAGE(GAP);
815 DECLARE_DISSECTOR_SUBMESSAGE(INFO_TS);
816 DECLARE_DISSECTOR_SUBMESSAGE(INFO_SRC);
817 DECLARE_DISSECTOR_SUBMESSAGE(INFO_REPLY_IP4);
818 DECLARE_DISSECTOR_SUBMESSAGE(INFO_DST);
819 DECLARE_DISSECTOR_SUBMESSAGE(INFO_REPLY);
820 DECLARE_DISSECTOR_SUBMESSAGE(RTPS_DATA_FRAG);
821 DECLARE_DISSECTOR_SUBMESSAGE(RTPS_DATA_BATCH);
822 DECLARE_DISSECTOR_SUBMESSAGE(HEARTBEAT_BATCH);
823 /* The RTPS_DATA has an extra parameter, can't use the macro... */
824 static void dissect_RTPS_DATA(tvbuff_t *, gint, guint8, gboolean, int,
825 proto_tree *, char *, guint16, int);
826 #undef DECLARE_DISSECTOR_SUBMESSAGE
828 /* The main packet dissector */
829 static gboolean dissect_rtps(tvbuff_t *, packet_info *, proto_tree *);
832 /***************************************************************************/
834 /***************************************************************************/
835 #define NEXT_guint16(tvb, offset, le) \
836 (le ? tvb_get_letohs(tvb, offset) : tvb_get_ntohs(tvb, offset))
838 #define NEXT_guint32(tvb, offset, le) \
839 (le ? tvb_get_letohl(tvb, offset) : tvb_get_ntohl(tvb, offset))
842 /***************************************************************************/
843 /* Global variables controlled by Wireshark preference panel */
844 /***************************************************************************/
845 static guint rtps_max_batch_samples_dissected = 16;
848 /* *********************************************************************** */
849 /* Appends a submessage description to the info summary text
851 static void info_summary_append(char *summaryText, int submessageId, const char * extra_text) {
852 gint len = (gint) strlen(summaryText);
853 if (extra_text == NULL) {
856 if (summaryText[0] != '\0') {
857 g_strlcat(summaryText, ", ", MAX_SUMMARY_SIZE-len-1);
860 g_snprintf(summaryText + len,
861 MAX_SUMMARY_SIZE - len,
863 val_to_str(submessageId, submessage_id_vals, "Unknown[%02x]"),
867 /* *********************************************************************** */
868 /* Appends a submessage description to the info summary text, with
869 * extra formatting for those submessages that has a status info
871 static void info_summary_append_ex(char *info_summary_text,
874 guint32 status_info) {
876 /* Defines the extra information associated to the writer involved in
879 * Format: [?Ptwrpm]\(u?d?\)
881 * First letter table:
883 * writerEntityId value | Letter
884 * ---------------------------------------------------+--------------
885 * ENTITYID_UNKNOWN | ?
886 * ENTITYID_PARTICIPANT | P
887 * ENTITYID_SEDP_BUILTIN_TOPIC_WRITER | t
888 * ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER | w
889 * ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER | r
890 * ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER | p
891 * ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER | m
893 * The letter is followed by:
894 * status_info &1 | status_info & 2 | Text
895 * ---------------+-----------------------+--------------
896 * status_info not defined in inlineQos | [?]
903 char buffer[10] = "(?[??])";
905 if (writer_id == ENTITYID_PARTICIPANT)
907 else if (writer_id == ENTITYID_SEDP_BUILTIN_TOPIC_WRITER)
909 else if (writer_id == ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER)
911 else if (writer_id == ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER)
913 else if (writer_id == ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER)
915 else if (writer_id == ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER)
918 /* Unknown writer ID, don't format anything */
919 info_summary_append(info_summary_text, submessageId, NULL);
923 switch(status_info) {
924 case 0: buffer[3] = '_'; buffer[4] = '_'; break;
925 case 1: buffer[3] = '_'; buffer[4] = 'D'; break;
926 case 2: buffer[3] = 'U'; buffer[4] = '_'; break;
927 case 3: buffer[3] = 'U'; buffer[4] = 'D'; break;
928 default: /* Unknown status info, omit it */
932 info_summary_append(info_summary_text, submessageId, buffer);
938 /* *********************************************************************** */
939 /* Format the given address (16 octets) as an IPv6 address
941 static void rtps_util_format_ipv6(guint8 *addr,
945 guint8 temp[5]; /* Contains a 4-digit hex value */
948 for (i = 0; i < 16; i+=2) {
949 /* Unfortunately %x is the same thing as %02x all the time... sigh */
950 g_snprintf(temp, 5, "%02x%02x", addr[i], addr[i+1]);
951 if (temp[0] == '0') {
952 if (temp[1] == '0') {
953 if (temp[2] == '0') {
954 g_strlcat(buffer, &temp[3], buffer_size);
956 g_strlcat(buffer, &temp[2], buffer_size);
959 g_strlcat(buffer, &temp[1], buffer_size);
962 g_strlcat(buffer, temp, buffer_size);
965 g_strlcat(buffer, ":", buffer_size);
973 /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
975 * In general those utility functions (they all starts with 'rtps_util')
976 * are used to dissect some part of a submessage.
977 * They take as first parameter the proto_tree.
978 * Now, the proto_tree can be NULL if the dissector is invoked without
980 * Sometimes those functions they also return some value (as result of
982 * At the price of optimizing the code, each function MUST tollerate
984 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
989 /* *********************************************************************** */
990 static void rtps_util_add_extra_flags(proto_tree *tree,
995 guint16 flags = NEXT_guint16(tvb, offset, 0); /* Always big endian */
996 guint8 temp_buffer[20];
998 for (i = 0; i < 16; ++i) {
999 temp_buffer[i] = ((flags & (1 << (15-i))) != 0) ? '1' : '0';
1001 temp_buffer[16] = '\0';
1003 proto_tree_add_text(tree,
1013 /* *********************************************************************** */
1014 static void rtps_util_add_protocol_version(proto_tree *tree,
1019 proto_tree * version_tree;
1023 major = tvb_get_guint8(tvb, offset);
1024 minor = tvb_get_guint8(tvb, offset+1);
1026 ti = proto_tree_add_none_format(tree,
1027 hf_rtps_protocol_version,
1031 "Protocol version: %d.%d",
1032 tvb_get_guint8(tvb, offset),
1033 tvb_get_guint8(tvb, offset+1));
1034 version_tree = proto_item_add_subtree(ti,
1035 ett_rtps_proto_version);
1036 proto_tree_add_item(version_tree,
1037 hf_rtps_protocol_version_major,
1042 proto_tree_add_item(version_tree,
1043 hf_rtps_protocol_version_minor,
1052 /* ------------------------------------------------------------------------- */
1053 /* Interpret the next bytes as vendor ID. If proto_tree and field ID is
1054 * provided, it can also set.
1056 static void rtps_util_add_vendor_id(proto_tree *tree,
1059 guint8 * buffer, /* Can be NULL */
1060 gint buffer_size) { /* Can be 0 */
1061 guint8 major, minor;
1062 guint32 vendor_id = 0;
1063 guint8 vendor_name[MAX_VENDOR_ID_SIZE];
1065 major = tvb_get_guint8(tvb, offset);
1066 minor = tvb_get_guint8(tvb, offset+1);
1067 vendor_id = (major<<8) | minor;
1069 case RTPS_VENDOR_UNKNOWN:
1070 g_strlcpy(vendor_name, RTPS_VENDOR_UNKNOWN_STRING, MAX_VENDOR_ID_SIZE);
1073 case RTPS_VENDOR_RTI:
1074 g_strlcpy(vendor_name, RTPS_VENDOR_RTI_STRING, MAX_VENDOR_ID_SIZE);
1078 g_snprintf(vendor_name, MAX_VENDOR_ID_SIZE, "%d.%d", major, minor);
1082 proto_tree_add_uint_format(tree,
1091 if (buffer != NULL) {
1092 g_strlcpy(buffer, vendor_name, buffer_size);
1098 /* ------------------------------------------------------------------------- */
1099 /* Insert in the protocol tree the next 8 bytes interpreted as Locator_t
1101 * Locator_t is a struct defined as:
1103 * long kind; // kind of locator
1104 * unsigned long port;
1105 * octet[16] address;
1108 static void rtps_util_add_locator_t(proto_tree *tree,
1112 const guint8 * label,
1113 guint8 * buffer, /* Can be NULL */
1114 gint buffer_size) { /* Can be 0 */
1117 proto_tree * locator_tree;
1121 char temp_buff[MAX_LOCATOR_SIZE];
1122 char addr_buff[MAX_IPV6_SIZE];
1123 const char *kind_string = NULL;
1127 kind = NEXT_guint32(tvb, offset, little_endian);
1128 port = NEXT_guint32(tvb, offset+4, little_endian);
1129 for (i = 0; i < 16; ++i) {
1130 addr[i] = tvb_get_guint8(tvb, offset + 8 + i);
1135 case LOCATOR_KIND_UDPV4:
1136 kind_string = "LOCATOR_KIND_UDPV4";
1137 g_snprintf(addr_buff, MAX_IPV6_SIZE,
1143 g_snprintf(temp_buff, MAX_LOCATOR_SIZE, "%s:%d",
1148 case LOCATOR_KIND_UDPV6:
1149 kind_string = "LOCATOR_KIND_UDPV6";
1150 rtps_util_format_ipv6(addr, &addr_buff[0], MAX_IPV6_SIZE);
1151 g_snprintf(temp_buff, MAX_LOCATOR_SIZE,
1152 "IPv6: { addr=%s, port=%d }",
1157 case LOCATOR_KIND_INVALID:
1158 kind_string = "LOCATOR_KIND_INVALID";
1160 case LOCATOR_KIND_RESERVED:
1161 if (!kind_string) /* Need to guard overrides (no break before) */
1162 kind_string = "LOCATOR_KIND_RESERVED";
1165 if (!kind_string) /* Need to guard overrides (no break before) */
1166 kind_string = "(unknown)";
1167 g_snprintf(temp_buff, MAX_LOCATOR_SIZE,
1168 "{ kind=%02x, port=%d, addr=%02x %02x %02x ... %02x %02x }",
1179 ti = proto_tree_add_text(tree,
1187 locator_tree = proto_item_add_subtree(ti,
1189 proto_tree_add_text(locator_tree,
1196 proto_tree_add_text(locator_tree,
1202 (port == 0) ? " (PORT_INVALID)" : "");
1203 proto_tree_add_text(locator_tree,
1211 g_strlcpy(buffer, temp_buff, buffer_size);
1215 /* ------------------------------------------------------------------------- */
1216 /* Insert in the protocol tree the next bytes interpreted as a list of
1218 * - unsigned long numLocators
1223 * Returns the new offset after parsing the locator list
1225 static int rtps_util_add_locator_list(proto_tree *tree,
1228 const guint8 * label,
1229 int little_endian) {
1232 proto_tree *locator_tree;
1233 guint32 num_locators;
1235 num_locators = NEXT_guint32(tvb, offset, little_endian);
1237 ti = proto_tree_add_text(tree,
1245 return offset + 4 + ((num_locators > 0) ? (24 * num_locators) : 0);
1248 if (num_locators > 0) {
1252 locator_tree = proto_item_add_subtree(ti,
1253 ett_rtps_locator_udp_v4);
1255 for (i = 0; i < num_locators; ++i) {
1256 g_snprintf(temp_buff, 20, "Locator[%d]", i);
1257 rtps_util_add_locator_t(tree,
1271 /* ------------------------------------------------------------------------- */
1272 /* Insert in the protocol tree the next 4 bytes interpreted as IPV4Address_t
1274 static void rtps_util_add_ipv4_address_t(proto_tree *tree,
1278 const guint8 * label,
1279 guint8 * buffer, /* Can be NULL */
1280 gint buffer_size) { /* Can be 0 */
1284 addr = NEXT_guint32(tvb, offset, little_endian);
1285 if (addr == IPADDRESS_INVALID) {
1287 g_strlcpy(buffer, IPADDRESS_INVALID_STRING, buffer_size);
1290 proto_tree_add_text(tree,
1296 IPADDRESS_INVALID_STRING);
1300 g_snprintf(buffer, buffer_size,
1302 (addr >> 24) & 0xff,
1303 (addr >> 16) & 0xff,
1308 proto_tree_add_text(tree,
1314 (addr >> 24) & 0xff,
1315 (addr >> 16) & 0xff,
1324 /* ------------------------------------------------------------------------- */
1325 /* Insert in the protocol tree the next 8 bytes interpreted as LocatorUDPv4
1327 * LocatorUDPv4 is a struct defined as:
1329 * unsigned long address;
1330 * unsigned long port;
1334 static void rtps_util_add_locator_udp_v4(proto_tree *tree,
1337 const guint8 * label,
1338 int little_endian) {
1341 proto_tree * locator_tree;
1343 char portLabel[MAX_PORT_SIZE];
1344 char addr[MAX_IPV4_ADDRESS_SIZE];
1346 port = NEXT_guint32(tvb, offset+4, little_endian);
1348 if (port == PORT_INVALID) {
1349 g_snprintf(portLabel, MAX_PORT_SIZE, "%s (0x00000000)", PORT_INVALID_STRING);
1351 g_snprintf(portLabel, MAX_PORT_SIZE, "%u", port);
1354 ti = proto_tree_add_text(tree,
1358 "addr"); /* Add text later */
1359 locator_tree = proto_item_add_subtree(ti, ett_rtps_locator_udp_v4);
1360 rtps_util_add_ipv4_address_t(locator_tree,
1366 MAX_IPV4_ADDRESS_SIZE);
1367 proto_tree_add_text(locator_tree,
1374 proto_item_set_text(ti, "%s: { address=%s, port=%s }",
1382 /* ------------------------------------------------------------------------- */
1383 /* Insert in the protocol tree the next 12 bytes interpreted as GuidPrefix
1384 * If tree is specified, it fills up the protocol tree item:
1385 * - hf_rtps_guid_prefix
1390 * If buffer is specified, it returns in it a string representation of the
1393 static void rtps_util_add_guid_prefix(proto_tree *tree,
1396 int hf_prefix, /* Cannot be 0 if tree != NULL */
1400 const guint8 * label, /* Can be NULL */
1401 guint8 * buffer, /* Can be NULL */
1407 guint8 guid_prefix[12];
1408 const guint8 * safe_label;
1411 safe_label = (label == NULL) ? (const guint8 *)"guidPrefix" : label;
1413 /* Read values from TVB */
1414 host_id = tvb_get_ntohl(tvb, offset);
1415 app_id = tvb_get_ntohl(tvb, offset + 4);
1416 counter = tvb_get_ntohl(tvb, offset + 8);
1417 for (i = 0; i < 12; ++i) {
1418 guid_prefix[i] = tvb_get_guint8(tvb, offset+i);
1421 /* Format the string */
1422 temp_buff = (guint8 *) ep_alloc(MAX_GUID_PREFIX_SIZE);
1423 g_snprintf(temp_buff, MAX_GUID_PREFIX_SIZE,
1424 "%s=%02x%02x%02x%02x:%02x%02x%02x%02x:%02x%02x%02x%02x"
1425 " { hostId=%08x, appId=%08x, counter=%08x }",
1444 proto_item * ti, *hidden_item;
1445 proto_tree * guid_tree;
1447 /* The numeric value (used for searches) */
1448 hidden_item = proto_tree_add_item(tree,
1454 PROTO_ITEM_SET_HIDDEN(hidden_item);
1456 /* The text node (root of the guid prefix sub-tree) */
1457 ti = proto_tree_add_text(tree,
1464 guid_tree = proto_item_add_subtree(ti,
1465 ett_rtps_guid_prefix);
1468 proto_tree_add_item(guid_tree,
1476 proto_tree_add_item(guid_tree,
1484 proto_tree_add_item(guid_tree,
1492 if (buffer != NULL) {
1493 g_strlcpy(buffer, temp_buff, buffer_size);
1499 /* ------------------------------------------------------------------------- */
1500 /* Insert the entityId from the next 4 bytes. Since there are more than
1501 * one entityId, we need to specify also the IDs of the entityId (and its
1502 * sub-components), as well as the label identifying it.
1504 static void rtps_util_add_entity_id(proto_tree *tree,
1508 int hf_item_entity_key,
1509 int hf_item_entity_kind,
1510 int subtree_entity_id,
1512 guint32 * entity_id_out) { /* Can be NULL */
1513 guint32 entity_id = tvb_get_ntohl(tvb, offset);
1514 guint32 entity_key = (entity_id >> 8);
1515 guint8 entity_kind = (entity_id & 0xff);
1516 const char *str_predef = match_strval(entity_id, entity_id_vals);
1518 if (entity_id_out != NULL) {
1519 *entity_id_out = entity_id;
1524 proto_tree * entity_tree;
1527 if (str_predef == NULL) {
1528 /* entityId is not a predefined value, format it */
1529 ti = proto_tree_add_uint_format(tree,
1535 "%s: 0x%08x (%s: 0x%06x)",
1538 val_to_str(entity_kind, entity_kind_vals,
1539 "unknown kind (%02x)"),
1542 /* entityId is a predefined value */
1543 ti = proto_tree_add_uint_format(tree,
1549 "%s: %s (0x%08x)", label, str_predef, entity_id);
1552 entity_tree = proto_item_add_subtree(ti,
1555 proto_tree_add_item(entity_tree,
1562 proto_tree_add_item(entity_tree,
1563 hf_item_entity_kind,
1572 /* ------------------------------------------------------------------------- */
1573 /* Insert the entityId from the next 4 bytes as a generic one (not connected
1574 * to any protocol field). It simply insert the content as a simple text entry
1575 * and returns in the passed buffer only the value (without the label).
1577 static void rtps_util_add_generic_entity_id(proto_tree *tree,
1581 guint8 * buffer, /* Can be NULL */
1583 guint32 entity_id = tvb_get_ntohl(tvb, offset);
1584 guint32 entity_key = (entity_id >> 8);
1585 guint8 entity_kind = (entity_id & 0xff);
1586 const char *str_predef = match_strval(entity_id, entity_id_vals);
1587 guint8 temp_buffer[MAX_GUID_SIZE];
1589 if (str_predef == NULL) {
1590 /* entityId is not a predefined value, format it */
1591 g_snprintf(temp_buffer, MAX_GUID_SIZE,
1592 "0x%08x (%s: 0x%06x)",
1594 val_to_str(entity_kind, entity_kind_vals,
1595 "unknown kind (%02x)"),
1598 /* entityId is a predefined value */
1599 g_snprintf(temp_buffer, MAX_GUID_SIZE,
1606 proto_tree_add_text(tree,
1615 if (buffer != NULL) {
1616 g_strlcpy(buffer, temp_buffer, buffer_size);
1622 /* ------------------------------------------------------------------------- */
1623 /* Interpret the next 16 octets as a generic GUID and insert it in the protocol
1624 * tree as simple text (no reference fields are set).
1625 * It is mostly used in situation where is not required to perform search for
1626 * this kind of GUID (i.e. like in some DATA parameter lists).
1628 static void rtps_util_add_generic_guid(proto_tree *tree,
1629 tvbuff_t * tvb, /* Cannot be NULL */
1631 const char *label, /* Cannot be NULL */
1632 guint8 * buffer, /* Can be NULL */
1641 guint8 guid_raw[16];
1642 const char * str_entity_kind;
1643 guint8 temp_buff[MAX_GUID_SIZE];
1646 /* Read typed data */
1647 host_id = tvb_get_ntohl(tvb, offset);
1648 app_id = tvb_get_ntohl(tvb, offset + 4);
1649 counter = tvb_get_ntohl(tvb, offset + 8);
1650 entity_id = tvb_get_ntohl(tvb, offset + 12);
1652 /* Re-Read raw data */
1653 for (i = 0; i < 16; ++i) {
1654 guid_raw[i] = tvb_get_guint8(tvb, offset+i);
1657 /* Split components from typed data */
1658 entity_key = (entity_id >> 8);
1659 entity_kind = (entity_id & 0xff);
1661 /* Lookup for predefined app kind and entity kind */
1662 str_entity_kind = val_to_str(entity_kind, entity_kind_vals, "%02x");
1664 /* Compose output buffer for raw guid */
1665 g_snprintf(temp_buff, MAX_GUID_SIZE,
1666 "%s=%02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x: "
1667 "{ hostId=%08x, appId=%08x, counter=%08x, entityId=%08x (%s: %06x) }",
1669 guid_raw[0], guid_raw[1], guid_raw[2], guid_raw[3],
1670 guid_raw[4], guid_raw[5], guid_raw[6], guid_raw[7],
1671 guid_raw[8], guid_raw[9], guid_raw[10], guid_raw[11],
1672 guid_raw[12], guid_raw[13], guid_raw[14], guid_raw[15],
1676 entity_id, str_entity_kind, entity_key);
1678 proto_tree_add_text(tree, tvb, offset, 16, "%s", temp_buff);
1680 if (buffer != NULL) {
1681 g_strlcpy(buffer, temp_buff, buffer_size);
1686 /* ------------------------------------------------------------------------- */
1687 /* Insert in the protocol tree the next 8 bytes interpreted as sequence
1690 static guint64 rtps_util_add_seq_number(proto_tree *tree,
1694 const char *label _U_) {
1695 guint64 hi = (guint64)NEXT_guint32(tvb, offset, little_endian);
1696 guint64 lo = (guint64)NEXT_guint32(tvb, offset+4, little_endian);
1697 guint64 all = (hi << 32) | lo;
1700 proto_tree_add_int64_format(tree,
1701 hf_rtps_sm_seq_number,
1706 "%s: %" G_GINT64_MODIFIER "u", label, all);
1712 /* ------------------------------------------------------------------------- */
1713 /* Insert in the protocol tree the next 8 bytes interpreted as NtpTime
1715 static void rtps_util_add_ntp_time(proto_tree *tree,
1720 guint8 * buffer, /* Can be NULL */
1722 guint8 tempBuffer[MAX_NTP_TIME_SIZE];
1724 gint32 sec = NEXT_guint32(tvb, offset, little_endian);
1725 guint32 frac = NEXT_guint32(tvb, offset+4, little_endian);
1728 if ((sec == 0x7fffffff) && (frac == 0xffffffff)) {
1729 g_strlcpy(tempBuffer, "INFINITE", MAX_NTP_TIME_SIZE);
1730 } else if ((sec == 0) && (frac == 0)) {
1731 g_strlcpy(tempBuffer, "0 sec", MAX_NTP_TIME_SIZE);
1733 absolute = (double)sec + (double)frac / ((double)(0x80000000) * 2.0);
1734 g_snprintf(tempBuffer, MAX_NTP_TIME_SIZE,
1735 "%f sec (%ds + 0x%08x)", absolute, sec, frac);
1739 proto_tree *time_tree;
1741 ti = proto_tree_add_none_format(tree,
1749 time_tree = proto_item_add_subtree(ti, ett_rtps_ntp_time);
1750 proto_tree_add_item(time_tree,
1751 hf_rtps_param_ntpt_sec,
1756 proto_tree_add_item(time_tree,
1757 hf_rtps_param_ntpt_fraction,
1763 if (buffer != NULL) {
1764 g_strlcpy(buffer, tempBuffer, buffer_size);
1768 /* ------------------------------------------------------------------------- */
1769 /* Insert in the protocol tree the next data interpreted as a String
1770 * Returns the new offset (after reading the string)
1772 static gint rtps_util_add_string(proto_tree *tree,
1775 int hf_item, /* Can be -1 (if label!=NULL) */
1777 const guint8 * label, /* Can be NULL (if hf_item!=-1) */
1778 guint8 * buffer, /* Can be NULL */
1779 size_t buffer_size) {
1780 guint8 * retVal = NULL;
1781 guint32 size = NEXT_guint32(tvb, offset, little_endian);
1784 retVal = tvb_get_ephemeral_string(tvb, offset+4, size);
1788 if (hf_item != -1) {
1789 proto_item * hidden_item;
1790 hidden_item = proto_tree_add_string(tree,
1795 (size == 0) ? (guint8 *)"" : retVal);
1796 PROTO_ITEM_SET_HIDDEN(hidden_item);
1798 proto_tree_add_text(tree,
1803 ((label != NULL) ? label : (const guint8 *)"value") ,
1804 (size == 0) ? (guint8 *)"" : retVal);
1806 if (buffer != NULL) {
1810 g_snprintf(buffer, (gulong) buffer_size, "%s", retVal);
1814 /* NDDS align strings at 4-bytes word. So:
1815 * string_length: 4 -> buffer_length = 4;
1816 * string_length: 5 -> buffer_length = 8;
1817 * string_length: 6 -> buffer_length = 8;
1818 * string_length: 7 -> buffer_length = 8;
1819 * string_length: 8 -> buffer_length = 8;
1822 return offset + 4 + ((size + 3) & 0xfffffffc);
1826 /* ------------------------------------------------------------------------- */
1827 /* Insert in the protocol tree the next data interpreted as a signed long.
1828 * Returns the value inserted as a guint32
1830 static guint32 rtps_util_add_long(proto_tree *tree,
1833 int hf_item, /* Can be -1 */
1835 gboolean is_hex, /* Format as 0x... */
1836 gboolean is_signed, /* Signed/Unsigned */
1837 const char *label, /* Can be NULL */
1839 size_t buffer_size) {
1843 guint32 retVal = NEXT_guint32(tvb, offset, little_endian);
1844 g_snprintf(temp_buff, 16,
1845 (is_hex ? "0x%08x" : (is_signed ? "%d" : "%u")),
1846 NEXT_guint32(tvb, offset, little_endian));
1848 if (hf_item != -1) {
1849 proto_tree_add_item(tree,
1855 } else if (label != NULL) {
1856 proto_tree_add_text(tree,
1865 if (buffer != NULL) {
1866 g_strlcpy(buffer, temp_buff, (gulong) buffer_size);
1871 /* ------------------------------------------------------------------------- */
1872 /* Insert in the protocol tree the next data interpreted as a 16-bit short
1874 static guint16 rtps_util_add_short(proto_tree *tree,
1877 int hf_item, /* Can be -1 */
1879 gboolean is_hex, /* Format as 0x... */
1880 gboolean is_signed, /* Signed/Unsigned */
1881 const char *label, /* Can be NULL */
1886 guint16 retVal = NEXT_guint16(tvb, offset, little_endian);
1887 g_snprintf(temp_buff, 16,
1888 (is_hex ? "0x%04x" : (is_signed ? "%d" : "%u")),
1891 if (hf_item != -1) {
1892 proto_tree_add_item(tree,
1898 } else if (label != NULL) {
1899 proto_tree_add_text(tree,
1908 if (buffer != NULL) {
1909 g_strlcpy(buffer, temp_buff, buffer_size);
1916 /* ------------------------------------------------------------------------- */
1917 /* Insert in the protocol tree the next data interpreted as a port (unsigned
1920 static void rtps_util_add_port(proto_tree *tree,
1925 guint8 * buffer, /* Can be NULL */
1927 guint8 tempBuffer[MAX_PORT_SIZE];
1928 guint32 value = NEXT_guint32(tvb, offset, little_endian);
1930 if (value == PORT_INVALID) {
1931 g_snprintf(buffer, buffer_size, "%s (0x00000000)", PORT_INVALID_STRING);
1933 g_snprintf(tempBuffer, MAX_PORT_SIZE, "%u", value);
1937 proto_tree_add_text(tree,
1945 if (buffer != NULL) {
1946 g_strlcpy(buffer, tempBuffer, buffer_size);
1951 /* ------------------------------------------------------------------------- */
1952 /* Insert in the protocol tree the next data interpreted as a boolean
1953 * Returns the pointer to a dynamically allocated buffer containing the
1954 * formatted version of the value.
1956 static void rtps_util_add_boolean(proto_tree *tree,
1960 guint8 * buffer, /* Can be NULL */
1961 size_t buffer_size) {
1963 guint8 value = tvb_get_guint8(tvb, offset);
1965 str = value ? "TRUE" : "FALSE";
1968 g_strlcpy(buffer, str, (gulong) buffer_size);
1972 proto_tree_add_text(tree,
1983 /* ------------------------------------------------------------------------- */
1984 /* Insert in the protocol tree the next bytes interpreted as
1985 * DurabilityServiceQosPolicy
1987 static void rtps_util_add_durability_service_qos(proto_tree *tree,
1993 guint8 temp_buffer[MAX_NTP_TIME_SIZE];
1994 gint32 kind = NEXT_guint32(tvb, offset+8, little_endian);
1995 gint32 history_depth = NEXT_guint32(tvb, offset+12, little_endian);
1996 gint32 max_samples = NEXT_guint32(tvb, offset+16, little_endian);
1997 gint32 max_instances = NEXT_guint32(tvb, offset+20, little_endian);
1998 gint32 max_spi = NEXT_guint32(tvb, offset+24, little_endian);
2000 rtps_util_add_ntp_time(NULL,
2008 g_snprintf(buffer, buffer_size,
2009 "{ service_cleanup_delay=%s, history_kind='%s', "
2010 "history_depth=%d, max_samples=%d, max_instances=%d, "
2011 "max_samples_per_instances=%d }",
2013 val_to_str(kind, history_qos_vals, "0x%08x"),
2019 rtps_util_add_ntp_time(tree,
2023 "service_cleanup_delay",
2026 proto_tree_add_text(tree,
2031 val_to_str(kind, history_qos_vals, "0x%08x"));
2032 proto_tree_add_text(tree,
2036 "history_depth: %d",
2038 proto_tree_add_text(tree,
2044 proto_tree_add_text(tree,
2048 "max_instances: %d",
2050 proto_tree_add_text(tree,
2054 "max_samples_per_instances: %d",
2059 /* ------------------------------------------------------------------------- */
2060 /* Insert in the protocol tree the next bytes interpreted as Liveliness
2061 * QoS Policy structure.
2063 static void rtps_util_add_liveliness_qos(proto_tree *tree,
2069 guint8 temp_buffer[MAX_NTP_TIME_SIZE];
2070 guint32 kind = NEXT_guint32(tvb, offset, little_endian);
2072 rtps_util_add_ntp_time(NULL,
2080 g_snprintf(buffer, buffer_size,
2081 "{ kind=%s, lease_duration=%s }",
2082 val_to_str(kind, liveliness_qos_vals, "0x%08x"),
2085 proto_tree_add_text(tree,
2090 val_to_str(kind, liveliness_qos_vals, "0x%08x"));
2091 rtps_util_add_ntp_time(tree,
2101 /* ------------------------------------------------------------------------- */
2102 /* Insert in the protocol tree the next bytes interpreted as enum type.
2104 static void rtps_util_add_kind_qos(proto_tree *tree,
2109 const value_string *vals,
2110 guint8 * buffer, /* Can be NULL */
2111 size_t buffer_size) {
2112 guint32 kind = NEXT_guint32(tvb, offset, little_endian);
2115 g_strlcpy(buffer, val_to_str(kind, vals, "0x%08x"),
2116 (gulong) buffer_size);
2120 proto_tree_add_text(tree,
2131 /* ------------------------------------------------------------------------- */
2132 /* Insert in the protocol tree the next bytes interpreted as Sequence of
2134 * The formatted buffer is: "string1", "string2", "string3", ...
2135 * Returns the new updated offset
2137 static gint rtps_util_add_seq_string(proto_tree *tree,
2143 guint8 * buffer, /* Can NOT be NULL */
2145 guint32 num_strings;
2147 proto_tree *string_tree = NULL;
2148 proto_item *ti = NULL;
2149 char temp_buff[MAX_LABEL_SIZE];
2150 guint8 overview_buffer[MAX_LABEL_SIZE];
2152 num_strings = NEXT_guint32(tvb, offset, little_endian);
2153 proto_tree_add_text(tree,
2157 "size: %d", num_strings);
2160 /* Create the string node with a fake string, then replace it later */
2162 ti = proto_tree_add_text(tree,
2167 string_tree = proto_item_add_subtree(ti, ett_rtps_seq_string);
2170 overview_buffer[0] = '\0';
2172 for (i = 0; i < num_strings; ++i) {
2173 g_snprintf(temp_buff, MAX_LABEL_SIZE,
2177 /* This call safe with string_tree=NULL and is required to calculate offset */
2178 offset = rtps_util_add_string(string_tree,
2184 overview_buffer+strlen(overview_buffer),
2185 MAX_LABEL_SIZE-strlen(overview_buffer));
2188 proto_item_set_text(ti,
2193 if (buffer != NULL) {
2194 g_strlcpy(buffer, overview_buffer, buffer_size);
2199 /* ------------------------------------------------------------------------- */
2200 /* Insert in the protocol tree the next bytes interpreted as Sequence of
2202 * The formatted buffer is: val1, val2, val3, ...
2203 * Returns the new updated offset
2205 static gint rtps_util_add_seq_ulong(proto_tree *tree,
2215 proto_tree *string_tree;
2217 char temp_buff[MAX_LABEL_SIZE];
2218 char overview_buff[MAX_PARAM_SIZE];
2220 num_elem = NEXT_guint32(tvb, offset, little_endian);
2223 /* Create the string node with an empty string, the replace it later */
2225 ti = proto_tree_add_text(tree,
2230 string_tree = proto_item_add_subtree(ti, ett_rtps_seq_ulong);
2232 return offset + 4*num_elem;
2235 overview_buff[0] = '\0';
2237 for (i = 0; i < num_elem; ++i) {
2238 g_snprintf(temp_buff, MAX_LABEL_SIZE,
2242 rtps_util_add_long( string_tree,
2250 overview_buff+strlen(overview_buff),
2251 MAX_PARAM_SIZE-strlen(overview_buff));
2254 proto_item_set_text(ti,
2262 #define LONG_ALIGN(x) (x = (x+3)&0xfffffffc)
2263 #define SHORT_ALIGN(x) (x = (x+1)&0xfffffffe)
2264 #define MAX_ARRAY_DIMENSION 10
2265 #define KEY_COMMENT (" //@key")
2267 /* ------------------------------------------------------------------------- */
2268 static const char * rtps_util_typecode_id_to_string(guint32 typecode_id) {
2269 switch(typecode_id) {
2270 case RTI_CDR_TK_ENUM: return "enum";
2271 case RTI_CDR_TK_UNION: return "union";
2272 case RTI_CDR_TK_STRUCT: return "struct";
2273 case RTI_CDR_TK_LONG: return "long";
2274 case RTI_CDR_TK_SHORT: return "short";
2275 case RTI_CDR_TK_USHORT: return "unsigned short";
2276 case RTI_CDR_TK_ULONG: return "unsigned long";
2277 case RTI_CDR_TK_FLOAT: return "float";
2278 case RTI_CDR_TK_DOUBLE: return "double";
2279 case RTI_CDR_TK_BOOLEAN:return "boolean";
2280 case RTI_CDR_TK_CHAR: return "char";
2281 case RTI_CDR_TK_OCTET: return "octet";
2282 case RTI_CDR_TK_LONGLONG:return "longlong";
2283 case RTI_CDR_TK_ULONGLONG: return "unsigned long long";
2284 case RTI_CDR_TK_LONGDOUBLE: return "long double";
2285 case RTI_CDR_TK_WCHAR: return "wchar";
2286 case RTI_CDR_TK_WSTRING:return "wstring";
2287 case RTI_CDR_TK_STRING: return "string";
2288 case RTI_CDR_TK_SEQUENCE: return "sequence";
2289 case RTI_CDR_TK_ARRAY: return "array";
2290 case RTI_CDR_TK_ALIAS: return "alias";
2291 case RTI_CDR_TK_VALUE: return "valuetype";
2293 case RTI_CDR_TK_NULL:
2295 return "<unknown type>";
2299 /* ------------------------------------------------------------------------- */
2300 /* Insert in the protocol tree the next bytes interpreted as typecode info
2301 * Returns the number of bytes parsed
2303 static gint rtps_util_add_typecode(proto_tree *tree,
2311 const gint offset_begin,
2313 int seq_max_len, /* -1 = not a sequence field */
2314 guint32 * arr_dimension, /* if !NULL: array of 10 int */
2316 const gint original_offset = offset;
2320 char indent_string[40];
2324 /* Structure of the typecode data:
2325 * Offset | Size | Field | Notes
2326 * ----------|-------|------------------------------|---------------------
2328 * 0 | 4 | RTI_CDR_TK_XXXXX | 4 bytes aligned
2329 * 4 | 2 | length the struct |
2332 /* Calc indent string */
2333 memset(indent_string, ' ', 40);
2334 indent_string[indent_level*2] = '\0';
2338 tk_id = NEXT_guint32(tvb, offset, little_endian);
2342 tk_size = NEXT_guint16(tvb, offset, little_endian);
2345 retVal = tk_size + 6; /* 6 = 4 (typecode ID) + 2 (size) */
2347 /* The first bit of typecode is set to 1, clear it */
2348 tk_id &= 0x7fffffff;
2350 /* HACK: NDDS 4.0 and NDDS 4.1 has different typecode ID list.
2351 * The ID listed in the RTI_CDR_TK_XXXXX are the one from NDDS 4.1
2352 * In order to correctly dissect NDDS 4.0 packets containing typecode
2353 * information, we check if the ID of the element at level zero is a
2354 * struct or union. If not, it means we are dissecting a ndds 4.0 packet
2355 * (and we can decrement the ID to match the correct values).
2357 if (indent_level == 0) {
2358 if (tk_id == RTI_CDR_TK_OCTET) {
2366 g_strlcpy(type_name, rtps_util_typecode_id_to_string(tk_id), 40);
2368 /* Structure of the typecode data:
2370 * <type_code_header> ::=
2372 * <type_code_length>
2374 * <kind> ::= long (0=TK_NULL, 1=TK_SHORT...)
2375 * <type_code_length> ::= unsugned short
2380 /* Structure of the typecode data:
2382 * <union_type_code> ::=
2383 * <type_code_header>
2386 * <discriminator_type_code>
2389 * <union_member> ::= <member_length><name><union_member_detail>
2390 * <member_length> ::= unsigned short
2391 * <name> ::= <string>
2392 * <string> ::= <length>char+<eol>
2393 * <length> ::= unsigned long
2396 * <union_member_detail> ::= <is_pointer>
2400 * <labels_count> ::= unsigned long
2404 case RTI_CDR_TK_UNION: {
2405 guint32 struct_name_len;
2406 gint8 * struct_name;
2407 const char * discriminator_name = "<unknown>"; /* for unions */
2408 char * discriminator_enum_name = NULL; /* for unions with enum discriminator */
2409 guint32 defaultIdx; /* Currently is ignored */
2410 guint32 disc_id; /* Used temporarily to populate 'discriminator_name' */
2411 guint16 disc_size; /* Currently is ignored */
2412 guint32 disc_offset_begin;
2413 guint32 num_members;
2414 guint16 member_length;
2415 guint32 member_name_len;
2416 guint8 *member_name = NULL;
2417 guint8 member_is_pointer;
2418 guint32 next_offset;
2419 guint32 field_offset_begin;
2420 guint32 member_label_count;
2421 gint32 member_label;
2422 guint32 discriminator_enum_name_length;
2425 /* - - - - - - - Union name - - - - - - - */
2429 /* Get structure name length */
2430 struct_name_len = NEXT_guint32(tvb, offset, little_endian);
2432 struct_name = tvb_get_ephemeral_string(tvb, offset, struct_name_len);
2433 offset += struct_name_len;
2435 /* - - - - - - - Default index - - - - - - - */
2437 defaultIdx = NEXT_guint32(tvb, offset, little_endian);
2440 /* - - - - - - - Discriminator type code - - - - - - - */
2441 /* We don't recursively dissect everything, instead we just read the type */
2442 disc_id = NEXT_guint32(tvb, offset, little_endian);
2445 disc_size = NEXT_guint16(tvb, offset, little_endian);
2447 disc_offset_begin = offset;
2448 disc_id &= 0x7fffffff;
2449 discriminator_name = rtps_util_typecode_id_to_string(disc_id);
2450 if (disc_id == RTI_CDR_TK_ENUM) {
2451 /* Enums has also a name that we should print */
2453 discriminator_enum_name_length = NEXT_guint32(tvb, offset, little_endian);
2454 discriminator_enum_name = tvb_get_ephemeral_string(tvb, offset+4, discriminator_enum_name_length);
2456 offset = disc_offset_begin + disc_size;
2458 field_offset_begin = offset;
2459 offset += rtps_util_add_typecode(
2461 tvb, next_offset = offset;
2477 /* Add the entry of the union in the tree */
2478 proto_tree_add_text(tree,
2482 "%sunion %s (%s%s%s) {",
2486 (discriminator_enum_name ? " " : ""),
2487 (discriminator_enum_name ? discriminator_enum_name : ""));
2489 if (seq_max_len != -1) {
2490 /* We're dissecting a sequence of struct, bypass the seq definition */
2491 g_snprintf(type_name, 40, "%s", struct_name);
2495 /* - - - - - - - Number of members - - - - - - - */
2497 num_members = NEXT_guint32(tvb, offset, little_endian);
2500 /* - - - - - - - <union_member>+ - - - - - - - */
2501 next_offset = offset;
2503 for (i = 0; i < num_members; ++i) {
2504 /* Safety: this theoretically should be the same already */
2505 field_offset_begin = offset = next_offset;
2507 SHORT_ALIGN(offset);
2509 /* member's length */
2510 member_length = NEXT_guint16(tvb, offset, little_endian);
2512 next_offset = offset + member_length;
2516 member_name_len = NEXT_guint32(tvb, offset, little_endian);
2520 member_name = tvb_get_ephemeral_string(tvb, offset, member_name_len);
2521 offset += member_name_len;
2524 member_is_pointer = tvb_get_guint8(tvb, offset);
2529 member_label_count = NEXT_guint32(tvb, offset, little_endian);
2532 for (j = 0; j < member_label_count; ++j) {
2535 member_label = NEXT_guint32(tvb, offset, little_endian);
2538 /* Add the entry of the union in the tree */
2539 proto_tree_add_text(tree,
2548 offset += rtps_util_add_typecode(
2563 /* Finally prints the name of the struct (if provided) */
2564 g_strlcpy(type_name, "}", 40);
2567 } /* end of case UNION */
2570 case RTI_CDR_TK_ENUM:
2571 case RTI_CDR_TK_STRUCT: {
2572 /* Structure of the typecode data:
2574 * <union_type_code> ::=
2575 * <type_code_header>
2578 * <discriminator_type_code>
2582 * <struct_type_code> ::=
2583 * <type_code_header>
2588 * <name> ::= <string>
2589 * <string> ::= <length>char+<eol>
2590 * <length> ::= unsigned long
2592 * <member_count> ::= unsigned long
2596 * - A2: 2: member length
2597 * - A4: 4: member name length
2600 * - A2 2: bitfield bits (-1=none)
2602 * - A4 4: Typecode ID
2608 * - A2: 2: member length
2609 * - A4: 4: member name length
2611 * - A4: 4: ordinal number
2613 * -> ----------------------------------------------------- <-
2614 * -> The alignment pad bytes belong to the FOLLOWING field <-
2615 * -> A4 = 4 bytes alignment, A2 = 2 bytes alignment <-
2616 * -> ----------------------------------------------------- <-
2618 guint32 struct_name_len;
2619 gint8 * struct_name;
2620 guint32 num_members;
2621 guint16 member_length;
2622 guint8 member_is_pointer;
2623 guint16 member_bitfield;
2624 guint8 member_is_key;
2625 guint32 member_name_len;
2626 guint8 *member_name = NULL;
2627 guint32 next_offset;
2628 guint32 field_offset_begin;
2629 guint32 ordinal_number;
2630 const char * typecode_name;
2635 /* Get structure name length */
2636 struct_name_len = NEXT_guint32(tvb, offset, little_endian);
2640 struct_name = tvb_get_ephemeral_string(tvb, offset, struct_name_len);
2641 offset += struct_name_len;
2644 if (tk_id == RTI_CDR_TK_ENUM) {
2645 typecode_name = "enum";
2646 } else if (tk_id == RTI_CDR_TK_VALUE_PARARM) {
2647 guint16 type_modifier;
2648 guint32 baseTypeCodeKind;
2649 guint32 baseTypeCodeLength;
2650 /* Need to read the type modifier and the base type code */
2651 typecode_name = "<sparse type>";
2652 SHORT_ALIGN(offset);
2653 type_modifier = NEXT_guint16(tvb, offset, little_endian);
2656 baseTypeCodeKind = NEXT_guint32(tvb, offset, little_endian);
2658 baseTypeCodeLength = NEXT_guint32(tvb, offset, little_endian);
2660 offset += baseTypeCodeLength;
2662 typecode_name = "struct";
2665 if (seq_max_len != -1) {
2666 /* We're dissecting a sequence of struct, bypass the seq definition */
2667 g_snprintf(type_name, 40, "%s", struct_name);
2670 /* Prints the typecode header */
2671 proto_tree_add_text(tree,
2683 /* number of members */
2684 num_members = NEXT_guint32(tvb, offset, little_endian);
2687 next_offset = offset;
2688 for (i = 0; i < num_members; ++i) {
2689 /* Safety: this theoretically should be the same already */
2690 field_offset_begin = offset = next_offset;
2692 SHORT_ALIGN(offset);
2694 /* member's length */
2695 member_length = NEXT_guint16(tvb, offset, little_endian);
2697 next_offset = offset + member_length;
2701 member_name_len = NEXT_guint32(tvb, offset, little_endian);
2705 member_name = tvb_get_ephemeral_string(tvb, offset, member_name_len);
2706 offset += member_name_len;
2708 if (tk_id == RTI_CDR_TK_ENUM) {
2709 /* ordinal number */
2711 ordinal_number = NEXT_guint32(tvb, offset, little_endian);
2714 proto_tree_add_text(tree,
2717 (offset-field_offset_begin),
2726 member_is_pointer = tvb_get_guint8(tvb, offset);
2730 SHORT_ALIGN(offset);
2731 member_bitfield = NEXT_guint16(tvb, offset, little_endian);
2732 offset += 2; /* pad will be added by typecode dissector */
2735 member_is_key = tvb_get_guint8(tvb, offset);
2738 offset += rtps_util_add_typecode(
2754 /* Finally prints the name of the struct (if provided) */
2755 g_strlcpy(type_name, "}", 40);
2759 case RTI_CDR_TK_WSTRING:
2760 case RTI_CDR_TK_STRING: {
2761 /* Structure of the typecode data:
2762 * Offset | Size | Field | Notes
2763 * ----------|-------|------------------------------|---------------------
2765 * 8 | 4 | String length | 4-bytes aligned
2767 guint32 string_length;
2770 string_length = NEXT_guint32(tvb, offset, little_endian);
2772 g_snprintf(type_name, 40, "%s<%d>",
2773 (tk_id == RTI_CDR_TK_STRING) ? "string" : "wstring",
2778 case RTI_CDR_TK_SEQUENCE: {
2779 /* Structure of the typecode data:
2781 * - A4: 4: Sequence max length
2782 * - the sequence typecode
2784 guint32 seq_max_len2;
2786 seq_max_len2 = NEXT_guint32(tvb, offset, little_endian);
2789 /* Recursive decode seq typecode */
2790 offset += rtps_util_add_typecode(
2804 /* Differently from the other typecodes, the line has been already printed */
2808 case RTI_CDR_TK_ARRAY: {
2809 /* Structure of the typecode data:
2811 * - A4: 4: number of dimensions
2815 * - the array typecode
2817 guint32 size[MAX_ARRAY_DIMENSION]; /* Max dimensions */
2821 dim_max = NEXT_guint32(tvb, offset, little_endian);
2824 for (i = 0; i < MAX_ARRAY_DIMENSION; ++i) size[i] = 0;
2825 for (i = 0; i < dim_max; ++i) {
2826 size[i] = NEXT_guint32(tvb, offset, little_endian);
2830 /* Recursive decode seq typecode */
2831 offset += rtps_util_add_typecode(
2845 /* Differently from the other typecodes, the line has been already printed */
2849 case RTI_CDR_TK_ALIAS: {
2850 /* Structure of the typecode data:
2852 * - A4: 4: alias name size
2853 * - A4: 4: alias name
2854 * - A4: 4: the alias typecode
2856 guint32 alias_name_length;
2860 alias_name_length = NEXT_guint32(tvb, offset, little_endian);
2862 alias_name = tvb_get_ephemeral_string(tvb, offset, alias_name_length);
2863 offset += alias_name_length;
2864 g_strlcpy(type_name, alias_name, 40);
2871 * - A4: 4: name length
2873 * - A2: type modifier
2874 * - A4: base type code
2875 * - A4: number of members
2876 * Foreach member: (it's just like a struct)
2879 case RTI_CDR_TK_VALUE_PARARM:
2880 case RTI_CDR_TK_VALUE: {
2881 /* Not fully dissected for now */
2883 guint32 value_name_len;
2885 const char * type_id_name = "valuetype";
2888 /* Get structure name length */
2889 value_name_len = NEXT_guint32(tvb, offset, little_endian);
2893 value_name = tvb_get_ephemeral_string(tvb, offset, value_name_len);
2894 offset += value_name_len;
2896 if (tk_id == RTI_CDR_TK_VALUE_PARARM) {
2897 type_id_name = "valueparam";
2899 g_snprintf(type_name, 40, "%s '%s'", type_id_name, value_name);
2902 } /* switch(tk_id) */
2904 /* Sequence print */
2905 if (seq_max_len != -1) {
2906 proto_tree_add_text(tree,
2909 (offset-offset_begin),
2910 "%ssequence<%s, %d> %s%s;%s",
2914 is_pointer ? "*" : "",
2916 is_key ? KEY_COMMENT : "");
2921 if (arr_dimension != NULL) {
2922 /* Printing an array */
2923 emem_strbuf_t *dim_str = ep_strbuf_new_label("");
2924 for (i = 0; i < MAX_ARRAY_DIMENSION; ++i) {
2925 if (arr_dimension[i] != 0) {
2926 ep_strbuf_append_printf(dim_str, "[%d]", arr_dimension[i]);
2931 proto_tree_add_text(tree,
2934 (offset-offset_begin),
2940 is_key ? KEY_COMMENT : "");
2944 /* Bitfield print */
2945 if (bitfield != 0xffff && name != NULL && is_pointer == 0) {
2946 proto_tree_add_text(tree,
2949 (offset-offset_begin),
2955 is_key ? KEY_COMMENT : "");
2959 /* Everything else */
2960 proto_tree_add_text(tree,
2963 (offset-offset_begin),
2968 is_pointer ? "*" : "",
2970 is_key ? KEY_COMMENT : "");
2975 /* ------------------------------------------------------------------------- */
2976 /* Insert in the protocol tree the next bytes interpreted as Sequence of
2978 * The formatted buffer is: [ 0x01, 0x02, 0x03, 0x04, ...]
2979 * The maximum number of elements displayed is 10, after that a '...' is
2982 static void rtps_util_add_seq_octets(proto_tree *tree,
2993 gint original_offset = offset;
2994 guint32 original_seq_length;
2997 original_seq_length = seq_length = NEXT_guint32(tvb, offset, little_endian);
3000 if (param_length < 4 + (int)seq_length) {
3001 g_strlcpy(buffer, "RTPS PROTOCOL ERROR: parameter value too small", buffer_size);
3003 proto_tree_add_text(tree,
3013 /* Limit the number of octets displayed to MAX_SEQ_OCTETS_PRINTED */
3014 if (seq_length > MAX_SEQ_OCTETS_PRINTED) {
3015 seq_length = MAX_SEQ_OCTETS_PRINTED;
3017 for (i = 0; i < seq_length; ++i) {
3018 idx += g_snprintf(&buffer[idx],
3019 buffer_size - idx - 1,
3021 tvb_get_guint8(tvb, offset++));
3022 if (idx >= buffer_size) {
3026 if (seq_length != original_seq_length) {
3027 /* seq_length was reduced, add '...' */
3028 g_strlcat(buffer, "...", buffer_size);
3032 proto_tree_add_text(tree,
3036 "sequenceSize: %d octets",
3037 original_seq_length);
3038 proto_tree_add_item(tree,
3042 original_seq_length,
3051 /* ------------------------------------------------------------------------- */
3052 /* Insert in the protocol tree the next bytes interpreted as a Bitmap
3054 * SequenceNumber_t bitmapBase;
3055 * sequence<long, 8> bitmap;
3056 * } SequenceNumberSet;
3058 * Returns the new offset after reading the bitmap.
3060 static int rtps_util_add_bitmap(proto_tree *tree,
3064 const char *label _U_) {
3068 char temp_buff[MAX_BITMAP_SIZE];
3071 proto_tree * bitmap_tree;
3072 const gint original_offset = offset;
3075 /* Bitmap base sequence number */
3076 seq_base = rtps_util_add_seq_number(NULL,
3083 /* Reads the bitmap size */
3084 num_bits = NEXT_guint32(tvb, offset, little_endian);
3088 /* Reads the bits (and format the print buffer) */
3090 temp_buff[0] = '\0';
3091 for (i = 0; i < num_bits; i += 32) {
3092 data = NEXT_guint32(tvb, offset, little_endian);
3094 for (j = 0; j < 32; ++j) {
3095 datamask = (1 << (31-j));
3096 temp_buff[idx] = ((data & datamask) == datamask) ? '1':'0';
3098 if (idx >= num_bits) {
3101 if (idx >= MAX_BITMAP_SIZE-1) {
3106 temp_buff[idx] = '\0';
3108 /* removes all the ending '0' */
3109 for (i = (int)strlen(temp_buff) - 1; (i>0 && temp_buff[i] == '0'); --i) {
3110 temp_buff[i] = '\0';
3114 ti = proto_tree_add_text(tree,
3117 offset-original_offset,
3118 "%s: %" G_GINT64_MODIFIER "u/%d:%s",
3123 bitmap_tree = proto_item_add_subtree(ti, ett_rtps_bitmap);
3124 proto_tree_add_text(bitmap_tree,
3128 "bitmapBase: %" G_GINT64_MODIFIER "u",
3130 proto_tree_add_text(bitmap_tree,
3132 original_offset + 8,
3136 if (temp_buff[0] != '\0') {
3137 proto_tree_add_text(bitmap_tree,
3139 original_offset + 12,
3140 offset - original_offset - 12,
3148 /* ------------------------------------------------------------------------- */
3149 /* Insert in the protocol tree the next bytes interpreted as a FragmentNumberSet
3150 * typedef unsigned long FragmentNumber_t;
3152 * FragmentNumber_t bitmapBase;
3153 * sequence<FragmentNumber_t> bitmap;
3154 * } FragmentNumberSet;
3156 * Returns the new offset after reading the bitmap.
3158 static int rtps_util_add_fragment_number_set(proto_tree *tree,
3162 const char *label _U_,
3163 gint section_size) {
3167 char temp_buff[MAX_BITMAP_SIZE];
3170 proto_tree * bitmap_tree;
3171 const gint original_offset = offset;
3176 /* RTI DDS 4.2d was sending the FragmentNumber_t as a 64-bit long integer
3177 * instead of 32-bit long.
3178 * Attempt to decode this section as 32-bit, then check if the size of the
3179 * message match what is here. If not re-decode it as 64-bit.
3181 num_bits = NEXT_guint32(tvb, offset+4, little_endian);
3182 expected_size = (((num_bits / 8) + 3) / 4) * 4 + 8;
3183 if (expected_size == section_size) {
3184 base = (guint64)NEXT_guint32(tvb, offset, little_endian);
3188 /* Attempt to use 64-bit for base */
3189 num_bits = NEXT_guint32(tvb, offset+8, little_endian);
3190 /* num_bits/8 must be aligned to the 4-byte word */
3191 expected_size = (((num_bits / 8) + 3) / 4) * 4 + 12;
3192 if (expected_size == section_size) {
3193 guint64 hi = (guint64)NEXT_guint32(tvb, offset, little_endian);
3194 guint64 lo = (guint64)NEXT_guint32(tvb, offset+4, little_endian);
3195 base = (hi << 32) | lo;
3199 /* size don't match, packet error */
3201 proto_tree_add_text(tree,
3205 "Packet malformed: illegal size for fragment number set");
3211 /* Reads the bits (and format the print buffer) */
3213 temp_buff[0] = '\0';
3214 for (i = 0; i < num_bits; i += 32) {
3215 data = NEXT_guint32(tvb, offset, little_endian);
3217 for (j = 0; j < 32; ++j) {
3218 datamask = (1 << (31-j));
3219 temp_buff[idx] = ((data & datamask) != 0) ? '1':'0';
3221 if (idx > num_bits) {
3224 if (idx >= MAX_BITMAP_SIZE-1) {
3229 temp_buff[idx] = '\0';
3231 /* removes all (but the last one) characters '0' */
3232 for (i = (int)strlen(temp_buff) - 1; (i>0 && temp_buff[i] == '0'); --i) {
3233 temp_buff[i] = '\0';
3236 ti = proto_tree_add_text(tree,
3239 offset-original_offset,
3240 "%s: %" G_GINT64_MODIFIER "u/%d:%s",
3245 bitmap_tree = proto_item_add_subtree(ti, ett_rtps_bitmap);
3246 proto_tree_add_text(bitmap_tree,
3250 "bitmapBase: %" G_GINT64_MODIFIER "u",
3252 proto_tree_add_text(bitmap_tree,
3254 original_offset + base_size,
3258 if (temp_buff[0] != '\0') {
3259 proto_tree_add_text(bitmap_tree,
3261 original_offset + base_size + 4,
3262 offset - original_offset - base_size - 4,
3271 /* ------------------------------------------------------------------------- */
3272 /* Decode the submessage flags (8 bit version)
3274 static void rtps_util_decode_flags(proto_tree * tree,
3278 const struct Flag_definition * flag_def) {
3281 proto_tree * flags_tree;
3283 char flags_str[MAX_FLAG_SIZE];
3288 flags_str[0] = '\0';
3289 for (i = 0; i < 8; ++i) {
3290 g_snprintf(flags_str + (2 * i), MAX_FLAG_SIZE - (2 * i), "%c ",
3291 ((flags & (1<<(7-i))) ? flag_def[i].letter : RESERVEDFLAG_CHAR));
3294 ti = proto_tree_add_uint_format(tree,
3300 "Flags: 0x%02x (%s)",
3304 flags_tree = proto_item_add_subtree(ti,
3307 for (i = 0; i < 8; ++i) {
3308 int is_set = (flags & (1 << (7-i)));
3310 for (j = 0; j < 8; ++j) {
3311 flags_str[j] = (i == j) ? (is_set ? '1' : '0') : '.';
3313 flags_str[8] = '\0';
3315 proto_tree_add_text(flags_tree,
3321 flag_def[i].description,
3322 is_set ? "Set" : "Not set");
3327 /* ------------------------------------------------------------------------- */
3328 /* Decode the submessage flags (16 bit version)
3330 static void rtps_util_decode_flags_16bit(proto_tree * tree,
3334 const struct Flag_definition * flag_def) {
3337 proto_tree * flags_tree;
3339 char flags_str[MAX_FLAG_SIZE];
3344 flags_str[0] = '\0';
3345 for (i = 0; i < 16; ++i) {
3346 g_snprintf(flags_str + (2 * i), MAX_FLAG_SIZE - (2 * i), "%c ",
3347 ((flags & (1<<(15-i))) ? flag_def[i].letter : RESERVEDFLAG_CHAR));
3350 ti = proto_tree_add_uint_format(tree,
3356 "Flags: 0x%04x (%s)",
3360 flags_tree = proto_item_add_subtree(ti,
3363 for (i = 0; i < 16; ++i) {
3364 int is_set = (flags & (1 << (15-i)));
3366 for (j = 0; j < 16; ++j) {
3367 flags_str[j] = (i == j) ? (is_set ? '1' : '0') : '.';
3369 flags_str[16] = '\0';
3371 proto_tree_add_text(flags_tree,
3377 flag_def[i].description,
3378 is_set ? "Set" : "Not set");
3384 /* *********************************************************************** */
3385 /* * Serialized data dissector * */
3386 /* *********************************************************************** */
3387 /* Note: the encapsulation header is ALWAYS big endian, then the encapsulation
3388 * type specified the type of endianess of the payload.
3390 static void dissect_serialized_data(proto_tree *tree,
3395 guint16 vendor_id) {
3397 proto_tree * rtps_parameter_sequence_tree;
3398 guint16 encapsulation_id;
3399 guint16 encapsulation_len;
3400 int encapsulation_little_endian = 0;
3405 /* Creates the sub-tree */
3406 ti = proto_tree_add_text(tree,
3411 rtps_parameter_sequence_tree = proto_item_add_subtree(ti,
3412 ett_rtps_serialized_data);
3415 /* Encapsulation ID */
3416 encapsulation_id = NEXT_guint16(tvb, offset, 0); /* Always big endian */
3418 proto_tree_add_text(rtps_parameter_sequence_tree,
3422 "encapsulation kind: %s",
3423 val_to_str(encapsulation_id, encapsulation_id_vals, "unknown (%02x)"));
3426 /* Sets the correct values for encapsulation_le */
3427 if (encapsulation_id == ENCAPSULATION_CDR_LE ||
3428 encapsulation_id == ENCAPSULATION_PL_CDR_LE) {
3429 encapsulation_little_endian = 1;
3432 /* Encapsulation length (or option) */
3433 encapsulation_len = NEXT_guint16(tvb, offset, 0); /* Always big endian */
3434 proto_tree_add_text(rtps_parameter_sequence_tree,
3438 "encapsulation options: %04x",
3444 switch (encapsulation_id) {
3445 case ENCAPSULATION_CDR_LE:
3446 case ENCAPSULATION_CDR_BE:
3447 proto_tree_add_item(rtps_parameter_sequence_tree,
3452 encapsulation_little_endian);
3455 case ENCAPSULATION_PL_CDR_LE:
3456 case ENCAPSULATION_PL_CDR_BE:
3457 dissect_parameter_sequence(rtps_parameter_sequence_tree,
3460 encapsulation_little_endian,
3462 label, NULL, vendor_id);
3466 proto_tree_add_text(rtps_parameter_sequence_tree,
3476 /* ***********************************************************************
3477 * The dissector for octet seq (serialized data)
3478 * For a sequence of octets, the first word is always the sequence length
3479 * followed by all the raw bytes.
3481 static void dissect_octet_seq(proto_tree *tree,
3484 const char * label) {
3486 proto_tree * rtps_parameter_sequence_tree;
3492 /* Creates the sub-tree */
3493 ti = proto_tree_add_text(tree,
3498 rtps_parameter_sequence_tree = proto_item_add_subtree(ti,
3499 ett_rtps_serialized_data);
3503 length = NEXT_guint32(tvb, offset, 0); /* Always big endian */
3505 proto_tree_add_text(rtps_parameter_sequence_tree,
3509 "Sequence length: %d", length);
3513 proto_tree_add_item(rtps_parameter_sequence_tree,
3523 /* *********************************************************************** */
3524 /* * Parameter Sequence dissector * */
3525 /* *********************************************************************** */
3527 * It returns the new offset representing the point where the parameter
3528 * sequence terminates.
3529 * In case of protocol error, it returns 0 (cannot determine the end of
3530 * the sequence, the caller should be responsible to find the end of the
3531 * section if possible or pass the error back and abort dissecting the
3533 * If no error occurred, the returned value is ALWAYS > than the offset passed.
3535 * Note: even if tree==NULL, we still have to go through the PID because
3536 * since RTPS 2.1, the status info is now stored in a PID (and the
3537 * status info is required to format the INFO column).
3539 #define ENSURE_LENGTH(size) \
3540 if (param_length < size) { \
3541 proto_tree_add_text(rtps_parameter_tree, \
3542 tvb, offset, param_length, \
3543 "RTPS PROTOCOL ERROR: parameter value too small"\
3544 " (must be at least %d octets)", size); \
3548 static gint dissect_parameter_sequence(proto_tree *tree,
3554 guint32 *pStatusInfo,
3555 guint16 vendor_id) {
3556 proto_item * ti = NULL;
3557 proto_tree * rtps_parameter_sequence_tree = NULL;
3558 proto_tree * rtps_parameter_tree = NULL;
3559 guint16 parameter, param_length;
3560 guint8 buffer[MAX_PARAM_SIZE];
3561 gint original_offset = offset;
3565 ti = proto_tree_add_text(tree,
3570 rtps_parameter_sequence_tree = proto_item_add_subtree(ti,
3571 ett_rtps_parameter_sequence);
3574 /* Loop through all the parameters defined until PID_SENTINEL is found */
3576 size -= offset - original_offset;
3578 proto_tree_add_text(tree,
3582 "RTPS PROTOCOL ERROR: not enough bytes to read "
3583 " the next parameter");
3586 original_offset = offset;
3588 /* Reads parameter and create the sub tree. At this point we don't know
3589 * the final string that will identify the node or its length. It will
3592 parameter = NEXT_guint16(tvb, offset, little_endian);
3594 ti = proto_tree_add_text(rtps_parameter_sequence_tree,
3599 val_to_str(parameter, parameter_id_vals,
3600 "Unknown (0x%04x)"));
3601 rtps_parameter_tree = proto_item_add_subtree(ti, ett_rtps_parameter);
3602 proto_tree_add_uint_format(rtps_parameter_tree,
3603 hf_rtps_parameter_id,
3608 "parameterId: 0x%04x (%s)",
3610 val_to_str(parameter, parameter_id_vals,
3615 if (parameter == PID_SENTINEL) {
3616 /* PID_SENTINEL closes the parameter list, (length is ignored) */
3620 /* parameter length */
3621 param_length = NEXT_guint16(tvb, offset, little_endian);
3623 proto_tree_add_item(rtps_parameter_tree,
3624 hf_rtps_parameter_length,
3631 /* Make sure we have enough bytes for the param value */
3632 if (size-4 < param_length) {
3634 proto_tree_add_text(tree,
3638 "RTPS PROTOCOL ERROR: not enough bytes to read"
3639 " the parameter value");
3644 /* Sets the end of this item (now we know it!) */
3646 proto_item_set_len(ti, param_length+4);
3649 /* Do a shortcut when tree == NULL. In this case we only care of
3653 if (parameter == PID_STATUS_INFO) {
3654 if (pStatusInfo != NULL) {
3655 *pStatusInfo = NEXT_guint32(tvb, offset, little_endian);
3658 offset += param_length;
3664 /* 0...2...........7...............15.............23...............31
3665 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3666 * | PID_STATUS_INFO | 0x0004 |
3667 * +---------------+---------------+---------------+---------------+
3668 * | long statusInfo |
3669 * +---------------+---------------+---------------+---------------+
3671 case PID_STATUS_INFO: {
3672 guint32 si = 0xffffffff;
3674 si = rtps_util_add_long(rtps_parameter_tree,
3677 hf_rtps_param_status_info,
3678 FALSE, /* ALWAYS in network byte order (big endian) */
3679 TRUE, /* Is Hex ? */
3680 FALSE, /* Is Signed ? */
3681 NULL, /* No Label, use the protocol item ID */
3684 if (pStatusInfo != NULL) {
3690 /* 0...2...........7...............15.............23...............31
3691 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3692 * | PID_DIRECTED_WRITE | 0x0010 |
3693 * +---------------+---------------+---------------+---------------+
3696 * | octet[12] guidPrefix |
3699 * +---------------+---------------+---------------+---------------+
3700 * | octet[4] entityId |
3701 * +---------------+---------------+---------------+---------------+
3703 case PID_DIRECTED_WRITE: {
3707 rtps_util_add_guid_prefix(rtps_parameter_tree,
3710 hf_rtps_sm_guid_prefix,
3717 rtps_util_add_entity_id(rtps_parameter_tree,
3720 hf_rtps_sm_entity_id,
3721 hf_rtps_sm_entity_id_key,
3722 hf_rtps_sm_entity_id_kind,
3726 memset(buffer, 0, MAX_PARAM_SIZE);
3727 for (i = 0; i < 16; ++i) {
3728 guidPart = tvb_get_guint8(tvb, offset+i);
3729 g_snprintf(buffer+strlen(buffer), MAX_PARAM_SIZE-(gulong)strlen(buffer),
3731 if (i == 3 || i == 7 || i == 11) g_strlcat(buffer, ":", MAX_PARAM_SIZE);
3737 /* 0...2...........7...............15.............23...............31
3738 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3739 * | PID_KEY_HASH | xxxx |
3740 * +---------------+---------------+---------------+---------------+
3743 * | octet[xxxx] guid |
3746 * +---------------+---------------+---------------+---------------+
3747 * Differently from the other GUID, the KEY_HASH parameter may have
3748 * variable length in the future.
3749 * As consequence, no interpretation is performed here (and no check
3752 case PID_KEY_HASH: {
3755 g_strlcat(buffer, "guid: ", MAX_PARAM_SIZE);
3756 for (i = 0; i < param_length; ++i) {
3757 guidPart = tvb_get_guint8(tvb, offset+i);
3758 g_snprintf(buffer+strlen(buffer), MAX_PARAM_SIZE-(gulong)strlen(buffer),
3760 if (( ((i+1) % 4) == 0 ) && (i != param_length-1) )
3761 g_strlcat(buffer, ":", MAX_PARAM_SIZE);
3763 proto_tree_add_text(rtps_parameter_tree,
3773 /* 0...2...........7...............15.............23...............31
3774 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3775 * | PID_PARTICIPANT_LEASE_DURATION| 0x0008 |
3776 * +---------------+---------------+---------------+---------------+
3777 * | long NtpTime.seconds |
3778 * +---------------+---------------+---------------+---------------+
3779 * | unsigned long NtpTime.fraction |
3780 * +---------------+---------------+---------------+---------------+
3782 case PID_PARTICIPANT_LEASE_DURATION:
3784 rtps_util_add_ntp_time(rtps_parameter_tree,
3794 /* 0...2...........7...............15.............23...............31
3795 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3796 * | PID_TIME_BASED_FILTER | 0x0008 |
3797 * +---------------+---------------+---------------+---------------+
3798 * | long NtpTime.seconds |
3799 * +---------------+---------------+---------------+---------------+
3800 * | unsigned long NtpTime.fraction |
3801 * +---------------+---------------+---------------+---------------+
3803 case PID_TIME_BASED_FILTER:
3805 rtps_util_add_ntp_time(rtps_parameter_tree,
3809 "minimum_separation",
3814 /* 0...2...........7...............15.............23...............31
3815 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3816 * | PID_TOPIC_NAME | length |
3817 * +---------------+---------------+---------------+---------------+
3818 * | unsigned long String.length |
3819 * +---------------+---------------+---------------+---------------+
3820 * | str[0] | str[1] | str[2] | str[3] |
3821 * +---------------+---------------+---------------+---------------+
3823 * +---------------+---------------+---------------+---------------+
3825 case PID_TOPIC_NAME:
3826 rtps_util_add_string(rtps_parameter_tree,
3829 hf_rtps_param_topic_name,
3831 NULL, /* No label, use hf param */
3837 /* 0...2...........7...............15.............23...............31
3838 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3839 * | PID_OWNERSHIP_STRENGTH | 0x0004 |
3840 * +---------------+---------------+---------------+---------------+
3842 * +---------------+---------------+---------------+---------------+
3844 case PID_OWNERSHIP_STRENGTH:
3846 rtps_util_add_long(rtps_parameter_tree,
3849 hf_rtps_param_strength,
3851 FALSE, /* Is Hex ? */
3852 TRUE, /* Is Signed ? */
3853 NULL, /* No Label, use the protocol item ID */
3858 /* 0...2...........7...............15.............23...............31
3859 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3860 * | PID_TYPE_NAME | length |
3861 * +---------------+---------------+---------------+---------------+
3862 * | unsigned long String.length |
3863 * +---------------+---------------+---------------+---------------+
3864 * | str[0] | str[1] | str[2] | str[3] |
3865 * +---------------+---------------+---------------+---------------+
3867 * +---------------+---------------+---------------+---------------+
3870 rtps_util_add_string(rtps_parameter_tree,
3873 hf_rtps_param_type_name,
3875 NULL, /* No label, use hf param */
3882 /* 0...2...........7...............15.............23...............31
3883 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3884 * | PID_XXXXXXXXXXX | 0x0004 |
3885 * +---------------+---------------+---------------+---------------+
3887 * +---------------+---------------+---------------+---------------+
3889 case PID_METATRAFFIC_MULTICAST_PORT:
3890 case PID_METATRAFFIC_UNICAST_PORT:
3891 case PID_DEFAULT_UNICAST_PORT:
3893 rtps_util_add_port(rtps_parameter_tree,
3904 /* 0...2...........7...............15.............23...............31
3905 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3906 * | PID_EXPECTS_INLINE_QOS | 0x0004 |
3907 * +---------------+---------------+---------------+---------------+
3908 * | boolean | N O T U S E D |
3909 * +---------------+---------------+---------------+---------------+
3911 case PID_EXPECTS_INLINE_QOS:
3913 rtps_util_add_boolean(rtps_parameter_tree,
3921 /* 0...2...........7...............15.............23...............31
3922 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3923 * | PID_XXXXXXXXXXX | length |
3924 * +---------------+---------------+---------------+---------------+
3925 * | unsigned long ip_address |
3926 * +---------------+---------------+---------------+---------------+
3928 case PID_METATRAFFIC_MULTICAST_IPADDRESS:
3929 case PID_DEFAULT_UNICAST_IPADDRESS:
3930 case PID_MULTICAST_IPADDRESS:
3931 case PID_METATRAFFIC_UNICAST_IPADDRESS:
3932 rtps_util_add_ipv4_address_t(rtps_parameter_tree,
3943 /* 0...2...........7...............15.............23...............31
3944 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3945 * | PID_PROTOCOL_VERSION | 0x0004 |
3946 * +---------------+---------------+---------------+---------------+
3947 * | uint8 major | uint8 minor | N O T U S E D |
3948 * +---------------+---------------+---------------+---------------+
3950 case PID_PROTOCOL_VERSION: {
3955 major = tvb_get_guint8(tvb, offset);
3956 minor = tvb_get_guint8(tvb, offset+1);
3957 g_snprintf(buffer, MAX_PARAM_SIZE, "%d.%d", major, minor);
3958 proto_tree_add_text(rtps_parameter_tree,
3962 "protocolVersion: %s",
3967 /* 0...2...........7...............15.............23...............31
3968 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3969 * | PID_VENDOR_ID | 0x0004 |
3970 * +---------------+---------------+---------------+---------------+
3971 * | uint8 major | uint8 minor | N O T U S E D |
3972 * +---------------+---------------+---------------+---------------+
3976 rtps_util_add_vendor_id(NULL,
3981 proto_tree_add_text(rtps_parameter_tree,
3991 /* 0...2...........7...............15.............23...............31
3992 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3993 * | PID_RELIABILITY | 0x0004 |
3994 * +---------------+---------------+---------------+---------------+
3995 * | unsigned long kind |
3996 * +---------------+---------------+---------------+---------------+
3998 case PID_RELIABILITY_OFFERED: /* Deprecated */
3999 case PID_RELIABILITY:
4001 rtps_util_add_kind_qos(rtps_parameter_tree,
4006 reliability_qos_vals,
4012 /* 0...2...........7...............15.............23...............31
4013 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4014 * | PID_LIVELINESS | 0x000c |
4015 * +---------------+---------------+---------------+---------------+
4016 * | unsigned long kind |
4017 * +---------------+---------------+---------------+---------------+
4018 * | long NtpTime.seconds |
4019 * +---------------+---------------+---------------+---------------+
4020 * | unsigned long NtpTime.fraction |
4021 * +---------------+---------------+---------------+---------------+
4022 * NDDS 3.1 sends only 'kind' on the wire.
4025 case PID_LIVELINESS_OFFERED: /* Deprecated */
4026 case PID_LIVELINESS:
4028 rtps_util_add_liveliness_qos(rtps_parameter_tree,
4037 /* 0...2...........7...............15.............23...............31
4038 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4039 * | PID_DURABILITY | 0x0004 |
4040 * +---------------+---------------+---------------+---------------+
4041 * | unsigned long kind |
4042 * +---------------+---------------+---------------+---------------+
4044 case PID_DURABILITY:
4046 rtps_util_add_kind_qos(rtps_parameter_tree,
4051 durability_qos_vals,
4056 /* 0...2...........7...............15.............23...............31
4057 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4058 * | PID_DURABILITY_SERVICE | 0x0004 |
4059 * +---------------+---------------+---------------+---------------+
4060 * | long NtpTime.seconds |
4061 * +---------------+---------------+---------------+---------------+
4062 * | unsigned long NtpTime.fraction |
4063 * +---------------+---------------+---------------+---------------+
4064 * | unsigned long kind |
4065 * +---------------+---------------+---------------+---------------+
4066 * | long history_depth |
4067 * +---------------+---------------+---------------+---------------+
4068 * | long max_samples |
4069 * +---------------+---------------+---------------+---------------+
4070 * | long max_instances |
4071 * +---------------+---------------+---------------+---------------+
4072 * | long max_samples_per_instance |
4073 * +---------------+---------------+---------------+---------------+
4075 case PID_DURABILITY_SERVICE:
4077 rtps_util_add_durability_service_qos(rtps_parameter_tree,
4086 /* 0...2...........7...............15.............23...............31
4087 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4088 * | PID_OWNERSHIP | 0x0004 |
4089 * +---------------+---------------+---------------+---------------+
4090 * | unsigned long kind |
4091 * +---------------+---------------+---------------+---------------+
4093 case PID_OWNERSHIP_OFFERED: /* Deprecated */
4096 rtps_util_add_kind_qos(rtps_parameter_tree,
4107 /* 0...2...........7...............15.............23...............31
4108 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4109 * | PID_TRANSPORT_PRIORITY | 0x0004 |
4110 * +---------------+---------------+---------------+---------------+
4111 * | unsigned long value |
4112 * +---------------+---------------+---------------+---------------+
4114 case PID_TRANSPORT_PRIORITY:
4116 rtps_util_add_long(rtps_parameter_tree,
4119 -1, /* No protocol ID, use label below */
4121 FALSE, /* Is Hex ? */
4122 FALSE, /* Is Signed ? */
4128 /* 0...2...........7...............15.............23...............31
4129 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4130 * | PID_PRESENTATION | 0x0008 |
4131 * +---------------+---------------+---------------+---------------+
4132 * | unsigned long kind |
4133 * +---------------+---------------+---------------+---------------+
4134 * | boolean | boolean | N O T U S E D |
4135 * +---------------+---------------+---------------+---------------+
4137 case PID_PRESENTATION_OFFERED: /* Deprecated */
4138 case PID_PRESENTATION:
4140 g_strlcpy(buffer, "{ ", MAX_PARAM_SIZE);
4141 rtps_util_add_kind_qos(rtps_parameter_tree,
4146 presentation_qos_vals,
4147 buffer+strlen(buffer),
4148 MAX_PARAM_SIZE-strlen(buffer));
4149 g_strlcat(buffer, ", ", MAX_PARAM_SIZE);
4150 rtps_util_add_boolean(rtps_parameter_tree,
4154 buffer+strlen(buffer),
4155 MAX_PARAM_SIZE-strlen(buffer));
4156 g_strlcat(buffer, ", ", MAX_PARAM_SIZE);
4157 rtps_util_add_boolean(rtps_parameter_tree,
4161 buffer+strlen(buffer),
4162 MAX_PARAM_SIZE-strlen(buffer));
4163 g_strlcat(buffer, " }", MAX_PARAM_SIZE);
4167 /* 0...2...........7...............15.............23...............31
4168 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4169 * | PID_DEADLINE | 0x0008 |
4170 * +---------------+---------------+---------------+---------------+
4171 * | long NtpTime.seconds |
4172 * +---------------+---------------+---------------+---------------+
4173 * | unsigned long NtpTime.fraction |
4174 * +---------------+---------------+---------------+---------------+
4176 case PID_DEADLINE_OFFERED: /* Deprecated */
4179 rtps_util_add_ntp_time(rtps_parameter_tree,
4188 /* 0...2...........7...............15.............23...............31
4189 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4190 * | PID_DESTINATION_ORDER | 0x0004 |
4191 * +---------------+---------------+---------------+---------------+
4192 * | unsigned long kind |
4193 * +---------------+---------------+---------------+---------------+
4195 case PID_DESTINATION_ORDER_OFFERED: /* Deprecated */
4196 case PID_DESTINATION_ORDER:
4198 rtps_util_add_kind_qos(rtps_parameter_tree,
4203 destination_order_qos_vals,
4209 /* 0...2...........7...............15.............23...............31
4210 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4211 * | PID_LATENCY_BUDGET | 0x0008 |
4212 * +---------------+---------------+---------------+---------------+
4213 * | long NtpTime.seconds |
4214 * +---------------+---------------+---------------+---------------+
4215 * | unsigned long NtpTime.fraction |
4216 * +---------------+---------------+---------------+---------------+
4218 case PID_LATENCY_BUDGET_OFFERED:
4219 case PID_LATENCY_BUDGET:
4221 rtps_util_add_ntp_time(rtps_parameter_tree,
4231 /* 0...2...........7...............15.............23...............31
4232 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4233 * | PID_PARTITION | length |
4234 * +---------------+---------------+---------------+---------------+
4235 * | unsigned long sequence_size |
4236 * +---------------+---------------+---------------+---------------+
4237 * | unsigned long string[0].size |
4238 * +---------------+---------------+---------------+---------------+
4239 * | string[0][0] | string[0][1] | string[0][2] | string[0][3] |
4240 * +---------------+---------------+---------------+---------------+
4242 * +---------------+---------------+---------------+---------------+
4243 * The value is a sequence of strings.
4245 case PID_PARTITION_OFFERED: /* Deprecated */
4248 rtps_util_add_seq_string(rtps_parameter_tree,
4258 /* 0...2...........7...............15.............23...............31
4259 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4260 * | PID_LIFESPAN | 0x0008 |
4261 * +---------------+---------------+---------------+---------------+
4262 * | long NtpTime.seconds |
4263 * +---------------+---------------+---------------+---------------+
4264 * | unsigned long NtpTime.fraction |
4265 * +---------------+---------------+---------------+---------------+
4269 rtps_util_add_ntp_time(rtps_parameter_tree,
4279 /* 0...2...........7...............15.............23...............31
4280 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4281 * | PID_USER_DATA | length |
4282 * +---------------+---------------+---------------+---------------+
4283 * | unsigned long sequence_size |
4284 * +---------------+---------------+---------------+---------------+
4285 * | octet[0] | octet[1] | octet[2] | octet[3] |
4286 * +---------------+---------------+---------------+---------------+
4288 * +---------------+---------------+---------------+---------------+
4292 rtps_util_add_seq_octets(rtps_parameter_tree,
4297 hf_rtps_param_user_data,
4303 /* 0...2...........7...............15.............23...............31
4304 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4305 * | PID_GROUP_DATA | length |
4306 * +---------------+---------------+---------------+---------------+
4307 * | unsigned long sequence_size |
4308 * +---------------+---------------+---------------+---------------+
4309 * | octet[0] | octet[1] | octet[2] | octet[3] |
4310 * +---------------+---------------+---------------+---------------+
4312 * +---------------+---------------+---------------+---------------+
4314 case PID_GROUP_DATA:
4316 rtps_util_add_seq_octets(rtps_parameter_tree,
4321 hf_rtps_param_group_data,
4326 /* 0...2...........7...............15.............23...............31
4327 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4328 * | PID_TOPIC_DATA | length |
4329 * +---------------+---------------+---------------+---------------+
4330 * | unsigned long sequence_size |
4331 * +---------------+---------------+---------------+---------------+
4332 * | octet[0] | octet[1] | octet[2] | octet[3] |
4333 * +---------------+---------------+---------------+---------------+
4335 * +---------------+---------------+---------------+---------------+
4337 case PID_TOPIC_DATA:
4339 rtps_util_add_seq_octets(rtps_parameter_tree,
4344 hf_rtps_param_topic_data,
4349 /* 0...2...........7...............15.............23...............31
4350 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4351 * | PID_UNICAST_LOCATOR | 0x0018 |
4352 * +---------------+---------------+---------------+---------------+
4354 * +---------------+---------------+---------------+---------------+
4356 * +---------------+---------------+---------------+---------------+
4357 * | ipv6addr[0] | ipv6addr[1] | ipv6addr[2] | ipv6addr[3] |
4358 * +---------------+---------------+---------------+---------------+
4359 * | ipv6addr[4] | ipv6addr[5] | ipv6addr[6] | ipv6addr[7] |
4360 * +---------------+---------------+---------------+---------------+
4361 * | ipv6addr[8] | ipv6addr[9] | ipv6addr[10] | ipv6addr[11] |
4362 * +---------------+---------------+---------------+---------------+
4363 * | ipv6addr[12] | ipv6addr[13] | ipv6addr[14] | ipv6addr[15] |
4364 * +---------------+---------------+---------------+---------------+
4366 case PID_UNICAST_LOCATOR:
4368 rtps_util_add_locator_t(rtps_parameter_tree,
4378 /* 0...2...........7...............15.............23...............31
4379 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4380 * | PID_DEFAULT_MULTICAST_LOCATOR | 0x0018 |
4381 * +---------------+---------------+---------------+---------------+
4383 * +---------------+---------------+---------------+---------------+
4385 * +---------------+---------------+---------------+---------------+
4386 * | ipv6addr[0] | ipv6addr[1] | ipv6addr[2] | ipv6addr[3] |
4387 * +---------------+---------------+---------------+---------------+
4388 * | ipv6addr[4] | ipv6addr[5] | ipv6addr[6] | ipv6addr[7] |
4389 * +---------------+---------------+---------------+---------------+
4390 * | ipv6addr[8] | ipv6addr[9] | ipv6addr[10] | ipv6addr[11] |
4391 * +---------------+---------------+---------------+---------------+
4392 * | ipv6addr[12] | ipv6addr[13] | ipv6addr[14] | ipv6addr[15] |
4393 * +---------------+---------------+---------------+---------------+
4395 case PID_DEFAULT_MULTICAST_LOCATOR:
4397 rtps_util_add_locator_t(rtps_parameter_tree,
4408 /* 0...2...........7...............15.............23...............31
4409 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4410 * | PID_MULTICAST_LOCATOR | 0x0018 |
4411 * +---------------+---------------+---------------+---------------+
4413 * +---------------+---------------+---------------+---------------+
4415 * +---------------+---------------+---------------+---------------+
4416 * | ipv6addr[0] | ipv6addr[1] | ipv6addr[2] | ipv6addr[3] |
4417 * +---------------+---------------+---------------+---------------+
4418 * | ipv6addr[4] | ipv6addr[5] | ipv6addr[6] | ipv6addr[7] |
4419 * +---------------+---------------+---------------+---------------+
4420 * | ipv6addr[8] | ipv6addr[9] | ipv6addr[10] | ipv6addr[11] |
4421 * +---------------+---------------+---------------+---------------+
4422 * | ipv6addr[12] | ipv6addr[13] | ipv6addr[14] | ipv6addr[15] |
4423 * +---------------+---------------+---------------+---------------+
4425 case PID_MULTICAST_LOCATOR:
4427 rtps_util_add_locator_t(rtps_parameter_tree,
4437 /* 0...2...........7...............15.............23...............31
4438 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4439 * | PID_DEFAULT_UNICAST_LOCATOR | 0x0018 |
4440 * +---------------+---------------+---------------+---------------+
4442 * +---------------+---------------+---------------+---------------+
4444 * +---------------+---------------+---------------+---------------+
4445 * | ipv6addr[0] | ipv6addr[1] | ipv6addr[2] | ipv6addr[3] |
4446 * +---------------+---------------+---------------+---------------+
4447 * | ipv6addr[4] | ipv6addr[5] | ipv6addr[6] | ipv6addr[7] |
4448 * +---------------+---------------+---------------+---------------+
4449 * | ipv6addr[8] | ipv6addr[9] | ipv6addr[10] | ipv6addr[11] |
4450 * +---------------+---------------+---------------+---------------+
4451 * | ipv6addr[12] | ipv6addr[13] | ipv6addr[14] | ipv6addr[15] |
4452 * +---------------+---------------+---------------+---------------+
4454 case PID_DEFAULT_UNICAST_LOCATOR:
4456 rtps_util_add_locator_t(rtps_parameter_tree,
4466 /* 0...2...........7...............15.............23...............31
4467 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4468 * | PID_METATRAFFIC_UNICAST_LOC...| 0x0018 |
4469 * +---------------+---------------+---------------+---------------+
4471 * +---------------+---------------+---------------+---------------+
4473 * +---------------+---------------+---------------+---------------+
4474 * | ipv6addr[0] | ipv6addr[1] | ipv6addr[2] | ipv6addr[3] |
4475 * +---------------+---------------+---------------+---------------+
4476 * | ipv6addr[4] | ipv6addr[5] | ipv6addr[6] | ipv6addr[7] |
4477 * +---------------+---------------+---------------+---------------+
4478 * | ipv6addr[8] | ipv6addr[9] | ipv6addr[10] | ipv6addr[11] |
4479 * +---------------+---------------+---------------+---------------+
4480 * | ipv6addr[12] | ipv6addr[13] | ipv6addr[14] | ipv6addr[15] |
4481 * +---------------+---------------+---------------+---------------+
4483 case PID_METATRAFFIC_UNICAST_LOCATOR:
4485 rtps_util_add_locator_t(rtps_parameter_tree,
4495 /* 0...2...........7...............15.............23...............31
4496 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4497 * | PID_METATRAFFIC_MULTICAST_L...| 0x0018 |
4498 * +---------------+---------------+---------------+---------------+
4500 * +---------------+---------------+---------------+---------------+
4502 * +---------------+---------------+---------------+---------------+
4503 * | ipv6addr[0] | ipv6addr[1] | ipv6addr[2] | ipv6addr[3] |
4504 * +---------------+---------------+---------------+---------------+
4505 * | ipv6addr[4] | ipv6addr[5] | ipv6addr[6] | ipv6addr[7] |
4506 * +---------------+---------------+---------------+---------------+
4507 * | ipv6addr[8] | ipv6addr[9] | ipv6addr[10] | ipv6addr[11] |
4508 * +---------------+---------------+---------------+---------------+
4509 * | ipv6addr[12] | ipv6addr[13] | ipv6addr[14] | ipv6addr[15] |
4510 * +---------------+---------------+---------------+---------------+
4512 case PID_METATRAFFIC_MULTICAST_LOCATOR:
4514 rtps_util_add_locator_t(rtps_parameter_tree,
4524 /* 0...2...........7...............15.............23...............31
4525 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4526 * | PID_PARTICIPANT_MANUAL_LIVE...| 0x0004 |
4527 * +---------------+---------------+---------------+---------------+
4528 * | long livelinessEpoch |
4529 * +---------------+---------------+---------------+---------------+
4531 case PID_PARTICIPANT_BUILTIN_ENDPOINTS:
4532 case PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT:
4534 rtps_util_add_long(rtps_parameter_tree,
4537 -1, /* No protocol ID, use label below */
4539 TRUE, /* Is Hex ? */
4540 FALSE, /* Is Signed ? */
4546 /* 0...2...........7...............15.............23...............31
4547 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4548 * | PID_HISTORY | 0x0004 |
4549 * +---------------+---------------+---------------+---------------+
4551 * +---------------+---------------+---------------+---------------+
4553 * +---------------+---------------+---------------+---------------+
4557 g_strlcpy(buffer, "{ ", MAX_PARAM_SIZE);
4558 rtps_util_add_kind_qos(rtps_parameter_tree,
4564 buffer+strlen(buffer),
4565 MAX_PARAM_SIZE-strlen(buffer));
4566 g_strlcat(buffer, ", ", MAX_PARAM_SIZE);
4568 rtps_util_add_long(rtps_parameter_tree,
4571 -1, /* No protocol ID, use label below */
4573 FALSE, /* Is Hex ? */
4574 TRUE, /* Is Signed ? */
4576 buffer + strlen(buffer),
4577 MAX_PARAM_SIZE-strlen(buffer));
4578 g_strlcat(buffer, " }", MAX_PARAM_SIZE);
4582 /* 0...2...........7...............15.............23...............31
4583 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4584 * | PID_RESOURCE_LIMIT | 0x0004 |
4585 * +---------------+---------------+---------------+---------------+
4586 * | long max_samples |
4587 * +---------------+---------------+---------------+---------------+
4588 * | long max_instances |
4589 * +---------------+---------------+---------------+---------------+
4590 * | long max_samples_per_instances |
4591 * +---------------+---------------+---------------+---------------+
4593 case PID_RESOURCE_LIMIT:
4595 g_strlcpy(buffer, "{ ", MAX_PARAM_SIZE);
4596 rtps_util_add_long(rtps_parameter_tree,
4599 -1, /* No protocol ID, use label below */
4601 FALSE, /* Is Hex ? */
4602 TRUE, /* Is Signed ? */
4604 buffer + strlen(buffer),
4605 MAX_PARAM_SIZE-strlen(buffer));
4606 g_strlcat(buffer, ", ", MAX_PARAM_SIZE);
4607 rtps_util_add_long(rtps_parameter_tree,
4610 -1, /* No protocol ID, use label below */
4612 FALSE, /* Is Hex ? */
4613 TRUE, /* Is Signed ? */
4615 buffer + strlen(buffer),
4616 MAX_PARAM_SIZE-strlen(buffer));
4617 g_strlcat(buffer, ", ", MAX_PARAM_SIZE);
4619 rtps_util_add_long(rtps_parameter_tree,
4622 -1, /* No protocol ID, use label below */
4624 FALSE, /* Is Hex ? */
4625 TRUE, /* Is Signed ? */
4626 "max_samples_per_instances",
4627 buffer + strlen(buffer),
4628 MAX_PARAM_SIZE-strlen(buffer));
4629 g_strlcat(buffer, " }", MAX_PARAM_SIZE);
4633 /* 0...2...........7...............15.............23...............31
4634 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4635 * | PID_CONTENT_FILTER_PROPERTY | length |
4636 * +---------------+---------------+---------------+---------------+
4637 * | unsigned long String1.length |
4638 * +---------------+---------------+---------------+---------------+
4639 * | str1[0] | str1[1] | str1[2] | str1[3] |
4640 * +---------------+---------------+---------------+---------------+
4642 * +---------------+---------------+---------------+---------------+
4643 * | unsigned long String2.length |
4644 * +---------------+---------------+---------------+---------------+
4645 * | str2[0] | str2[1] | str2[2] | str2[3] |
4646 * +---------------+---------------+---------------+---------------+
4648 * +---------------+---------------+---------------+---------------+
4649 * | unsigned long String3.length |
4650 * +---------------+---------------+---------------+---------------+
4651 * | str3[0] | str3[1] | str3[2] | str3[3] |
4652 * +---------------+---------------+---------------+---------------+
4654 * +---------------+---------------+---------------+---------------+
4655 * | unsigned long String4.length |
4656 * +---------------+---------------+---------------+---------------+
4657 * | str4[0] | str4[1] | str4[2] | str4[3] |
4658 * +---------------+---------------+---------------+---------------+
4660 * +---------------+---------------+---------------+---------------+
4662 * | Filter Parameters |
4664 * +---------------+---------------+---------------+---------------+
4666 * String1: ContentFilterName
4667 * String2: RelatedTopicName
4668 * String3: FilterName
4669 * String4: FilterExpression
4670 * FilterParameters: sequence of Strings
4672 * Note: those strings starts all to a word-aligned (4 bytes) offset
4674 case PID_CONTENT_FILTER_PROPERTY: {
4675 guint32 temp_offset = offset;
4677 temp_offset = rtps_util_add_string(rtps_parameter_tree,
4680 hf_rtps_param_content_filter_name,
4682 NULL, /* No label, use hf param */
4685 temp_offset = rtps_util_add_string(rtps_parameter_tree,
4688 hf_rtps_param_related_topic_name,
4693 temp_offset = rtps_util_add_string(rtps_parameter_tree,
4696 hf_rtps_param_filter_name,
4701 temp_offset = rtps_util_add_string(rtps_parameter_tree,
4709 temp_offset = rtps_util_add_seq_string(rtps_parameter_tree,
4720 /* 0...2...........7...............15.............23...............31
4721 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4722 * | PID_PROPERTY_LIST | length |
4723 * +---------------+---------------+---------------+---------------+
4724 * | unsigned long Seq.Length |
4725 * +---------------+---------------+---------------+---------------+
4729 * +---------------+---------------+---------------+---------------+
4733 * +---------------+---------------+---------------+---------------+
4737 * +---------------+---------------+---------------+---------------+
4745 * struct PROPERTY_LIST {
4746 * Sequence<PROPERTY> PropertyList;
4750 case PID_PROPERTY_LIST:
4751 case PID_PROPERTY_LIST_OLD:
4754 guint32 prev_offset;
4755 guint32 temp_offset;
4756 guint8 tempName[MAX_PARAM_SIZE];
4757 guint8 tempValue[MAX_PARAM_SIZE];
4758 guint32 seq_size = NEXT_guint32(tvb, offset, little_endian);
4759 g_snprintf(buffer, MAX_PARAM_SIZE, "%d properties", seq_size);
4761 proto_tree_add_text(rtps_parameter_tree,
4765 /* 123456789012345678901234567890|123456789012345678901234567890 */
4766 " Property Name | Property Value");
4768 proto_tree_add_text(rtps_parameter_tree,
4772 /* 123456789012345678901234567890|123456789012345678901234567890 */
4773 "------------------------------|------------------------------");
4775 temp_offset = offset+4;
4776 while(seq_size-- > 0) {
4777 prev_offset = temp_offset;
4778 temp_offset = rtps_util_add_string(NULL,
4786 temp_offset = rtps_util_add_string(NULL,
4794 proto_tree_add_text(rtps_parameter_tree,
4797 temp_offset - prev_offset,
4806 /* 0...2...........7...............15.............23...............31
4807 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4808 * | PID_CONTENT_FILTER_INFO | length |
4809 * +---------------+---------------+---------------+---------------+
4811 * +---------------+---------------+---------------+---------------+
4814 * struct CONTENT_FILTER_SIGNATURE {
4815 * sequence<long> filterBitmap;
4816 * sequence<FILTER_SIGNATURE, 4> filterSignature;
4820 * struct FILTER_SIGNATURE {
4821 * long filterSignature[4];
4824 case PID_CONTENT_FILTER_INFO: {
4825 guint32 temp_offset = offset;
4826 guint32 prev_offset;
4831 /* Dissect filter bitmap */
4832 temp_offset = rtps_util_add_seq_ulong(rtps_parameter_tree,
4838 FALSE, /* filterSignature: is_signed */
4841 /* Dissect sequence of FILTER_SIGNATURE */
4842 fs_elem = NEXT_guint32(tvb, temp_offset, little_endian);
4844 while (fs_elem-- > 0) {
4845 prev_offset = temp_offset;
4846 /* Dissect the next FILTER_SIGNATURE object */
4847 fs[0] = NEXT_guint32(tvb, temp_offset, little_endian);
4849 fs[1] = NEXT_guint32(tvb, temp_offset, little_endian);
4851 fs[2] = NEXT_guint32(tvb, temp_offset, little_endian);
4853 fs[3] = NEXT_guint32(tvb, temp_offset, little_endian);
4855 proto_tree_add_text(rtps_parameter_tree,
4858 temp_offset - prev_offset,
4859 "filterSignature: %08x %08x %08x %08x",
4860 fs[0], fs[1], fs[2], fs[3]);
4867 /* 0...2...........7...............15.............23...............31
4868 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4869 * | PID_COHERENT_SET | length |
4870 * +---------------+---------------+---------------+---------------+
4872 * + SequenceNumber seqNumber +
4874 * +---------------+---------------+---------------+---------------+
4876 case PID_COHERENT_SET:
4878 rtps_util_add_seq_number(rtps_parameter_tree,
4886 /* 0...2...........7...............15.............23...............31
4887 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4888 * | PID_BUILTIN_ENDPOINT_SET | length |
4889 * +---------------+---------------+---------------+---------------+
4891 * +---------------+---------------+---------------+---------------+
4893 case PID_BUILTIN_ENDPOINT_SET: {
4899 data = NEXT_guint32(tvb, offset, little_endian);
4900 for (i = 0; i < 32; ++i) {
4901 datamask = (1 << (31-i));
4902 bitbuf[i] = ((data & datamask) == datamask) ? '1':'0';
4905 proto_tree_add_text(rtps_parameter_tree,
4914 /* 0...2...........7...............15.............23...............31
4915 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4916 * | PID_TYPE_MAX_SIZE_SERIALIZED | length |
4917 * +---------------+---------------+---------------+---------------+
4919 * +---------------+---------------+---------------+---------------+
4921 case PID_TYPE_MAX_SIZE_SERIALIZED:
4923 rtps_util_add_long(rtps_parameter_tree,
4926 -1, /* No protocol ID, use label below */
4928 FALSE, /* Is Hex ? */
4929 FALSE, /* Is Signed ? */
4937 /* 0...2...........7...............15.............23...............31
4938 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4939 * | PID_ORIGINAL_WRITER_INFO | length |
4940 * +---------------+---------------+---------------+---------------+
4943 * | octet[12] guidPrefix |
4946 * +---------------+---------------+---------------+---------------+
4947 * | octet[4] entityId |
4948 * +---------------+---------------+---------------+---------------+
4950 * + SequenceNumber writerSeqNum +
4952 * +---------------+---------------+---------------+---------------+
4954 case PID_ORIGINAL_WRITER_INFO:
4956 rtps_util_add_guid_prefix(rtps_parameter_tree,
4959 hf_rtps_sm_guid_prefix,
4963 "virtualGUIDPrefix",
4966 rtps_util_add_entity_id(rtps_parameter_tree,
4969 hf_rtps_sm_entity_id,
4970 hf_rtps_sm_entity_id_key,
4971 hf_rtps_sm_entity_id_kind,
4973 "virtualGUIDSuffix",
4976 /* Sequence number */
4977 rtps_util_add_seq_number(rtps_parameter_tree,
4981 "virtualSeqNumber");
4984 /* 0...2...........7...............15.............23...............31
4985 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4986 * | PID_ENTITY_NAME | length |
4987 * +---------------+---------------+---------------+---------------+
4988 * | unsigned long String.length |
4989 * +---------------+---------------+---------------+---------------+
4990 * | str[0] | str[1] | str[2] | str[3] |
4991 * +---------------+---------------+---------------+---------------+
4993 * +---------------+---------------+---------------+---------------+
4995 case PID_ENTITY_NAME:
4996 rtps_util_add_string(rtps_parameter_tree,
4999 hf_rtps_param_entity_name,
5001 NULL, /* No label, use hf param */
5007 /* 0...2...........7...............15.............23...............31
5008 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5009 * | PID_PARTICIPANT_GUID | 0x0010 |
5010 * | PID_ENDPOINT_GUID | |
5011 * +---------------+---------------+---------------+---------------+
5012 * | guid[0] | guid[1] | guid[2] | guid[3] |
5013 * +---------------+---------------+---------------+---------------+
5014 * | guid[4] | guid[5] | guid[6] | guid[7] |
5015 * +---------------+---------------+---------------+---------------+
5016 * | guid[8] | guid[9] | guid[10] | guid[11] |
5017 * +---------------+---------------+---------------+---------------+
5018 * | guid[12] | guid[13] | guid[14] | guid[15] |
5019 * +---------------+---------------+---------------+---------------+
5021 case PID_PARTICIPANT_GUID:
5022 case PID_ENDPOINT_GUID:
5024 rtps_util_add_generic_guid(rtps_parameter_tree,
5033 /* 0...2...........7...............15.............23...............31
5034 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5035 * | PID_PARTICIPANT_ENTITY_ID | 0x0004 |
5036 * +---------------+---------------+---------------+---------------+
5037 * | entity[0] | entity[1] | entity[2] | entity[3] |
5038 * +---------------+---------------+---------------+---------------+
5040 case PID_PARTICIPANT_ENTITY_ID:
5042 rtps_util_add_generic_entity_id(rtps_parameter_tree,
5045 "Participant entity ID",
5050 /* 0...2...........7...............15.............23...............31
5051 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5052 * | PID_GROUP_GUID | 0x0010 |
5053 * +---------------+---------------+---------------+---------------+
5054 * | guid[0] | guid[1] | guid[2] | guid[3] |
5055 * +---------------+---------------+---------------+---------------+
5056 * | guid[4] | guid[5] | guid[6] | guid[7] |
5057 * +---------------+---------------+---------------+---------------+
5058 * | guid[8] | guid[9] | guid[10] | guid[11] |
5059 * +---------------+---------------+---------------+---------------+
5060 * | guid[12] | guid[13] | guid[14] | guid[15] |
5061 * +---------------+---------------+---------------+---------------+
5063 case PID_GROUP_GUID:
5065 rtps_util_add_generic_guid(rtps_parameter_tree,
5074 /* 0...2...........7...............15.............23...............31
5075 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5076 * | PID_GROUP_ENTITY_ID | 0x0004 |
5077 * +---------------+---------------+---------------+---------------+
5078 * | entity[0] | entity[1] | entity[2] | entity[3] |
5079 * +---------------+---------------+---------------+---------------+
5081 case PID_GROUP_ENTITY_ID:
5084 rtps_util_add_generic_entity_id(rtps_parameter_tree,
5097 /* ==================================================================
5098 * Here are all the deprecated items.
5101 case PID_PERSISTENCE:
5103 rtps_util_add_ntp_time(rtps_parameter_tree,
5112 case PID_TYPE_CHECKSUM:
5114 rtps_util_add_long(rtps_parameter_tree,
5120 FALSE, /* Is signed ? */
5126 case PID_EXPECTS_ACK:
5128 rtps_util_add_boolean(rtps_parameter_tree,
5136 case PID_MANAGER_KEY: {
5139 guint32 manager_key;
5142 while (param_length >= 4) {
5143 manager_key = NEXT_guint32(tvb, offset, little_endian);
5144 g_snprintf(buffer+strlen(buffer),
5145 MAX_PARAM_SIZE-(gulong)strlen(buffer),
5149 proto_tree_add_text(rtps_parameter_tree,
5153 "Key[%d]: 0x%X", i, manager_key);
5157 param_length -= 4; /* decrement count */
5159 offset += param_length;
5164 case PID_RECV_QUEUE_SIZE:
5165 case PID_SEND_QUEUE_SIZE:
5167 rtps_util_add_long(rtps_parameter_tree,
5173 FALSE, /* Is signed ? */
5180 case PID_VARGAPPS_SEQUENCE_NUMBER_LAST:
5182 rtps_util_add_seq_number(rtps_parameter_tree,
5186 "sequenceNumberLast");
5189 /* This is the default branch when we don't have enough information
5190 * on how to decode the parameter. It can be used also for known
5193 /* 0...2...........7...............15.............23...............31
5194 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5195 * | <pid_id> | 0x0000 |
5196 * +---------------+---------------+---------------+---------------+
5198 case PID_IS_RELIABLE:
5199 case PID_TYPE2_NAME:
5200 case PID_TYPE2_CHECKSUM:
5201 case PID_RELIABILITY_ENABLED:
5202 g_strlcpy(buffer, "[DEPRECATED] - Parameter not decoded", MAX_PARAM_SIZE);
5209 /* The following PIDS are vendor-specific */
5210 if (vendor_id == RTPS_VENDOR_RTI) {
5212 /* 0...2...........7...............15.............23...............31
5213 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5214 * | PID_PRODUCT_VERSION | length |
5215 * +---------------+---------------+---------------+---------------+
5216 * | uint8 major | uint8 minor | N O T U S E D |
5217 * +---------------+---------------+---------------+---------------+
5219 case PID_PRODUCT_VERSION: {
5226 major = tvb_get_guint8(tvb, offset);
5227 minor = tvb_get_guint8(tvb, offset+1);
5228 release = tvb_get_guint8(tvb, offset+2);
5229 revision = tvb_get_guint8(tvb, offset+3);
5230 g_snprintf(buffer, MAX_PARAM_SIZE, "%d.%d%c rev%d",
5231 major, minor, release, revision);
5232 proto_tree_add_text(rtps_parameter_tree,
5236 "productVersion: %s",
5241 /* 0...2...........7...............15.............23...............31
5242 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5243 * | PID_PLUGIN_PROMISCUITY_KIND | length |
5244 * +---------------+---------------+---------------+---------------+
5246 * +---------------+---------------+---------------+---------------+
5248 case PID_PLUGIN_PROMISCUITY_KIND: {
5251 val = NEXT_guint32(tvb, offset, little_endian);
5252 g_snprintf(buffer, MAX_PARAM_SIZE, "%s",
5253 val_to_str(val, plugin_promiscuity_kind_vals,
5256 proto_tree_add_text(rtps_parameter_tree,
5260 "promiscuityKind: %s",
5265 /* 0...2...........7...............15.............23...............31
5266 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5267 * | PID_ENTITY_VIRTUAL_GUID | length |
5268 * +---------------+---------------+---------------+---------------+
5271 * | octet[12] guidPrefix |
5274 * +---------------+---------------+---------------+---------------+
5275 * | octet[4] entityId |
5276 * +---------------+---------------+---------------+---------------+
5278 case PID_ENTITY_VIRTUAL_GUID:
5280 rtps_util_add_guid_prefix(rtps_parameter_tree,
5283 hf_rtps_sm_guid_prefix,
5287 "virtualGUIDPrefix",
5290 rtps_util_add_entity_id(rtps_parameter_tree,
5293 hf_rtps_sm_entity_id,
5294 hf_rtps_sm_entity_id_key,
5295 hf_rtps_sm_entity_id_kind,
5297 "virtualGUIDSuffix",
5302 /* 0...2...........7...............15.............23...............31
5303 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5304 * | PID_SERVICE_KIND | length |
5305 * +---------------+---------------+---------------+---------------+
5307 * +---------------+---------------+---------------+---------------+
5309 case PID_SERVICE_KIND: {
5312 val = NEXT_guint32(tvb, offset, little_endian);
5314 g_snprintf(buffer, MAX_PARAM_SIZE, "%s",
5315 val_to_str(val, service_kind_vals, "unknown (%04x)"));
5317 proto_tree_add_text(rtps_parameter_tree,
5326 /* 0...2...........7...............15.............23...............31
5327 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5328 * | PID_TYPECODE | length |
5329 * +---------------+---------------+---------------+---------------+
5331 * + Type code description +
5333 * +---------------+---------------+---------------+---------------+
5336 rtps_util_add_typecode(rtps_parameter_tree,
5340 0, /* indent level */
5346 -1, /* not a seq field */
5347 NULL, /* not an array */
5348 0); /* ndds 4.0 hack: init to false */
5351 /* 0...2...........7...............15.............23...............31
5352 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5353 * | PID_DISABLE_POSITIVE_ACKS | length |
5354 * +---------------+---------------+---------------+---------------+
5355 * | boolean value | = = = = = = = = u n u s e d = = = = = = = = |
5356 * +---------------+---------------+---------------+---------------+
5358 case PID_DISABLE_POSITIVE_ACKS:
5360 rtps_util_add_boolean(rtps_parameter_tree,
5363 "disablePositiveAcks",
5368 /* 0...2...........7...............15.............23...............31
5369 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5370 * | PID_LOCATOR_FILTER_LIST | length |
5371 * +---------------+---------------+---------------+---------------+
5372 * | unsigned long number_of_channels |
5373 * +---------------+---------------+---------------+---------------+
5375 * ~ String filter_name ~
5377 * +---------------+---------------+---------------+---------------+
5379 * ~ LocatorList ~ <----------+
5381 * +---------------+---------------+---------------+---------------+ For each|
5383 * ~ String filter_expression ~ |
5385 * +---------------+---------------+---------------+---------------+ <----------+
5387 case PID_LOCATOR_FILTER_LIST: {
5388 guint32 number_of_channels = 0;
5389 proto_tree *channel_tree = NULL;
5390 proto_item *ti_channel = NULL;
5391 char temp_buff[MAX_LABEL_SIZE];
5394 guint32 off = offset;
5397 number_of_channels = NEXT_guint32(tvb, off, little_endian);
5398 g_snprintf(buffer, MAX_PARAM_SIZE, "%d channels", number_of_channels);
5401 if (number_of_channels == 0) {
5402 /* Do not dissect the rest */
5403 proto_tree_add_text(rtps_parameter_tree,
5407 "numberOfChannels: %d", number_of_channels);
5412 off = rtps_util_add_string(rtps_parameter_tree,
5415 -1, /* hf_item not set */
5417 "filterName", /* label */
5418 NULL, /* buffer not set */
5419 0); /* buffer length */
5421 /* Foreach channel... */
5422 for (ch = 0; ch < number_of_channels; ++ch) {
5423 g_snprintf(temp_buff, MAX_LABEL_SIZE, "Channel[%u]", ch);
5426 ti_channel = proto_tree_add_text(rtps_parameter_tree,
5432 channel_tree = proto_item_add_subtree(ti_channel, ett_rtps_locator_filter_channel);
5434 off = rtps_util_add_locator_list(channel_tree,
5439 /* Filter expression */
5440 off = rtps_util_add_string(channel_tree,
5443 -1, /* hf_item not set */
5445 "filterExpression", /* label */
5446 NULL, /* buffer not set */
5447 0); /* buffer length */
5448 /* Now we know the length of the channel data, set the length */
5450 proto_item_set_len(ti_channel, (off - old_offset));
5452 } /* End of for each channel */
5454 } /* End of case PID_LOCATOR_FILTER_LIST */
5456 } /* End of switch for parameters for vendor RTI */
5457 } /* End of branch vendor RTI */
5459 /* Put here other branches if you are planning to dissect parameters
5460 * ID from different vendors.
5464 if (param_length > 0) {
5465 proto_tree_add_text(rtps_parameter_tree,
5472 } /* End main parameter switch */
5475 proto_item_append_text(ti, ": %s", buffer);
5478 offset += param_length;
5480 } /* for all the parameters */
5483 #undef ENSURE_LENGTH
5488 /* *********************************************************************** */
5490 /* *********************************************************************** */
5491 static void dissect_PAD(tvbuff_t *tvb,
5494 gboolean little_endian,
5495 int octets_to_next_header,
5497 char * info_summary_text,
5498 guint16 G_GNUC_UNUSED vendor_id) {
5499 /* 0...2...........7...............15.............23...............31
5500 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5501 * | PAD |X|X|X|X|X|X|X|E| octetsToNextHeader |
5502 * +---------------+---------------+---------------+---------------+
5505 rtps_util_decode_flags(tree, tvb, offset + 1, flags, PAD_FLAGS);
5507 if (octets_to_next_header != 0) {
5508 proto_tree_add_uint_format(tree,
5509 hf_rtps_sm_octets_to_next_header,
5513 octets_to_next_header,
5514 "octetsToNextHeader: %u (Error: should be ZERO)",
5515 octets_to_next_header);
5519 proto_tree_add_item(tree,
5520 hf_rtps_sm_octets_to_next_header,
5526 info_summary_append(info_summary_text, SUBMESSAGE_PAD, NULL);
5533 /* *********************************************************************** */
5535 /* *********************************************************************** */
5536 static void dissect_DATA(tvbuff_t *tvb,
5539 gboolean little_endian,
5540 int octets_to_next_header,
5542 char * info_summary_text,
5543 guint16 vendor_id) {
5546 * 0...2...........7...............15.............23...............31
5547 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5548 * | DATA |X|X|X|I|H|D|Q|E| octetsToNextHeader |
5549 * +---------------+---------------+---------------+---------------+
5550 * | EntityId readerEntityId |
5551 * +---------------+---------------+---------------+---------------+
5552 * | EntityId writerEntityId |
5553 * +---------------+---------------+---------------+---------------+
5555 * + SequenceNumber writerSeqNum +
5557 * +---------------+---------------+---------------+---------------+
5560 * | KeyHashPrefix keyHashPrefix [only if H==1] |
5563 * +---------------+---------------+---------------+---------------+
5564 * | KeyHashSuffix keyHashSuffix |
5565 * +---------------+---------------+---------------+---------------+
5566 * | StatusInfo statusInfo [only if I==1] |
5567 * +---------------+---------------+---------------+---------------+
5569 * ~ ParameterList inlineQos [only if Q==1] ~
5571 * +---------------+---------------+---------------+---------------+
5573 * ~ SerializedData serializedData [only if D==1] ~
5575 * +---------------+---------------+---------------+---------------+
5578 gint old_offset = offset;
5579 guint32 wid; /* Writer EntityID */
5580 guint32 status_info = 0xffffffff;
5582 rtps_util_decode_flags(tree, tvb, offset + 1, flags, DATA_FLAGS);
5585 /* Calculates the minimum length for this submessage */
5587 if ((flags & FLAG_DATA_Q) != 0) min_len += 4;
5588 if ((flags & FLAG_DATA_D) != 0) min_len += 4;
5589 if ((flags & FLAG_DATA_H) != 0) min_len += 12;
5591 if (octets_to_next_header < min_len) {
5592 if (tree) proto_tree_add_uint_format(tree,
5593 hf_rtps_sm_octets_to_next_header,
5597 octets_to_next_header,
5598 "octetsToNextHeader: %u (Error: should be >= %u)",
5599 octets_to_next_header,
5604 /* Skip decoding the entire packet if (tree == NULL)
5605 * Note that we still need to decode the statusInfo and the writer ID
5608 offset += 8; /* Skip to writer entity ID */
5609 wid = NEXT_guint32(tvb, offset, little_endian);
5610 offset += 12; /* Skip to keyHashPrefix */
5611 if ((flags & FLAG_DATA_H) != 0) {
5614 offset += 4; /* GUID Entity ID */
5615 if ((flags & FLAG_DATA_I) != 0) {
5616 status_info = NEXT_guint32(tvb, offset, little_endian);
5618 info_summary_append_ex(info_summary_text, SUBMESSAGE_DATA, wid, status_info);
5622 if (tree) proto_tree_add_item(tree,
5623 hf_rtps_sm_octets_to_next_header,
5631 /* readerEntityId */
5632 rtps_util_add_entity_id(tree,
5635 hf_rtps_sm_rdentity_id,
5636 hf_rtps_sm_rdentity_id_key,
5637 hf_rtps_sm_rdentity_id_kind,
5643 /* writerEntityId */
5644 rtps_util_add_entity_id(tree,
5647 hf_rtps_sm_wrentity_id,
5648 hf_rtps_sm_wrentity_id_key,
5649 hf_rtps_sm_wrentity_id_kind,
5656 /* Sequence number */
5657 rtps_util_add_seq_number(tree,
5664 /* If flag H is defined, read the GUID Prefix */
5665 if ((flags & FLAG_DATA_H) != 0) {
5666 rtps_util_add_guid_prefix(tree,
5669 hf_rtps_sm_guid_prefix,
5679 /* Flag H not set, use hostId, appId from the packet header */
5682 /* Complete the GUID by reading the Object ID */
5683 rtps_util_add_entity_id(tree,
5686 hf_rtps_sm_entity_id,
5687 hf_rtps_sm_entity_id_key,
5688 hf_rtps_sm_entity_id_kind,
5694 if ((flags & FLAG_DATA_I) != 0) {
5695 status_info = rtps_util_add_long(tree,
5709 if ((flags & FLAG_DATA_Q) != 0) {
5710 offset = dissect_parameter_sequence(tree,
5714 octets_to_next_header - (offset - old_offset) + 4,
5720 /* SerializedData */
5721 if ((flags & FLAG_DATA_D) != 0) {
5722 dissect_serialized_data(tree,
5725 octets_to_next_header - (offset - old_offset) + 4,
5729 info_summary_append_ex(info_summary_text, SUBMESSAGE_DATA, wid, status_info);
5733 /* *********************************************************************** */
5734 /* * D A T A _ F R A G * */
5735 /* *********************************************************************** */
5736 static void dissect_DATA_FRAG(tvbuff_t *tvb,
5739 gboolean little_endian,
5740 int octets_to_next_header,
5742 char *info_summary_text,
5743 guint16 vendor_id) {
5745 * 0...2...........7...............15.............23...............31
5746 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5747 * | DATA_FRAG |X|X|X|X|X|H|Q|E| octetsToNextHeader |
5748 * +---------------+---------------+---------------+---------------+
5749 * | EntityId readerEntityId |
5750 * +---------------+---------------+---------------+---------------+
5751 * | EntityId writerEntityId |
5752 * +---------------+---------------+---------------+---------------+
5754 * + SequenceNumber writerSeqNum +
5756 * +---------------+---------------+---------------+---------------+
5759 * | KeyHashPrefix keyHashPrefix [only if H==1] |
5762 * +---------------+---------------+---------------+---------------+
5763 * | KeyHashSuffix keyHashSuffix |
5764 * +---------------+---------------+---------------+---------------+
5765 * | FragmentNumber fragmentStartingNum |
5766 * +---------------+---------------+---------------+---------------+
5767 * | ushort fragmentsInSubmessage | ushort fragmentSize |
5768 * +---------------+---------------+---------------+---------------+
5769 * | unsigned long sampleSize |
5770 * +---------------+---------------+---------------+---------------+
5772 * ~ ParameterList inlineQos [only if Q==1] ~
5774 * +---------------+---------------+---------------+---------------+
5776 * ~ SerializedData serializedData ~
5778 * +---------------+---------------+---------------+---------------+
5782 gint old_offset = offset;
5783 rtps_util_decode_flags(tree, tvb, offset + 1, flags, NOKEY_DATA_FRAG_FLAGS);
5786 /* Calculates the minimum length for this submessage */
5788 if ((flags & FLAG_DATA_FRAG_Q) != 0) min_len += 4;
5789 if ((flags & FLAG_DATA_FRAG_H) != 0) min_len += 12;
5791 if (octets_to_next_header < min_len) {
5792 proto_tree_add_uint_format(tree,
5793 hf_rtps_sm_octets_to_next_header,
5797 octets_to_next_header,
5798 "octetsToNextHeader: %u (Error: should be >= %u)",
5799 octets_to_next_header,
5804 /* Skip decoding the entire packet if (tree == NULL)
5805 * Note that we still need to decode the statusInfo and the writer ID
5808 info_summary_append(info_summary_text, SUBMESSAGE_DATA_FRAG, NULL);
5812 proto_tree_add_item(tree,
5813 hf_rtps_sm_octets_to_next_header,
5820 /* readerEntityId */
5821 rtps_util_add_entity_id(tree,
5824 hf_rtps_sm_rdentity_id,
5825 hf_rtps_sm_rdentity_id_key,
5826 hf_rtps_sm_rdentity_id_kind,
5832 /* writerEntityId */
5833 rtps_util_add_entity_id(tree,
5836 hf_rtps_sm_wrentity_id,
5837 hf_rtps_sm_wrentity_id_key,
5838 hf_rtps_sm_wrentity_id_kind,
5844 /* Sequence number */
5845 rtps_util_add_seq_number(tree,
5852 /* If flag H is defined, read the GUID Prefix */
5853 if ((flags & FLAG_DATA_H) != 0) {
5854 rtps_util_add_guid_prefix(tree,
5857 hf_rtps_sm_guid_prefix,
5867 /* Flag H not set, use hostId, appId from the packet header */
5870 /* Complete the GUID by reading the Object ID */
5871 rtps_util_add_entity_id(tree,
5874 hf_rtps_sm_entity_id,
5875 hf_rtps_sm_entity_id_key,
5876 hf_rtps_sm_entity_id_kind,
5883 /* Fragment number */
5884 rtps_util_add_long(tree,
5891 "fragmentStartingNum",
5896 /* Fragments in submessage */
5897 rtps_util_add_short(tree,
5904 "fragmentsInSubmessage",
5910 rtps_util_add_short(tree,
5923 rtps_util_add_long(tree,
5936 if ((flags & FLAG_DATA_Q) != 0) {
5937 offset = dissect_parameter_sequence(tree,
5941 octets_to_next_header - (offset - old_offset) + 4,
5947 /* SerializedData */
5948 if ((flags & FLAG_DATA_D) != 0) {
5949 dissect_serialized_data(tree,
5952 octets_to_next_header - (offset - old_offset) + 4,
5956 info_summary_append(info_summary_text, SUBMESSAGE_DATA_FRAG, NULL);
5961 /* *********************************************************************** */
5962 /* * N O K E Y _ D A T A * */
5963 /* *********************************************************************** */
5964 static void dissect_NOKEY_DATA(tvbuff_t *tvb,
5967 gboolean little_endian,
5968 int octets_to_next_header,
5970 char * info_summary_text,
5971 guint16 vendor_id) {
5974 * 0...2...........7...............15.............23...............31
5975 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5976 * | NOKEY_DATA |X|X|X|X|X|D|Q|E| octetsToNextHeader |
5977 * +---------------+---------------+---------------+---------------+
5978 * | EntityId readerEntityId |
5979 * +---------------+---------------+---------------+---------------+
5980 * | EntityId writerEntityId |
5981 * +---------------+---------------+---------------+---------------+
5983 * + SequenceNumber writerSeqNum +
5985 * +---------------+---------------+---------------+---------------+
5987 * ~ ParameterList inlineQos [only if Q==1] ~
5989 * +---------------+---------------+---------------+---------------+
5991 * ~ SerializedData serializedData [only if D==1] ~
5993 * +---------------+---------------+---------------+---------------+
5997 gint old_offset = offset;
5998 rtps_util_decode_flags(tree, tvb, offset + 1, flags, NOKEY_DATA_FLAGS);
6001 /* Calculates the minimum length for this submessage */
6003 if ((flags & FLAG_NOKEY_DATA_Q) != 0) min_len += 4;
6005 if (octets_to_next_header < min_len) {
6006 proto_tree_add_uint_format(tree,
6007 hf_rtps_sm_octets_to_next_header,
6011 octets_to_next_header,
6012 "octetsToNextHeader: %u (Error: should be >= %u)",
6013 octets_to_next_header,
6018 /* Skip decoding the entire packet if (tree == NULL)
6019 * Note that we still need to decode the statusInfo and the writer ID
6022 info_summary_append(info_summary_text, SUBMESSAGE_NOKEY_DATA, NULL);
6026 proto_tree_add_item(tree,
6027 hf_rtps_sm_octets_to_next_header,
6034 /* readerEntityId */
6035 rtps_util_add_entity_id(tree,
6038 hf_rtps_sm_rdentity_id,
6039 hf_rtps_sm_rdentity_id_key,
6040 hf_rtps_sm_rdentity_id_kind,
6046 /* writerEntityId */
6047 rtps_util_add_entity_id(tree,
6050 hf_rtps_sm_wrentity_id,
6051 hf_rtps_sm_wrentity_id_key,
6052 hf_rtps_sm_wrentity_id_kind,
6058 /* Sequence number */
6059 rtps_util_add_seq_number(tree,
6067 if ((flags & FLAG_DATA_Q) != 0) {
6068 offset = dissect_parameter_sequence(tree,
6072 octets_to_next_header - (offset - old_offset) + 4,
6078 /* SerializedData */
6079 if ((flags & FLAG_DATA_D) != 0) {
6080 dissect_serialized_data(tree,
6083 octets_to_next_header - (offset - old_offset) + 4,
6087 info_summary_append(info_summary_text, SUBMESSAGE_NOKEY_DATA, NULL);
6091 /* *********************************************************************** */
6092 /* * N O K E Y _ D A T A _ F R A G * */
6093 /* *********************************************************************** */
6094 static void dissect_NOKEY_DATA_FRAG(tvbuff_t *tvb,
6097 gboolean little_endian,
6098 int octets_to_next_header,
6100 char * info_summary_text,
6101 guint16 vendor_id) {
6103 * 0...2...........7...............15.............23...............31
6104 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6105 * |NOKEY_DATA_FRAG|X|X|X|X|X|X|Q|E| octetsToNextHeader |
6106 * +---------------+---------------+---------------+---------------+
6107 * | EntityId readerEntityId |
6108 * +---------------+---------------+---------------+---------------+
6109 * | EntityId writerEntityId |
6110 * +---------------+---------------+---------------+---------------+
6112 * + SequenceNumber writerSeqNum +
6114 * +---------------+---------------+---------------+---------------+
6115 * | FragmentNumber fragmentStartingNum |
6116 * +---------------+---------------+---------------+---------------+
6117 * | ushort fragmentsInSubmessage | ushort fragmentSize |
6118 * +---------------+---------------+---------------+---------------+
6119 * | unsigned long sampleSize |
6120 * +---------------+---------------+---------------+---------------+
6122 * ~ ParameterList inlineQos [only if Q==1] ~
6124 * +---------------+---------------+---------------+---------------+
6126 * ~ SerializedData serializedData ~
6128 * +---------------+---------------+---------------+---------------+
6132 gint old_offset = offset;
6133 rtps_util_decode_flags(tree, tvb, offset + 1, flags, NOKEY_DATA_FRAG_FLAGS);
6136 /* Calculates the minimum length for this submessage */
6138 if ((flags & FLAG_NOKEY_DATA_Q) != 0) min_len += 4;
6140 if (octets_to_next_header < min_len) {
6141 proto_tree_add_uint_format(tree,
6142 hf_rtps_sm_octets_to_next_header,
6146 octets_to_next_header,
6147 "octetsToNextHeader: %u (Error: should be >= %u)",
6148 octets_to_next_header,
6153 /* Skip decoding the entire packet if (tree == NULL)
6154 * Note that we still need to decode the statusInfo and the writer ID
6157 info_summary_append(info_summary_text, SUBMESSAGE_NOKEY_DATA_FRAG, NULL);
6161 proto_tree_add_item(tree,
6162 hf_rtps_sm_octets_to_next_header,
6169 /* readerEntityId */
6170 rtps_util_add_entity_id(tree,
6173 hf_rtps_sm_rdentity_id,
6174 hf_rtps_sm_rdentity_id_key,
6175 hf_rtps_sm_rdentity_id_kind,
6181 /* writerEntityId */
6182 rtps_util_add_entity_id(tree,
6185 hf_rtps_sm_wrentity_id,
6186 hf_rtps_sm_wrentity_id_key,
6187 hf_rtps_sm_wrentity_id_kind,
6193 /* Sequence number */
6194 rtps_util_add_seq_number(tree,
6201 /* Fragment number */
6202 rtps_util_add_long(tree,
6209 "fragmentStartingNum",
6214 /* Fragments in submessage */
6215 rtps_util_add_short(tree,
6222 "fragmentsInSubmessage",
6228 rtps_util_add_short(tree,
6241 if ((flags & FLAG_DATA_Q) != 0) {
6242 offset = dissect_parameter_sequence(tree,
6246 octets_to_next_header - (offset - old_offset) + 4,
6252 /* SerializedData */
6253 if ((flags & FLAG_DATA_D) != 0) {
6254 dissect_serialized_data(tree,
6257 octets_to_next_header - (offset - old_offset) + 4,
6261 info_summary_append(info_summary_text, SUBMESSAGE_NOKEY_DATA_FRAG, NULL);
6266 /* *********************************************************************** */
6267 /* * A C K N A C K * */
6268 /* *********************************************************************** */
6269 static void dissect_ACKNACK(tvbuff_t *tvb,
6272 gboolean little_endian,
6273 int octets_to_next_header,
6275 char * info_summary_text,
6276 guint16 G_GNUC_UNUSED vendor_id ) {
6278 * 0...2...........7...............15.............23...............31
6279 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6280 * | ACKNACK |X|X|X|X|X|X|F|E| octetsToNextHeader |
6281 * +---------------+---------------+---------------+---------------+
6282 * | EntityId readerEntityId |
6283 * +---------------+---------------+---------------+---------------+
6284 * | EntityId writerEntityId |
6285 * +---------------+---------------+---------------+---------------+
6287 * + SequenceNumberSet readerSNState +
6289 * +---------------+---------------+---------------+---------------+
6291 * +---------------+---------------+---------------+---------------+
6293 gint original_offset; /* Offset to the readerEntityId */
6295 rtps_util_decode_flags(tree, tvb, offset + 1, flags, ACKNACK_FLAGS);
6297 if (octets_to_next_header < 20) {
6298 proto_tree_add_uint_format(tree,
6299 hf_rtps_sm_octets_to_next_header,
6303 octets_to_next_header,
6304 "octetsToNextHeader: %u (Error: should be >= 20)",
6305 octets_to_next_header);
6309 /* Skip decoding the entire packet if (tree == NULL)
6310 * Note that we still need to decode the statusInfo and the writer ID
6313 info_summary_append(info_summary_text, SUBMESSAGE_ACKNACK, NULL);
6317 proto_tree_add_item(tree,
6318 hf_rtps_sm_octets_to_next_header,
6324 original_offset = offset;
6326 /* readerEntityId */
6327 rtps_util_add_entity_id(tree,
6330 hf_rtps_sm_rdentity_id,
6331 hf_rtps_sm_rdentity_id_key,
6332 hf_rtps_sm_rdentity_id_kind,
6338 /* writerEntityId */
6339 rtps_util_add_entity_id(tree,
6342 hf_rtps_sm_wrentity_id,
6343 hf_rtps_sm_wrentity_id_key,
6344 hf_rtps_sm_wrentity_id_kind,
6351 offset = rtps_util_add_bitmap(tree,
6358 /* RTPS 1.0 didn't have count: make sure we don't decode it wrong
6361 if (offset + 4 == original_offset + octets_to_next_header) {
6362 /* Count is present */
6363 rtps_util_add_long(tree,
6368 FALSE, /* Is Hex ? */
6369 TRUE, /* Is Signed ? */
6370 "counter", /* No Label, use the protocol item ID */
6373 } else if (offset < original_offset + octets_to_next_header) {
6374 /* In this case there must be something wrong in the bitmap: there
6375 * are some extra bytes that we don't know how to decode
6377 proto_tree_add_text(tree,
6380 octets_to_next_header - offset,
6381 "Packet malformed: don't know how to decode those "
6383 octets_to_next_header - offset);
6384 } else if (offset > original_offset + octets_to_next_header) {
6385 /* Decoding the bitmap went over the end of this submessage.
6386 * Enter an item in the protocol tree that spans over the entire
6389 proto_tree_add_text(tree,
6392 octets_to_next_header + original_offset,
6393 "Packet malformed: not enough bytes to decode");
6395 info_summary_append(info_summary_text, SUBMESSAGE_ACKNACK, NULL);
6399 /* *********************************************************************** */
6400 /* * N A C K _ F R A G * */
6401 /* *********************************************************************** */
6402 static void dissect_NACK_FRAG(tvbuff_t *tvb,
6405 gboolean little_endian,
6406 int octets_to_next_header,
6408 char * info_summary_text,
6409 guint16 G_GNUC_UNUSED vendor_id ) {
6411 * 0...2...........7...............15.............23...............31
6412 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6413 * | NACK_FRAG |X|X|X|X|X|X|X|E| octetsToNextHeader |
6414 * +---------------+---------------+---------------+---------------+
6415 * | EntityId readerEntityId |
6416 * +---------------+---------------+---------------+---------------+
6417 * | EntityId writerEntityId |
6418 * +---------------+---------------+---------------+---------------+
6420 * + SequenceNumberSet writerSN +
6422 * +---------------+---------------+---------------+---------------+
6424 * ~ FragmentNumberSet fragmentNumberState +
6426 * +---------------+---------------+---------------+---------------+
6428 * +---------------+---------------+---------------+---------------+
6430 rtps_util_decode_flags(tree, tvb, offset + 1, flags, NACK_FRAG_FLAGS);
6432 if (octets_to_next_header < 24) {
6433 proto_tree_add_uint_format(tree,
6434 hf_rtps_sm_octets_to_next_header,
6438 octets_to_next_header,
6439 "octetsToNextHeader: %u (Error: should be >= 24)",
6440 octets_to_next_header);
6444 /* Skip decoding the entire packet if (tree == NULL)
6445 * Note that we still need to decode the statusInfo and the writer ID
6448 info_summary_append(info_summary_text, SUBMESSAGE_NACK_FRAG, NULL);
6453 proto_tree_add_item(tree,
6454 hf_rtps_sm_octets_to_next_header,
6461 /* readerEntityId */
6462 rtps_util_add_entity_id(tree,
6465 hf_rtps_sm_rdentity_id,
6466 hf_rtps_sm_rdentity_id_key,
6467 hf_rtps_sm_rdentity_id_kind,
6473 /* writerEntityId */
6474 rtps_util_add_entity_id(tree,
6477 hf_rtps_sm_wrentity_id,
6478 hf_rtps_sm_wrentity_id_key,
6479 hf_rtps_sm_wrentity_id_kind,
6485 /* Writer sequence number */
6486 rtps_util_add_seq_number(tree,
6493 /* FragmentNumberSet */
6494 offset = rtps_util_add_fragment_number_set(tree,
6498 "fragmentNumberState",
6499 octets_to_next_header - 20);
6500 info_summary_append(info_summary_text, SUBMESSAGE_NACK_FRAG, NULL);
6506 rtps_util_add_long(tree,
6511 FALSE, /* Is Hex ? */
6512 TRUE, /* Is Signed ? */
6513 "count", /* No Label, use the protocol item ID */
6520 /* *********************************************************************** */
6521 /* * H E A R T B E A T * */
6522 /* *********************************************************************** */
6523 static void dissect_HEARTBEAT(tvbuff_t *tvb,
6526 gboolean little_endian,
6527 int octets_to_next_header,
6529 char * info_summary_text,
6530 guint16 G_GNUC_UNUSED vendor_id) {
6532 * 0...2...........7...............15.............23...............31
6533 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6534 * | HEARTBEAT |X|X|X|X|X|L|F|E| octetsToNextHeader |
6535 * +---------------+---------------+---------------+---------------+
6536 * | EntityId readerEntityId |
6537 * +---------------+---------------+---------------+---------------+
6538 * | EntityId writerEntityId |
6539 * +---------------+---------------+---------------+---------------+
6541 * + SequenceNumber firstSeqNumber +
6543 * +---------------+---------------+---------------+---------------+
6545 * + SequenceNumber lastSeqNumber +
6547 * +---------------+---------------+---------------+---------------+
6549 * +---------------+---------------+---------------+---------------+
6552 rtps_util_decode_flags(tree, tvb, offset + 1, flags, HEARTBEAT_FLAGS);
6555 if (octets_to_next_header < 28) {
6556 proto_tree_add_uint_format(tree,
6557 hf_rtps_sm_octets_to_next_header,
6561 octets_to_next_header,
6562 "octetsToNextHeader: %u (Error: should be >= 28)",
6563 octets_to_next_header);
6567 /* Skip decoding the entire packet if (tree == NULL)
6568 * Note that we still need to decode the statusInfo and the writer ID
6571 info_summary_append(info_summary_text, SUBMESSAGE_HEARTBEAT, NULL);
6575 proto_tree_add_item(tree,
6576 hf_rtps_sm_octets_to_next_header,
6583 /* readerEntityId */
6584 rtps_util_add_entity_id(tree,
6587 hf_rtps_sm_rdentity_id,
6588 hf_rtps_sm_rdentity_id_key,
6589 hf_rtps_sm_rdentity_id_kind,
6595 /* writerEntityId */
6596 rtps_util_add_entity_id(tree,
6599 hf_rtps_sm_wrentity_id,
6600 hf_rtps_sm_wrentity_id_key,
6601 hf_rtps_sm_wrentity_id_kind,
6607 /* First available Sequence Number */
6608 rtps_util_add_seq_number(tree,
6615 /* Last Sequence Number */
6616 rtps_util_add_seq_number(tree,
6624 rtps_util_add_long(tree,
6634 info_summary_append(info_summary_text, SUBMESSAGE_HEARTBEAT, NULL);
6638 /* *********************************************************************** */
6639 /* * H E A R T B E A T _ B A T C H * */
6640 /* *********************************************************************** */
6641 static void dissect_HEARTBEAT_BATCH(tvbuff_t *tvb,
6644 gboolean little_endian,
6645 int octets_to_next_header,
6647 char * info_summary_text,
6648 guint16 G_GNUC_UNUSED vendor_id) {
6652 * 0...2...........7...............15.............23...............31
6653 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6654 * |HEARTBEAT_BATCH|X|X|X|X|X|L|F|E| octetsToNextHeader |
6655 * +---------------+---------------+---------------+---------------+
6656 * | EntityId readerId |
6657 * +---------------+---------------+---------------+---------------+
6658 * | EntityId writerId |
6659 * +---------------+---------------+---------------+---------------+
6661 * + SequenceNumber firstBatchSN +
6663 * +---------------+---------------+---------------+---------------+
6665 * + SequenceNumber lastBatchSN +
6667 * +---------------+---------------+---------------+---------------+
6669 * + SequenceNumber firstSN +
6671 * +---------------+---------------+---------------+---------------+
6673 * + SequenceNumber lastSN +
6675 * +---------------+---------------+---------------+---------------+
6677 * +---------------+---------------+---------------+---------------+
6680 rtps_util_decode_flags(tree, tvb, offset + 1, flags, HEARTBEAT_BATCH_FLAGS);
6683 if (octets_to_next_header < 36) {
6684 proto_tree_add_uint_format(tree,
6685 hf_rtps_sm_octets_to_next_header,
6689 octets_to_next_header,
6690 "octetsToNextHeader: %u (Error: should be >= 36)",
6691 octets_to_next_header);
6695 /* Skip decoding the entire packet if (tree == NULL)
6696 * Note that we still need to decode the statusInfo and the writer ID
6699 info_summary_append(info_summary_text, SUBMESSAGE_HEARTBEAT, NULL);
6702 proto_tree_add_item(tree,
6703 hf_rtps_sm_octets_to_next_header,
6710 /* readerEntityId */
6711 rtps_util_add_entity_id(tree,
6714 hf_rtps_sm_rdentity_id,
6715 hf_rtps_sm_rdentity_id_key,
6716 hf_rtps_sm_rdentity_id_kind,
6722 /* writerEntityId */
6723 rtps_util_add_entity_id(tree,
6726 hf_rtps_sm_wrentity_id,
6727 hf_rtps_sm_wrentity_id_key,
6728 hf_rtps_sm_wrentity_id_kind,
6734 /* First available Batch Sequence Number */
6735 rtps_util_add_seq_number(tree,
6742 /* Last Batch Sequence Number */
6743 rtps_util_add_seq_number(tree,
6750 /* First available Sequence Number */
6751 rtps_util_add_seq_number(tree,
6758 /* Last Sequence Number */
6759 rtps_util_add_seq_number(tree,
6767 rtps_util_add_long(tree,
6777 info_summary_append(info_summary_text, SUBMESSAGE_HEARTBEAT_BATCH, NULL);
6781 /* *********************************************************************** */
6782 /* * H E A R T B E A T _ F R A G * */
6783 /* *********************************************************************** */
6784 static void dissect_HEARTBEAT_FRAG(tvbuff_t *tvb,
6787 gboolean little_endian,
6788 int octets_to_next_header,
6790 char * info_summary_text,
6791 guint16 G_GNUC_UNUSED vendor_id) {
6793 * 0...2...........7...............15.............23...............31
6794 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6795 * |HEARTBEAT_FRAG |X|X|X|X|X|X|X|E| octetsToNextHeader |
6796 * +---------------+---------------+---------------+---------------+
6797 * | EntityId readerEntityId |
6798 * +---------------+---------------+---------------+---------------+
6799 * | EntityId writerEntityId |
6800 * +---------------+---------------+---------------+---------------+
6802 * + SequenceNumber writerSeqNumber +
6804 * +---------------+---------------+---------------+---------------+
6805 * | FragmentNumber lastFragmentNum |
6806 * +---------------+---------------+---------------+---------------+
6808 * +---------------+---------------+---------------+---------------+
6811 rtps_util_decode_flags(tree, tvb, offset + 1, flags, HEARTBEAT_FRAG_FLAGS);
6813 if (octets_to_next_header < 24) {
6814 proto_tree_add_uint_format(tree,
6815 hf_rtps_sm_octets_to_next_header,
6819 octets_to_next_header,
6820 "octetsToNextHeader: %u (Error: should be >= 24)",
6821 octets_to_next_header);
6826 /* Skip decoding the entire packet if (tree == NULL)
6827 * Note that we still need to decode the statusInfo and the writer ID
6830 info_summary_append(info_summary_text, SUBMESSAGE_HEARTBEAT_FRAG, NULL);
6834 proto_tree_add_item(tree,
6835 hf_rtps_sm_octets_to_next_header,
6842 /* readerEntityId */
6843 rtps_util_add_entity_id(tree,
6846 hf_rtps_sm_rdentity_id,
6847 hf_rtps_sm_rdentity_id_key,
6848 hf_rtps_sm_rdentity_id_kind,
6854 /* writerEntityId */
6855 rtps_util_add_entity_id(tree,
6858 hf_rtps_sm_wrentity_id,
6859 hf_rtps_sm_wrentity_id_key,
6860 hf_rtps_sm_wrentity_id_kind,
6866 /* First available Sequence Number */
6867 rtps_util_add_seq_number(tree,
6874 /* Fragment number */
6875 rtps_util_add_long(tree,
6888 rtps_util_add_long(tree,
6898 info_summary_append(info_summary_text, SUBMESSAGE_HEARTBEAT_FRAG, NULL);
6903 /* *********************************************************************** */
6905 /* *********************************************************************** */
6906 static void dissect_GAP(tvbuff_t *tvb,
6909 gboolean little_endian,
6910 int octets_to_next_header,
6912 char * info_summary_text,
6913 guint16 G_GNUC_UNUSED vendor_id) {
6915 * 0...2...........7...............15.............23...............31
6916 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6917 * | GAP |X|X|X|X|X|X|X|E| octetsToNextHeader |
6918 * +---------------+---------------+---------------+---------------+
6919 * | EntityId readerEntityId |
6920 * +---------------+---------------+---------------+---------------+
6921 * | EntityId writerEntityId |
6922 * +---------------+---------------+---------------+---------------+
6924 * + SequenceNumber gapStart +
6926 * +---------------+---------------+---------------+---------------+
6928 * ~ SequenceNumberSet gapList ~
6930 * +---------------+---------------+---------------+---------------+
6933 rtps_util_decode_flags(tree, tvb, offset + 1, flags, GAP_FLAGS);
6935 if (octets_to_next_header < 24) {
6936 proto_tree_add_uint_format(tree,
6937 hf_rtps_sm_octets_to_next_header,
6941 octets_to_next_header,
6942 "octetsToNextHeader: %u (Error: should be >= 24)",
6943 octets_to_next_header);
6947 /* Skip decoding the entire packet if (tree == NULL)
6948 * Note that we still need to decode the statusInfo and the writer ID
6951 info_summary_append(info_summary_text, SUBMESSAGE_GAP, NULL);
6955 proto_tree_add_item(tree,
6956 hf_rtps_sm_octets_to_next_header,
6963 /* readerEntityId */
6964 rtps_util_add_entity_id(tree,
6967 hf_rtps_sm_rdentity_id,
6968 hf_rtps_sm_rdentity_id_key,
6969 hf_rtps_sm_rdentity_id_kind,
6975 /* writerEntityId */
6976 rtps_util_add_entity_id(tree,
6979 hf_rtps_sm_wrentity_id,
6980 hf_rtps_sm_wrentity_id_key,
6981 hf_rtps_sm_wrentity_id_kind,
6988 /* First Sequence Number */
6989 rtps_util_add_seq_number(tree,
6997 rtps_util_add_bitmap(tree,
7002 info_summary_append(info_summary_text, SUBMESSAGE_GAP, NULL);
7006 /* *********************************************************************** */
7007 /* * I N F O _ T S * */
7008 /* *********************************************************************** */
7009 static void dissect_INFO_TS(tvbuff_t *tvb,
7012 gboolean little_endian,
7013 int octets_to_next_header,
7015 char * info_summary_text,
7016 guint16 G_GNUC_UNUSED vendor_id) {
7018 * 0...2...........7...............15.............23...............31
7019 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
7020 * | INFO_TS |X|X|X|X|X|X|I|E| octetsToNextHeader |
7021 * +---------------+---------------+---------------+---------------+
7023 * + Timestamp timestamp [only if I==1] +
7025 * +---------------+---------------+---------------+---------------+
7029 rtps_util_decode_flags(tree, tvb, offset + 1, flags, INFO_TS_FLAGS);
7032 if ((flags & FLAG_INFO_TS_T) == 0) min_len += 8;
7034 if (octets_to_next_header != min_len) {
7035 proto_tree_add_uint_format(tree,
7036 hf_rtps_sm_octets_to_next_header,
7040 octets_to_next_header,
7041 "octetsToNextHeader: %u (Error: should be == %u)",
7042 octets_to_next_header,
7047 /* Skip decoding the entire packet if (tree == NULL)
7048 * Note that we still need to decode the statusInfo and the writer ID
7051 info_summary_append(info_summary_text, SUBMESSAGE_INFO_TS, NULL);
7055 proto_tree_add_item(tree,
7056 hf_rtps_sm_octets_to_next_header,
7063 if ((flags & FLAG_INFO_TS_T) == 0) {
7064 rtps_util_add_ntp_time(tree,
7072 info_summary_append(info_summary_text, SUBMESSAGE_INFO_TS, NULL);
7076 /* *********************************************************************** */
7077 /* * I N F O _ S R C * */
7078 /* *********************************************************************** */
7079 static void dissect_INFO_SRC(tvbuff_t *tvb,
7082 gboolean little_endian,
7083 int octets_to_next_header,
7085 char * info_summary_text,
7086 guint16 G_GNUC_UNUSED vendor_id) {
7088 * 0...2...........7...............15.............23...............31
7089 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
7090 * | INFO_SRC |X|X|X|X|X|X|X|E| octetsToNextHeader |
7091 * +---------------+---------------+---------------+---------------+
7093 * +---------------+---------------+---------------+---------------+
7094 * | ProtocolVersion version | VendorId vendor |
7095 * +---------------+---------------+---------------+---------------+
7098 * | GuidPrefix guidPrefix |
7101 * +---------------+---------------+---------------+---------------+
7104 rtps_util_decode_flags(tree, tvb, offset + 1, flags, INFO_SRC_FLAGS);
7106 if (octets_to_next_header != 16) {
7107 proto_tree_add_uint_format(tree,
7108 hf_rtps_sm_octets_to_next_header,
7112 octets_to_next_header,
7113 "octetsToNextHeader: %u (Error: should be == 16)",
7114 octets_to_next_header);
7118 /* Skip decoding the entire packet if (tree == NULL)
7119 * Note that we still need to decode the statusInfo and the writer ID
7122 info_summary_append(info_summary_text, SUBMESSAGE_INFO_SRC, NULL);
7126 proto_tree_add_item(tree,
7127 hf_rtps_sm_octets_to_next_header,
7136 guint32 ip = NEXT_guint32(tvb, offset, little_endian);
7137 proto_tree_add_text(tree,
7141 "unused: 0x%08x (appIpAddress: %d.%d.%d.%d)",
7154 major = tvb_get_guint8(tvb, offset);
7155 minor = tvb_get_guint8(tvb, offset+1);
7157 proto_tree_add_text(tree,
7169 guint8 vendor[MAX_VENDOR_ID_SIZE];
7170 rtps_util_add_vendor_id(NULL,
7174 MAX_VENDOR_ID_SIZE);
7175 proto_tree_add_text(tree,
7185 /* guint8 temp_buffer[MAX_GUID_PREFIX_SIZE]; */
7186 rtps_util_add_guid_prefix(tree,
7189 hf_rtps_sm_guid_prefix,
7193 NULL, /* Use default 'guidPrefix' */
7197 info_summary_append(info_summary_text, SUBMESSAGE_INFO_SRC, NULL);
7201 /* *********************************************************************** */
7202 /* * I N F O _ R E P L Y _ I P 4 * */
7203 /* *********************************************************************** */
7204 static void dissect_INFO_REPLY_IP4(tvbuff_t *tvb,
7207 gboolean little_endian,
7208 int octets_to_next_header,
7210 char * info_summary_text,
7211 guint16 G_GNUC_UNUSED vendor_id) {
7213 * 0...2...........7...............15.............23...............31
7214 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
7215 * |INFO_REPLY_IP4 |X|X|X|X|X|X|M|E| octetsToNextHeader |
7216 * +---------------+---------------+---------------+---------------+
7218 * + LocatorUDPv4 unicastReplyLocator +
7220 * +---------------+---------------+---------------+---------------+
7222 * + LocatorUDPv4 multicastReplyLocator [only if M==1] +
7224 * +---------------+---------------+---------------+---------------+
7228 rtps_util_decode_flags(tree, tvb, offset + 1, flags, INFO_REPLY_IP4_FLAGS);
7231 if ((flags & FLAG_INFO_REPLY_IP4_M) == 1) min_len += 8;
7234 if (octets_to_next_header != min_len) {
7235 proto_tree_add_uint_format(tree,
7236 hf_rtps_sm_octets_to_next_header,
7240 octets_to_next_header,
7241 "octetsToNextHeader: %u (Error: should be == %u)",
7242 octets_to_next_header,
7247 /* Skip decoding the entire packet if (tree == NULL)
7248 * Note that we still need to decode the statusInfo and the writer ID
7251 info_summary_append(info_summary_text, SUBMESSAGE_INFO_REPLY_IP4, NULL);
7254 proto_tree_add_item(tree,
7255 hf_rtps_sm_octets_to_next_header,
7263 /* unicastReplyLocator */
7264 rtps_util_add_locator_udp_v4(tree,
7267 "unicastReplyLocator",
7272 /* multicastReplyLocator */
7273 if ((flags & FLAG_INFO_REPLY_IP4_M) == 1) {
7274 rtps_util_add_locator_udp_v4(tree,
7277 "multicastReplyLocator",
7281 info_summary_append(info_summary_text, SUBMESSAGE_INFO_REPLY_IP4, NULL);
7284 /* *********************************************************************** */
7285 /* * I N F O _ D S T * */
7286 /* *********************************************************************** */
7287 static void dissect_INFO_DST(tvbuff_t *tvb,
7290 gboolean little_endian,
7291 int octets_to_next_header,
7293 char * info_summary_text,
7294 guint16 G_GNUC_UNUSED vendor_id) {
7296 * 0...2...........7...............15.............23...............31
7297 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
7298 * | INFO_DST |X|X|X|X|X|X|X|E| octetsToNextHeader |
7299 * +---------------+---------------+---------------+---------------+
7302 * | GuidPrefix guidPrefix |
7305 * +---------------+---------------+---------------+---------------+
7308 rtps_util_decode_flags(tree, tvb, offset + 1, flags, INFO_DST_FLAGS);
7310 if (octets_to_next_header != 12) {
7311 proto_tree_add_uint_format(tree,
7312 hf_rtps_sm_octets_to_next_header,
7316 octets_to_next_header,
7317 "octetsToNextHeader: %u (Error: should be == 12)",
7318 octets_to_next_header);
7322 /* Skip decoding the entire packet if (tree == NULL)
7323 * Note that we still need to decode the statusInfo and the writer ID
7326 info_summary_append(info_summary_text, SUBMESSAGE_INFO_DST, NULL);
7330 proto_tree_add_item(tree,
7331 hf_rtps_sm_octets_to_next_header,
7338 rtps_util_add_guid_prefix(tree,
7341 hf_rtps_sm_guid_prefix,
7348 info_summary_append(info_summary_text, SUBMESSAGE_INFO_DST, NULL);
7353 /* *********************************************************************** */
7354 /* * I N F O _ R E P L Y * */
7355 /* *********************************************************************** */
7356 static void dissect_INFO_REPLY(tvbuff_t *tvb,
7359 gboolean little_endian,
7360 int octets_to_next_header,
7362 char * info_summary_text,
7363 guint16 G_GNUC_UNUSED vendor_id) {
7365 * 0...2...........7...............15.............23...............31
7366 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
7367 * | INFO_REPLY |X|X|X|X|X|X|M|E| octetsToNextHeader |
7368 * +---------------+---------------+---------------+---------------+
7370 * ~ LocatorList unicastReplyLocatorList ~
7372 * +---------------+---------------+---------------+---------------+
7374 * ~ LocatorList multicastReplyLocatorList [only if M==1] ~
7376 * +---------------+---------------+---------------+---------------+
7380 rtps_util_decode_flags(tree, tvb, offset + 1, flags, INFO_REPLY_FLAGS);
7383 if ((flags & FLAG_INFO_REPLY_M) == 1) min_len += 8;
7386 if (octets_to_next_header != min_len) {
7387 proto_tree_add_uint_format(tree,
7388 hf_rtps_sm_octets_to_next_header,
7392 octets_to_next_header,
7393 "octetsToNextHeader: %u (Error: should be == %u)",
7394 octets_to_next_header,
7399 /* Skip decoding the entire packet if (tree == NULL)
7400 * Note that we still need to decode the statusInfo and the writer ID
7403 info_summary_append(info_summary_text, SUBMESSAGE_INFO_REPLY, NULL);
7407 proto_tree_add_item(tree,
7408 hf_rtps_sm_octets_to_next_header,
7416 /* unicastReplyLocatorList */
7417 offset = rtps_util_add_locator_list(tree,
7420 "unicastReplyLocatorList",
7424 /* multicastReplyLocatorList */
7425 if ((flags & FLAG_INFO_REPLY_M) == 1) {
7426 offset = rtps_util_add_locator_list(tree,
7429 "multicastReplyLocatorList",
7432 info_summary_append(info_summary_text, SUBMESSAGE_INFO_REPLY, NULL);
7435 /* *********************************************************************** */
7436 /* * R T P S _ D A T A * */
7438 /* * R T P S _ D A T A _ S E S S I O N * */
7439 /* *********************************************************************** */
7440 static void dissect_RTPS_DATA(tvbuff_t *tvb,
7443 gboolean little_endian,
7444 int octets_to_next_header,
7446 char * info_summary_text,
7451 * 0...2...........7...............15.............23...............31
7452 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
7453 * | RTPS_DATA |X|X|X|X|K|D|Q|E| octetsToNextHeader |
7454 * +---------------+---------------+---------------+---------------+
7455 * | Flags extraFlags | octetsToInlineQos |
7456 * +---------------+---------------+---------------+---------------+
7457 * | EntityId readerEntityId |
7458 * +---------------+---------------+---------------+---------------+
7459 * | EntityId writerEntityId |
7460 * +---------------+---------------+---------------+---------------+
7462 * + SequenceNumber writerSeqNum +
7464 * +---------------+---------------+---------------+---------------+
7466 * ~ ParameterList inlineQos [only if Q==1] ~
7468 * +---------------+---------------+---------------+---------------+
7470 * ~ SerializedData serializedData [only if D==1 || K==1] ~
7472 * +---------------+---------------+---------------+---------------+
7474 * 0...2...........7...............15.............23...............31
7475 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
7476 * |RTPS_DATA_SESSI|X|X|X|X|K|D|Q|E| octetsToNextHeader |
7477 * +---------------+---------------+---------------+---------------+
7478 * | Flags extraFlags | octetsToInlineQos |
7479 * +---------------+---------------+---------------+---------------+
7480 * | EntityId readerEntityId |
7481 * +---------------+---------------+---------------+---------------+
7482 * | EntityId writerEntityId |
7483 * +---------------+---------------+---------------+---------------+
7485 * + SequenceNumber writerSessionSeqNum +
7487 * +---------------+---------------+---------------+---------------+
7489 * + SequenceNumber writerVirtualSeqNum +
7491 * +---------------+---------------+---------------+---------------+
7493 * ~ ParameterList inlineQos [only if Q==1] ~
7495 * +---------------+---------------+---------------+---------------+
7497 * ~ SerializedData serializedData [only if D==1 || K==1] ~
7499 * +---------------+---------------+---------------+---------------+
7502 gint old_offset = offset;
7503 guint32 wid; /* Writer EntityID */
7504 guint32 status_info = 0xffffffff;
7506 rtps_util_decode_flags(tree, tvb, offset + 1, flags, RTPS_DATA_FLAGS);
7508 /* Calculates the minimum length for this submessage */
7513 if ((flags & FLAG_RTPS_DATA_Q) != 0) min_len += 4;
7514 if ((flags & FLAG_RTPS_DATA_D) != 0) min_len += 4;
7515 if ((flags & FLAG_RTPS_DATA_K) != 0) min_len += 4;
7517 if (octets_to_next_header < min_len) {
7518 proto_tree_add_uint_format(tree,
7519 hf_rtps_sm_octets_to_next_header,
7523 octets_to_next_header,
7524 "octetsToNextHeader: %u (Error: should be >= %u)",
7525 octets_to_next_header,
7530 /* Skip decoding the entire packet if (tree == NULL)
7531 * Note that we still need to decode the statusInfo and the writer ID
7535 /* writerEntityId */
7536 wid = NEXT_guint32(tvb, offset, little_endian);
7539 if ((flags & FLAG_RTPS_DATA_Q) != 0) {
7540 offset = dissect_parameter_sequence(tree,
7544 octets_to_next_header - (offset - old_offset) + 4,
7549 info_summary_append_ex(info_summary_text, SUBMESSAGE_RTPS_DATA, wid, status_info);
7553 proto_tree_add_item(tree,
7554 hf_rtps_sm_octets_to_next_header,
7563 rtps_util_add_extra_flags(tree,
7569 /* octetsToInlineQos */
7570 proto_tree_add_text(tree,
7574 "Octets to inline QoS: %d",
7575 NEXT_guint16(tvb, offset, little_endian));
7579 /* readerEntityId */
7580 rtps_util_add_entity_id(tree,
7583 hf_rtps_sm_rdentity_id,
7584 hf_rtps_sm_rdentity_id_key,
7585 hf_rtps_sm_rdentity_id_kind,
7591 /* writerEntityId */
7592 rtps_util_add_entity_id(tree,
7595 hf_rtps_sm_wrentity_id,
7596 hf_rtps_sm_wrentity_id_key,
7597 hf_rtps_sm_wrentity_id_kind,
7603 /* Sequence number */
7605 rtps_util_add_seq_number(tree,
7609 "writerSessionSeqNumber");
7611 rtps_util_add_seq_number(tree,
7615 "writerVirtualSeqNumber");
7618 rtps_util_add_seq_number(tree,
7627 if ((flags & FLAG_RTPS_DATA_Q) != 0) {
7628 offset = dissect_parameter_sequence(tree,
7632 octets_to_next_header - (offset - old_offset) + 4,
7638 /* SerializedData */
7639 if (((flags & FLAG_RTPS_DATA_D) != 0) || ((flags & FLAG_RTPS_DATA_K) != 0)) {
7640 if (wid == ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER) {
7641 /* Dissect the serialized data as ParticipantMessageData:
7642 * struct ParticipantMessageData {
7643 * KeyHashPrefix_t participantGuidPrefix;
7644 * KeyHashSuffix_t kind;
7645 * sequence<octet> data;
7648 proto_tree * rtps_pm_tree;
7649 proto_tree * guid_tree;
7651 guint16 encapsulation_id;
7652 guint16 encapsulation_len;
7653 int encapsulation_little_endian = 0;
7654 proto_item * ti = proto_tree_add_text(tree,
7657 octets_to_next_header - (offset - old_offset) + 4,
7658 "ParticipantMessageData");
7660 rtps_pm_tree = proto_item_add_subtree(ti, ett_rtps_part_message_data);
7661 /* Encapsulation ID */
7662 encapsulation_id = NEXT_guint16(tvb, offset, 0); /* Always big endian */
7664 proto_tree_add_text(rtps_pm_tree,
7668 "encapsulation kind: %s",
7669 val_to_str(encapsulation_id,
7670 encapsulation_id_vals, "unknown (%02x)"));
7673 /* Sets the correct values for encapsulation_le */
7674 if (encapsulation_id == ENCAPSULATION_CDR_LE ||
7675 encapsulation_id == ENCAPSULATION_PL_CDR_LE) {
7676 encapsulation_little_endian = 1;
7679 /* Encapsulation length (or option) */
7680 encapsulation_len = NEXT_guint16(tvb, offset, 0); /* Always big endian */
7681 proto_tree_add_text(rtps_pm_tree,
7685 "encapsulation options: %04x",
7689 guid_tree = proto_item_add_subtree(ti,
7690 ett_rtps_part_message_data);
7692 rtps_util_add_guid_prefix(guid_tree,
7695 hf_rtps_sm_guid_prefix,
7699 "participantGuidPrefix",
7705 kind = NEXT_guint32(tvb, offset, 0); /* Always big endian */
7706 proto_tree_add_text(guid_tree,
7711 val_to_str(kind, participant_message_data_kind, "unknown (%04x)"));
7714 dissect_octet_seq(rtps_pm_tree, /* guid_tree, */
7720 if (((flags & FLAG_RTPS_DATA_D) != 0) || ((flags & FLAG_RTPS_DATA_K) == 0)) {
7721 label = "serializedData";
7722 } else if (((flags & FLAG_RTPS_DATA_D) == 0) || ((flags & FLAG_RTPS_DATA_K) != 0)) {
7723 label = "serializedKey";
7726 label = "<invalid or unknown data type>";
7729 /* At the end still dissect the rest of the bytes as raw data */
7730 dissect_serialized_data(tree,
7733 octets_to_next_header - (offset - old_offset) + 4,
7739 info_summary_append_ex(info_summary_text, SUBMESSAGE_RTPS_DATA, wid, status_info);
7745 /* *********************************************************************** */
7746 /* * R T P S _ D A T A _ F R A G * */
7747 /* *********************************************************************** */
7748 static void dissect_RTPS_DATA_FRAG(tvbuff_t *tvb,
7751 gboolean little_endian,
7752 int octets_to_next_header,
7754 char * info_summary_text,
7755 guint16 vendor_id) {
7758 * 0...2...........7...............15.............23...............31
7759 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
7760 * |RTPS_DATA_FRAG |X|X|X|X|X|K|Q|E| octetsToNextHeader |
7761 * +---------------+---------------+---------------+---------------+
7762 * | Flags extraFlags | octetsToInlineQos |
7763 * +---------------+---------------+---------------+---------------+
7764 * | EntityId readerEntityId |
7765 * +---------------+---------------+---------------+---------------+
7766 * | EntityId writerEntityId |
7767 * +---------------+---------------+---------------+---------------+
7769 * + SequenceNumber writerSeqNum +
7771 * +---------------+---------------+---------------+---------------+
7772 * | FragmentNumber fragmentStartingNum |
7773 * +---------------+---------------+---------------+---------------+
7774 * | ushort fragmentsInSubmessage | ushort fragmentSize |
7775 * +---------------+---------------+---------------+---------------+
7776 * | unsigned long sampleSize |
7777 * +---------------+---------------+---------------+---------------+
7779 * ~ ParameterList inlineQos [only if Q==1] ~
7781 * +---------------+---------------+---------------+---------------+
7783 * ~ SerializedData serializedData ~
7785 * +---------------+---------------+---------------+---------------+
7788 gint old_offset = offset;
7789 guint32 wid; /* Writer EntityID */
7790 guint32 status_info = 0xffffffff;
7792 rtps_util_decode_flags(tree, tvb, offset + 1, flags, RTPS_DATA_FRAG_FLAGS);
7794 /* Calculates the minimum length for this submessage */
7796 if ((flags & FLAG_RTPS_DATA_FRAG_Q) != 0) min_len += 4;
7798 if (octets_to_next_header < min_len) {
7799 proto_tree_add_uint_format(tree,
7800 hf_rtps_sm_octets_to_next_header,
7804 octets_to_next_header,
7805 "octetsToNextHeader: %u (Error: should be >= %u)",
7806 octets_to_next_header,
7811 /* Skip decoding the entire packet if (tree == NULL)
7812 * Note that we still need to decode the statusInfo and the writer ID
7816 /* writerEntityId */
7817 wid = NEXT_guint32(tvb, offset, little_endian);
7820 if ((flags & FLAG_RTPS_DATA_FRAG_Q) != 0) {
7821 offset = dissect_parameter_sequence(tree,
7825 octets_to_next_header - (offset - old_offset) + 4,
7830 info_summary_append_ex(info_summary_text, SUBMESSAGE_RTPS_DATA_FRAG, wid, status_info);
7834 proto_tree_add_item(tree,
7835 hf_rtps_sm_octets_to_next_header,
7844 rtps_util_add_extra_flags(tree,
7850 /* octetsToInlineQos */
7851 proto_tree_add_text(tree,
7855 "Octets to inline QoS: %d",
7856 NEXT_guint16(tvb, offset, little_endian));
7860 /* readerEntityId */
7861 rtps_util_add_entity_id(tree,
7864 hf_rtps_sm_rdentity_id,
7865 hf_rtps_sm_rdentity_id_key,
7866 hf_rtps_sm_rdentity_id_kind,
7872 /* writerEntityId */
7873 rtps_util_add_entity_id(tree,
7876 hf_rtps_sm_wrentity_id,
7877 hf_rtps_sm_wrentity_id_key,
7878 hf_rtps_sm_wrentity_id_kind,
7885 /* Sequence number */
7886 rtps_util_add_seq_number(tree,
7893 /* Fragment number */
7894 rtps_util_add_long(tree,
7901 "fragmentStartingNum",
7906 /* Fragments in submessage */
7907 rtps_util_add_short(tree,
7914 "fragmentsInSubmessage",
7920 rtps_util_add_short(tree,
7933 rtps_util_add_long(tree,
7946 if ((flags & FLAG_RTPS_DATA_FRAG_Q) != 0) {
7947 offset = dissect_parameter_sequence(tree,
7951 octets_to_next_header - (offset - old_offset) + 4,
7957 /* SerializedData */
7959 const char *label = "serializedData";
7960 if ((flags & FLAG_RTPS_DATA_FRAG_K) != 0) {
7961 label = "serializedKey";
7963 dissect_serialized_data(tree,
7966 octets_to_next_header - (offset - old_offset) + 4,
7970 info_summary_append_ex(info_summary_text, SUBMESSAGE_RTPS_DATA_FRAG, wid, status_info);
7976 /* *********************************************************************** */
7977 /* * R T P S _ D A T A _ B A T C H * */
7978 /* *********************************************************************** */
7979 static void dissect_RTPS_DATA_BATCH(tvbuff_t *tvb,
7982 gboolean little_endian,
7983 int octets_to_next_header,
7985 char * info_summary_text,
7986 guint16 vendor_id) {
7989 * 0...2...........7...............15.............23...............31
7990 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
7991 * |RTPS_DATA_BATCH|X|X|X|X|X|X|Q|E| octetsToNextHeader |
7992 * +---------------+---------------+---------------+---------------+
7993 * | Flags extraFlags | octetsToInlineQos |
7994 * +---------------+---------------+---------------+---------------+
7995 * | EntityId readerId |
7996 * +---------------+---------------+---------------+---------------+
7997 * | EntityId writerId |
7998 * +---------------+---------------+---------------+---------------+
8000 * + SequenceNumber batchSN +
8002 * +---------------+---------------+---------------+---------------+
8004 * + SequenceNumber firstSampleSN +
8006 * +---------------+---------------+---------------+---------------+
8007 * | SequenceNumberOffset offsetToLastSampleSN |
8008 * +---------------+---------------+---------------+---------------+
8009 * | unsigned long batchSampleCount |
8010 * +---------------+---------------+---------------+---------------+
8012 * ~ ParameterList batchInlineQos [only if Q==1] ~
8014 * +---------------+---------------+---------------+---------------+
8015 * | unsigned long octetsToSLEncapsulationId |
8016 * +---------------+---------------+---------------+---------------+
8018 * ~ SampleInfoList sampleInfoList ~
8020 * +---------------+---------------+---------------+---------------+
8021 * | SampleListEncapsulationId | |
8022 * +---------------+---------------+---------------+---------------+
8024 * ~ SampleList sampleList ~
8026 * +---------------+---------------+---------------+---------------+
8030 * 0...............8..............16..............24..............32
8031 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
8032 * |X|X|X|X|X|X|X|X|X|X|K|I|D|O|Q|T| octetsToInlineQoS |
8033 * +---------------+---------------+---------------+---------------+
8034 * | unsigned long serializedDataLength |
8035 * +---------------+---------------+---------------+---------------+
8037 * + Timestamp timestamp [only if T==1] +
8039 * +---------------+---------------+---------------+---------------+
8040 * | SequenceNumberOffset offsetSN [only if O==1] |
8041 * +---------------+---------------+---------------+---------------+
8043 * ~ ParameterList sampleInlineQos [only if Q==1] ~
8045 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
8049 * 0...............8..............16..............24..............32
8050 * +---------------+---------------+---------------+---------------+
8052 * ~ SerializedData serializedData [sampleInfo D==1 || K==1] ~
8054 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
8058 gint old_offset = offset;
8059 guint32 wid; /* Writer EntityID */
8060 guint32 status_info = 0xffffffff;
8061 gint32 octectsToSLEncapsulationId;
8062 guint32 batchSampleCount;
8063 gint32 sampleListOffset;
8064 guint16 encapsulation_id;
8065 guint16 *sample_info_flags = NULL;
8066 guint32 *sample_info_length = NULL;
8067 gint32 sample_info_count = 0;
8068 gint32 sample_info_max = rtps_max_batch_samples_dissected;
8070 rtps_util_decode_flags(tree, tvb, offset + 1, flags, RTPS_DATA_BATCH_FLAGS);
8072 /* Calculates the minimum length for this submessage */
8074 if ((flags & FLAG_RTPS_DATA_BATCH_Q) != 0) min_len += 4;
8076 if (octets_to_next_header < min_len) {
8077 proto_tree_add_uint_format(tree,
8078 hf_rtps_sm_octets_to_next_header,
8082 octets_to_next_header,
8083 "octetsToNextHeader: %u (Error: should be >= %u)",
8084 octets_to_next_header,
8089 /* Skip decoding the entire packet if (tree == NULL)
8090 * Note that we still need to decode the statusInfo and the writer ID
8094 /* writerEntityId */
8095 wid = NEXT_guint32(tvb, offset, little_endian);
8098 if ((flags & FLAG_DATA_Q) != 0) {
8099 offset = dissect_parameter_sequence(tree,
8103 octets_to_next_header - (offset - old_offset) + 4,
8108 info_summary_append_ex(info_summary_text, SUBMESSAGE_RTPS_DATA_BATCH, wid, status_info);
8111 proto_tree_add_item(tree,
8112 hf_rtps_sm_octets_to_next_header,
8121 rtps_util_add_extra_flags(tree,
8127 /* octetsToInlineQos */
8128 proto_tree_add_text(tree,
8132 "Octets to inline QoS: %d",
8133 NEXT_guint16(tvb, offset, little_endian));
8137 /* readerEntityId */
8138 rtps_util_add_entity_id(tree,
8141 hf_rtps_sm_rdentity_id,
8142 hf_rtps_sm_rdentity_id_key,
8143 hf_rtps_sm_rdentity_id_kind,
8149 /* writerEntityId */
8150 rtps_util_add_entity_id(tree,
8153 hf_rtps_sm_wrentity_id,
8154 hf_rtps_sm_wrentity_id_key,
8155 hf_rtps_sm_wrentity_id_kind,
8162 /* Batch sequence number */
8163 rtps_util_add_seq_number(tree,
8170 /* First stample sequence number */
8171 rtps_util_add_seq_number(tree,
8175 "firstSampleSeqNumber");
8178 /* offsetToLastSampleSN */
8179 rtps_util_add_long(tree,
8186 "offsetToLastSampleSN",
8191 /* batchSampleCount */
8192 batchSampleCount = rtps_util_add_long(tree,
8204 /* Parameter list (if Q==1) */
8206 if ((flags & FLAG_RTPS_DATA_BATCH_Q) != 0) {
8207 offset = dissect_parameter_sequence(tree,
8211 octets_to_next_header - (offset - old_offset) + 4,
8217 /* octetsToSLEncapsulationId */
8218 octectsToSLEncapsulationId = (gint32)rtps_util_add_long(tree,
8225 "octetsToSLEncapsulationId",
8229 sampleListOffset = offset + octectsToSLEncapsulationId;
8232 /* Sample info list */
8235 proto_tree * sil_tree;
8236 sample_info_count = 0;
8238 ti = proto_tree_add_text(tree,
8242 "Sample Info List");
8243 sil_tree = proto_item_add_subtree(ti, ett_rtps_sample_info_list);
8245 /* Allocate sample_info_flags and sample_info_length
8246 * to store a copy of the flags for each sample info */
8247 if (rtps_max_batch_samples_dissected == 0) {
8248 sample_info_max = 1024; /* Max size of sampleInfo shown */
8250 sample_info_flags = (guint16 *)ep_alloc(sizeof(guint16) * sample_info_max);
8251 sample_info_length = (guint32 *)ep_alloc(sizeof(guint32) * sample_info_max);
8253 /* Sample Info List: start decoding the sample info list until the offset
8254 * is greater or equal than 'sampleListOffset' */
8255 while (offset < sampleListOffset) {
8257 guint16 octetsToInlineQos;
8259 proto_tree * si_tree;
8260 gint offset_begin_sampleinfo = offset;
8262 if (rtps_max_batch_samples_dissected > 0 && (guint)sample_info_count >= rtps_max_batch_samples_dissected) {
8263 ti = proto_tree_add_text(sil_tree,
8267 "... (more samples available. Configure this limit from preferences dialog)");
8268 offset = sampleListOffset;
8272 ti = proto_tree_add_text(sil_tree,
8276 "sampleInfo[%d]", sample_info_count);
8277 si_tree = proto_item_add_subtree(ti, ett_rtps_sample_info);
8279 flags2 = NEXT_guint16(tvb, offset, 0); /* Flags are always big endian */
8280 sample_info_flags[sample_info_count] = flags2;
8281 rtps_util_decode_flags_16bit(si_tree, tvb, offset, flags2, RTPS_SAMPLE_INFO_FLAGS16);
8283 octetsToInlineQos = rtps_util_add_short(si_tree,
8290 "octetsToInlineQos",
8296 if ((flags2 & FLAG_SAMPLE_INFO_T) != 0) min_len += 8;
8297 if ((flags2 & FLAG_SAMPLE_INFO_Q) != 0) min_len += 4;
8298 if ((flags2 & FLAG_SAMPLE_INFO_O) != 0) min_len += 4;
8300 /* Ensure there are enough bytes to decode */
8301 if (sampleListOffset - offset < min_length) {
8302 proto_tree_add_text(si_tree,
8306 "Error: not enough bytes to dissect sample info");
8310 /* Serialized data length */
8311 sample_info_length[sample_info_count] = rtps_util_add_long(si_tree,
8318 "serializedDataLength",
8323 /* Timestamp [only if T==1] */
8324 if ((flags2 & FLAG_SAMPLE_INFO_T) != 0) {
8325 rtps_util_add_ntp_time(si_tree,
8335 /* Offset SN [only if O==1] */
8336 if ((flags2 & FLAG_SAMPLE_INFO_O) != 0) {
8337 rtps_util_add_long(si_tree,
8350 /* Parameter list [only if Q==1] */
8351 if ((flags2 & FLAG_SAMPLE_INFO_Q) != 0) {
8352 offset = dissect_parameter_sequence(si_tree,
8356 octets_to_next_header - (offset - old_offset) + 4,
8361 proto_item_set_len(ti, offset - offset_begin_sampleinfo);
8362 sample_info_count++;
8363 } /* while (offset < sampleListOffset) */
8366 /* Encapsulation ID for the entire data sequence */
8367 encapsulation_id = NEXT_guint16(tvb, offset, 0); /* Always big endian */
8368 proto_tree_add_text(tree,
8372 "encapsulation kind: %s",
8373 val_to_str(encapsulation_id, encapsulation_id_vals, "unknown (%02x)"));
8376 /* The next two bytes are ignored */
8379 /* Now the list of serialized data:
8380 * Serialized data is allocated one after another one.
8381 * We need to use the data previously stored in the sampleInfo to detect the
8383 * - sample_info_flags -> Array of guint16 holding the flags for this sample info
8384 * - sample_info_length -> Array of guint32 with the size of this sample info
8385 * - sample_info_count -> size of the above arrays
8386 * This section will NEVER dissect more than 'sample_info_count'.
8387 * Note, if there are not enough bytes in the buffer, don't dissect it (this
8388 * can happen for example when a DISPOSE message is sent, there are sample
8389 * info records, but the payload size is zero for all of them)
8391 if (octets_to_next_header - (offset - old_offset) > 0) {
8393 proto_tree * sil_tree;
8397 ti = proto_tree_add_text(tree,
8401 "Serialized Sample List");
8402 sil_tree = proto_item_add_subtree(ti, ett_rtps_sample_batch_list);
8403 for (count = 0; count < sample_info_count; ++count) {
8404 /* Ensure there are enough bytes in the buffer to dissect the next sample */
8405 if (octets_to_next_header - (offset - old_offset) + 4 < (gint)sample_info_length[count]) {
8406 proto_tree_add_text(sil_tree,
8410 "Error: not enough bytes to dissect sample");
8414 if ((sample_info_flags[count] & FLAG_SAMPLE_INFO_K) != 0) {
8415 label = "serializedKey[%d]";
8417 label = "serializedData[%d]";
8419 proto_tree_add_text(sil_tree,
8422 sample_info_length[count],
8425 offset += sample_info_length[count];
8428 info_summary_append_ex(info_summary_text, SUBMESSAGE_RTPS_DATA_BATCH, wid, status_info);
8435 /***************************************************************************/
8436 /* The main packet dissector function
8438 static gboolean dissect_rtps(tvbuff_t *tvb,
8441 proto_item *ti = NULL;
8442 proto_tree *rtps_tree = NULL;
8444 proto_tree *rtps_submessage_tree = NULL;
8445 guint8 submessageId;
8447 gboolean little_endian;
8448 gboolean is_ping = FALSE;
8449 gint next_submsg, octets_to_next_header;
8450 guint16 vendor_id = RTPS_VENDOR_UNKNOWN;
8451 char info_summary_text[MAX_SUMMARY_SIZE];
8453 info_summary_text[0] = '\0';
8455 /* Check 'RTPS' signature:
8456 * A header is invalid if it has less than 16 octets
8458 if (!tvb_bytes_exist(tvb, offset, 16)) return FALSE;
8460 /* Check packet signature */
8461 if ( (tvb_get_guint8(tvb,offset) != 'R') ||
8462 (tvb_get_guint8(tvb,offset+1) != 'T') ||
8463 (tvb_get_guint8(tvb,offset+2) != 'P') ||
8464 (tvb_get_guint8(tvb,offset+3) != 'S') ||
8465 (tvb_get_guint8(tvb,offset+4) != 2) ) {
8469 /* --- Make entries in Protocol column ---*/
8470 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTPS2");
8471 col_clear(pinfo->cinfo, COL_INFO);
8473 /* Check if is NDDSPING */
8476 tvb_memcpy(tvb, nddsPing, offset+8, 8);
8477 is_ping = (nddsPing[0] == 'N' &&
8478 nddsPing[1] == 'D' &&
8479 nddsPing[2] == 'D' &&
8480 nddsPing[3] == 'S' &&
8481 nddsPing[4] == 'P' &&
8482 nddsPing[5] == 'I' &&
8483 nddsPing[6] == 'N' &&
8484 nddsPing[7] == 'G');
8488 /* create display subtree for the protocol */
8489 ti = proto_tree_add_item(tree, proto_rtps, tvb, 0, -1, FALSE);
8490 rtps_tree = proto_item_add_subtree(ti, ett_rtps);
8492 /* Protocol Version */
8493 rtps_util_add_protocol_version(rtps_tree, tvb, offset+4);
8496 vendor_id = NEXT_guint16(tvb, offset+6, FALSE);
8497 rtps_util_add_vendor_id(rtps_tree, tvb, offset+6, NULL, 0);
8499 /* If is not PING, the next 12 bytes are the GUID prefix */
8501 rtps_util_add_guid_prefix(rtps_tree,
8504 hf_rtps_guid_prefix,
8515 g_strlcpy(info_summary_text, "PING", MAX_SUMMARY_SIZE);
8519 pinfo->guid_prefix_host = tvb_get_ntohl(tvb, offset + 8);
8520 pinfo->guid_prefix_app = tvb_get_ntohl(tvb, offset + 12);
8521 pinfo->guid_prefix_count = tvb_get_ntohl(tvb, offset + 16);
8522 pinfo->guid_rtps2 = 1;
8526 /* Extract the domain id and participant index for the default mapping */
8529 int participant_idx = -1;
8533 proto_tree *mapping_tree;
8535 /* For a complete description of these rules, see RTPS documentation
8538 domain_id = ((pinfo->destport - PORT_BASE)/10) % 100;
8539 participant_idx = (pinfo->destport - PORT_BASE) / 1000;
8540 nature = (pinfo->destport % 10);
8542 For Unicast, the port mapping formula is:
8543 metatraffic_unicast_port = port_base +
8544 (domain_id_gain * domain_id) +
8545 (participant_id_gain * participant_id) +
8546 builtin_unicast_port_offset
8547 For Multicast, the port mapping is:
8548 metatraffic_multicast_port = port_base +
8549 (domain_id_gain * domain_id) +
8550 builtin_multicast_port_offset
8552 Where the constants are:
8554 domain_id_gain = 250
8555 participant_id_gain = 2
8556 builtin_multicast_port_offset = 0
8557 builtin_unicast_port_offset = 10
8558 user_multicast_port_offset = 1
8559 user_unicast_port_offset = 11
8562 To obtain the individual components from the port number, the reverse formulas are:
8563 domain_id = (port - port_base) / 250 (valid both multicast / unicast)
8564 Doffset = (port - port_Base - (domain_id * 250));
8565 participant_idx = (Doffset - 10) / 2;
8568 domain_id = (pinfo->destport - PORT_BASE) / 250;
8569 Doffset = (pinfo->destport - PORT_BASE - domain_id * 250);
8571 nature = PORT_METATRAFFIC_MULTICAST;
8572 } else if (Doffset == 1) {
8573 nature = PORT_USERTRAFFIC_MULTICAST;
8575 participant_idx = (Doffset - 10) / 2;
8576 if ( (Doffset - 10) % 2 == 0) {
8577 nature = PORT_METATRAFFIC_UNICAST;
8579 nature = PORT_USERTRAFFIC_UNICAST;
8583 if (nature == PORT_METATRAFFIC_UNICAST || nature == PORT_USERTRAFFIC_UNICAST) {
8584 ti2 = proto_tree_add_text(rtps_tree,
8588 "Default port mapping: %s, domainId=%d, "
8589 "participantIdx=%d",
8590 val_to_str(nature, nature_type_vals, "%02x"),
8594 /* Multicast doesn't print the participant index */
8595 ti2 = proto_tree_add_text(rtps_tree,
8599 "Default port mapping: %s, domainId=%d",
8600 val_to_str(nature, nature_type_vals, "%02x"),
8604 /* Build the searchable protocol tree */
8605 mapping_tree = proto_item_add_subtree(ti2, ett_rtps_default_mapping);
8606 proto_tree_add_uint(mapping_tree,
8612 if (nature == PORT_METATRAFFIC_UNICAST || nature == PORT_USERTRAFFIC_UNICAST) {
8613 proto_tree_add_uint(mapping_tree,
8614 hf_rtps_participant_idx,
8620 proto_tree_add_uint(mapping_tree,
8621 hf_rtps_nature_type,
8628 /* offset behind RTPS's Header (need to be set in case tree=NULL)*/
8631 while (tvb_reported_length_remaining(tvb, offset) > 0) {
8632 submessageId = tvb_get_guint8(tvb, offset);
8634 /* Creates the subtree 'Submessage: XXXX' */
8636 if (submessageId & 0x80) {
8637 ti = proto_tree_add_text(rtps_tree,
8642 val_to_str(submessageId, submessage_id_vals,
8643 "Vendor-specific (0x%02x)"));
8645 ti = proto_tree_add_text(rtps_tree,
8650 val_to_str(submessageId, submessage_id_vals,
8651 "Unknown (0x%02x)"));
8653 rtps_submessage_tree = proto_item_add_subtree(ti, ett_rtps_submessage);
8655 /* Decode the submessage ID */
8656 if (submessageId & 0x80) {
8657 proto_tree_add_uint_format(rtps_submessage_tree,
8663 "submessageId: Vendor-specific (0x%02x)",
8666 proto_tree_add_uint(rtps_submessage_tree, hf_rtps_sm_id,
8667 tvb, offset, 1, submessageId);
8669 } /* tree is present */
8671 /* Gets the flags */
8672 flags = tvb_get_guint8(tvb, offset + 1);
8674 /* Gets the E (Little endian) flag */
8675 little_endian = ((flags & FLAG_E) != 0);
8677 /* octet-to-next-header */
8678 octets_to_next_header = NEXT_guint16(tvb, offset + 2, little_endian);
8679 next_submsg = offset + octets_to_next_header + 4;
8681 /* Set length of this item */
8683 proto_item_set_len(ti, octets_to_next_header + 4);
8686 /* Now decode each single submessage
8688 * Note: if tree==NULL, it's true we don't care too much about the
8689 * details, but we are still calling the individual submessage
8690 * dissectors in order to correctly compose the INFO list.
8691 * The offset passed to the dissectors points to the start of the
8692 * submessage (at the ID byte).
8694 switch (submessageId) {
8695 case SUBMESSAGE_PAD:
8700 octets_to_next_header,
8701 rtps_submessage_tree,
8706 case SUBMESSAGE_DATA:
8711 octets_to_next_header,
8712 rtps_submessage_tree,
8717 case SUBMESSAGE_DATA_FRAG:
8718 dissect_DATA_FRAG(tvb,
8722 octets_to_next_header,
8723 rtps_submessage_tree,
8728 case SUBMESSAGE_NOKEY_DATA:
8729 dissect_NOKEY_DATA(tvb,
8733 octets_to_next_header,
8734 rtps_submessage_tree,
8739 case SUBMESSAGE_NOKEY_DATA_FRAG:
8740 dissect_NOKEY_DATA_FRAG(tvb,
8744 octets_to_next_header,
8745 rtps_submessage_tree,
8750 case SUBMESSAGE_NACK_FRAG:
8751 dissect_NACK_FRAG(tvb,
8755 octets_to_next_header,
8756 rtps_submessage_tree,
8762 case SUBMESSAGE_ACKNACK_SESSION:
8763 case SUBMESSAGE_ACKNACK_BATCH:
8764 case SUBMESSAGE_ACKNACK:
8765 dissect_ACKNACK(tvb,
8769 octets_to_next_header,
8770 rtps_submessage_tree,
8775 case SUBMESSAGE_HEARTBEAT:
8776 dissect_HEARTBEAT(tvb,
8780 octets_to_next_header,
8781 rtps_submessage_tree,
8786 case SUBMESSAGE_HEARTBEAT_SESSION:
8787 case SUBMESSAGE_HEARTBEAT_BATCH:
8788 dissect_HEARTBEAT_BATCH(tvb,
8792 octets_to_next_header,
8793 rtps_submessage_tree,
8798 case SUBMESSAGE_HEARTBEAT_FRAG:
8799 dissect_HEARTBEAT_FRAG(tvb,
8803 octets_to_next_header,
8804 rtps_submessage_tree,
8809 case SUBMESSAGE_GAP:
8814 octets_to_next_header,
8815 rtps_submessage_tree,
8820 case SUBMESSAGE_INFO_TS:
8821 dissect_INFO_TS(tvb,
8825 octets_to_next_header,
8826 rtps_submessage_tree,
8831 case SUBMESSAGE_INFO_SRC:
8832 dissect_INFO_SRC(tvb,
8836 octets_to_next_header,
8837 rtps_submessage_tree,
8842 case SUBMESSAGE_INFO_REPLY_IP4:
8843 dissect_INFO_REPLY_IP4(tvb,
8847 octets_to_next_header,
8848 rtps_submessage_tree,
8853 case SUBMESSAGE_INFO_DST:
8854 dissect_INFO_DST(tvb,
8858 octets_to_next_header,
8859 rtps_submessage_tree,
8864 case SUBMESSAGE_INFO_REPLY:
8865 dissect_INFO_REPLY(tvb,
8869 octets_to_next_header,
8870 rtps_submessage_tree,
8875 case SUBMESSAGE_RTPS_DATA_SESSION:
8876 case SUBMESSAGE_RTPS_DATA:
8877 dissect_RTPS_DATA(tvb,
8881 octets_to_next_header,
8882 rtps_submessage_tree,
8885 (submessageId == SUBMESSAGE_RTPS_DATA_SESSION));
8888 case SUBMESSAGE_RTPS_DATA_FRAG:
8889 dissect_RTPS_DATA_FRAG(tvb,
8893 octets_to_next_header,
8894 rtps_submessage_tree,
8899 case SUBMESSAGE_RTPS_DATA_BATCH:
8900 dissect_RTPS_DATA_BATCH(tvb,
8904 octets_to_next_header,
8905 rtps_submessage_tree,
8912 if (rtps_submessage_tree != NULL) {
8913 proto_tree_add_uint(rtps_submessage_tree, hf_rtps_sm_flags,
8914 tvb, offset + 1, 1, flags);
8915 proto_tree_add_uint(rtps_submessage_tree,
8916 hf_rtps_sm_octets_to_next_header,
8917 tvb, offset + 2, 2, next_submsg);
8921 /* next submessage's offset */
8922 offset = next_submsg;
8925 /* Compose the content of the 'summary' column */
8926 col_add_str(pinfo->cinfo, COL_INFO, info_summary_text);
8929 } /* dissect_rtps(...) */
8935 /***************************************************************************
8936 * Register the protocol with Wireshark
8937 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8939 void proto_register_rtps2(void) {
8941 /* Definition of the protocol tree items:
8942 * This section declares all the protocol items that are parsed in the
8944 * Structure of each element:
8947 * name, // As appears in the GUI tree
8948 * abbrev, // Referenced by filters (rtps.xxxx[.yyyy])
8949 * type, // FT_BOOLEAN, FT_UINT8, ...
8950 * display, // BASE_HEX | BASE_DEC | BASE_OCT or other meanings
8951 * strings, // String table (for enums) or NULL
8952 * bitmask, // only for bitfields
8953 * blurb, // Complete description of this item
8958 static hf_register_info hf[] = {
8960 /* Protocol Version (composed as major.minor) -------------------------- */
8961 { &hf_rtps_protocol_version, {
8968 "RTPS protocol version number",
8971 { &hf_rtps_protocol_version_major, {
8973 "rtps2.version.major",
8978 "RTPS major protocol version number",
8981 { &hf_rtps_protocol_version_minor, {
8983 "rtps2.version.minor",
8988 "RTPS minor protocol version number",
8992 /* Domain Participant and Participant Index ---------------------------- */
8993 { &hf_rtps_domain_id, {
9004 { &hf_rtps_participant_idx, {
9006 "rtps2.participant_idx",
9011 "Participant index",
9014 { &hf_rtps_nature_type, {
9016 "rtps2.traffic_nature",
9019 VALS(nature_type_vals),
9021 "Nature of the traffic (meta/user-traffic uni/multi-cast)",
9025 /* Vendor ID ----------------------------------------------------------- */
9026 { &hf_rtps_vendor_id, {
9033 "Unique identifier of the DDS vendor that generated this packet",
9037 /* Guid Prefix for the Packet ------------------------------------------ */
9038 { &hf_rtps_guid_prefix, {
9045 "GuidPrefix of the RTPS packet",
9049 /* Host ID ------------------------------------------------------------- */
9050 { &hf_rtps_host_id, { /* HIDDEN */
9057 "Sub-component 'hostId' of the GuidPrefix of the RTPS packet",
9061 /* AppID --------------------------------------------------------------- */
9062 { &hf_rtps_app_id, {
9069 "Sub-component 'appId' of the GuidPrefix of the RTPS packet",
9073 /* Counter ------------------------------------------------------------- */
9074 { &hf_rtps_counter, { /* HIDDEN */
9081 "Sub-component 'counter' of the GuidPrefix of the RTPS packet",
9086 /* Submessage ID ------------------------------------------------------- */
9092 VALS(submessage_id_vals),
9094 "defines the type of submessage",
9098 /* Submessage flags ---------------------------------------------------- */
9099 { &hf_rtps_sm_flags, {
9106 "bitmask representing the flags associated with a submessage",
9110 /* octets to next header ---------------------------------------------- */
9111 { &hf_rtps_sm_octets_to_next_header, {
9112 "octetsToNextHeader",
9113 "rtps2.sm.octetsToNextHeader",
9118 "Size of the submessage payload",
9122 /* GUID as {GuidPrefix, EntityId} ------------------------------------ */
9123 { &hf_rtps_sm_guid_prefix, {
9125 "rtps2.sm.guidPrefix",
9130 "a generic guidPrefix that is transmitted inside the submessage (this is NOT the guidPrefix described in the packet header",
9134 { &hf_rtps_sm_host_id, {
9136 "rtps2.sm.guidPrefix.hostId",
9141 "The hostId component of the rtps2.sm.guidPrefix",
9145 { &hf_rtps_sm_app_id, {
9147 "rtps2.sm.guidPrefix.appId",
9152 "AppId component of the rtps2.sm.guidPrefix",
9155 { &hf_rtps_sm_instance_id, {
9157 "rtps2.sm.guidPrefix.appId.instanceId",
9162 "instanceId component of the AppId of the rtps2.sm.guidPrefix",
9165 { &hf_rtps_sm_app_kind, {
9167 "rtps2.sm.guidPrefix.appId.appKind",
9172 "appKind component of the AppId of the rtps2.sm.guidPrefix",
9176 { &hf_rtps_sm_counter, {
9178 "rtps2.sm.guidPrefix.counter",
9183 "The counter component of the rtps2.sm.guidPrefix",
9187 /* Entity ID (composed as entityKey, entityKind) ----------------------- */
9188 { &hf_rtps_sm_entity_id, {
9190 "rtps2.sm.entityId",
9193 VALS(entity_id_vals),
9195 "Object entity ID as it appears in a DATA submessage (keyHashSuffix)",
9198 { &hf_rtps_sm_entity_id_key, {
9200 "rtps2.sm.entityId.entityKey",
9205 "'entityKey' field of the object entity ID",
9208 { &hf_rtps_sm_entity_id_kind, {
9210 "rtps2.sm.entityId.entityKind",
9213 VALS(entity_kind_vals),
9215 "'entityKind' field of the object entity ID",
9219 { &hf_rtps_sm_rdentity_id, {
9221 "rtps2.sm.rdEntityId",
9224 VALS(entity_id_vals),
9226 "Reader entity ID as it appears in a submessage",
9229 { &hf_rtps_sm_rdentity_id_key, {
9231 "rtps2.sm.rdEntityId.entityKey",
9236 "'entityKey' field of the reader entity ID",
9239 { &hf_rtps_sm_rdentity_id_kind, {
9241 "rtps2.sm.rdEntityId.entityKind",
9244 VALS(entity_kind_vals),
9246 "'entityKind' field of the reader entity ID",
9250 { &hf_rtps_sm_wrentity_id, {
9252 "rtps2.sm.wrEntityId",
9255 VALS(entity_id_vals),
9257 "Writer entity ID as it appears in a submessage",
9260 { &hf_rtps_sm_wrentity_id_key, {
9262 "rtps2.sm.wrEntityId.entityKey",
9267 "'entityKey' field of the writer entity ID",
9270 { &hf_rtps_sm_wrentity_id_kind, {
9272 "rtps2.sm.wrEntityId.entityKind",
9275 VALS(entity_kind_vals),
9277 "'entityKind' field of the writer entity ID",
9283 /* Sequence number ----------------------------------------------------- */
9284 { &hf_rtps_sm_seq_number, {
9286 "rtps2.sm.seqNumber",
9291 "Writer sequence number",
9295 /* Parameter Id -------------------------------------------------------- */
9296 { &hf_rtps_parameter_id, {
9301 VALS(parameter_id_vals),
9307 /* Parameter Length ---------------------------------------------------- */
9308 { &hf_rtps_parameter_length, {
9310 "rtps2.param.length",
9319 /* Parameter / Status Info --------------------------------------------- */
9320 { &hf_rtps_param_status_info, {
9322 "rtps2.param.statusInfo",
9327 "State information of the data object to which the message apply (i.e. lifecycle)",
9331 /* Parameter / NtpTime ------------------------------------------------- */
9332 { &hf_rtps_param_ntpt, {
9334 "rtps2.param.ntpTime",
9339 "Time using the NTP standard format",
9342 { &hf_rtps_param_ntpt_sec, {
9344 "rtps2.param.ntpTime.sec",
9349 "The 'second' component of a NTP time",
9352 { &hf_rtps_param_ntpt_fraction, {
9354 "rtps2.param.ntpTime.fraction",
9359 "The 'fraction' component of a NTP time",
9364 /* Parameter / Topic --------------------------------------------------- */
9365 { &hf_rtps_param_topic_name, {
9367 "rtps2.param.topicName",
9372 "String representing the value value of a PID_TOPIC parameter",
9376 /* Parameter / Entity -------------------------------------------------- */
9377 { &hf_rtps_param_entity_name, {
9379 "rtps2.param.entityName",
9384 "String representing the name of the entity addressed by the submessage",
9389 /* Parameter / Strength ------------------------------------------------ */
9390 { &hf_rtps_param_strength, {
9392 "rtps2.param.strength",
9397 "Decimal value representing the value of a PID_OWNERSHIP_STRENGTH parameter",
9401 /* Parameter / Type Name ----------------------------------------------- */
9402 { &hf_rtps_param_type_name, {
9404 "rtps2.param.typeName",
9409 "String representing the value of a PID_TYPE_NAME parameter",
9413 /* Parameter / User Data ----------------------------------------------- */
9414 { &hf_rtps_param_user_data, {
9416 "rtps2.param.userData",
9421 "The user data sent in a PID_USER_DATA parameter",
9425 /* Parameter / Group Data ---------------------------------------------- */
9426 { &hf_rtps_param_group_data, {
9428 "rtps2.param.groupData",
9433 "The user data sent in a PID_GROUP_DATA parameter",
9437 /* Parameter / Topic Data ---------------------------------------------- */
9438 { &hf_rtps_param_topic_data, {
9440 "rtps2.param.topicData",
9445 "The user data sent in a PID_TOPIC_DATA parameter",
9450 /* Parameter / Content Filter Name ------------------------------------- */
9451 { &hf_rtps_param_content_filter_name, {
9452 "contentFilterName",
9453 "rtps2.param.contentFilterName",
9458 "Value of the content filter name as sent in a PID_CONTENT_FILTER_PROPERTY parameter",
9461 { &hf_rtps_param_related_topic_name, {
9463 "rtps2.param.relatedTopicName",
9468 "Value of the related topic name as sent in a PID_CONTENT_FILTER_PROPERTY parameter",
9471 { &hf_rtps_param_filter_name, {
9473 "rtps2.param.filterName",
9478 "Value of the filter name as sent in a PID_CONTENT_FILTER_PROPERTY parameter",
9482 /* Finally the raw issue data ------------------------------------------ */
9483 { &hf_rtps_issue_data, {
9485 "rtps2.serializedData",
9490 "The user data transferred in a ISSUE submessage",
9496 static gint *ett[] = {
9498 &ett_rtps_default_mapping,
9499 &ett_rtps_proto_version,
9500 &ett_rtps_submessage,
9501 &ett_rtps_parameter_sequence,
9502 &ett_rtps_parameter,
9507 &ett_rtps_guid_prefix,
9508 &ett_rtps_part_message_data,
9509 &ett_rtps_part_message_guid,
9510 &ett_rtps_locator_udp_v4,
9512 &ett_rtps_locator_list,
9515 &ett_rtps_seq_string,
9516 &ett_rtps_seq_ulong,
9517 &ett_rtps_serialized_data,
9518 &ett_rtps_sample_info_list,
9519 &ett_rtps_sample_info,
9520 &ett_rtps_sample_batch_list,
9521 &ett_rtps_locator_filter_channel,
9522 &ett_rtps_locator_filter_locator
9524 module_t *rtps_module;
9526 proto_rtps = proto_register_protocol(
9527 "Real-Time Publish-Subscribe Wire Protocol 2.x",
9530 proto_register_field_array(proto_rtps, hf, array_length(hf));
9531 proto_register_subtree_array(ett, array_length(ett));
9533 /* Registers the control in the preference panel */
9534 rtps_module = prefs_register_protocol(proto_rtps, NULL);
9535 prefs_register_uint_preference(rtps_module, "max_batch_samples_dissected",
9536 "Max samples dissected for DATA_BATCH",
9537 "Specifies the maximum number of samples dissected in "
9538 "a DATA_BATCH submessage. Increasing this value may affect "
9539 "performances if the trace has a lot of big batched samples.",
9540 10, &rtps_max_batch_samples_dissected);
9543 void proto_reg_handoff_rtps2(void) {
9544 heur_dissector_add("udp", dissect_rtps, proto_rtps);