4 * Routines for Real-Time Publish-Subscribe Protocol (RTPS) dissection
6 * Copyright 2005, Fabrizio Bertocci <fabrizio@rti.com>
7 * Real-Time Innovations, Inc.
9 * Santa Clara, CA 95054
11 * Copyright 2003, LUKAS POKORNY <maskis@seznam.cz>
12 * PETR SMOLIK <petr.smolik@wo.cz>
13 * ZDENEK SEBEK <sebek@fel.cvut.cz>
14 * Czech Technical University in Prague
15 * Faculty of Electrical Engineering <www.fel.cvut.cz>
16 * Department of Control Engineering <dce.felk.cvut.cz>
20 * Wireshark - Network traffic analyzer
21 * By Gerald Combs <gerald@wireshark.org>
22 * Copyright 1998 Gerald Combs
24 * This program is free software; you can redistribute it and/or modify
25 * it under the terms of the GNU General Public License as published by
26 * the Free Software Foundation; either version 2 of the License, or
27 * (at your option) any later version.
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU General Public License for more details.
34 * You should have received a copy of the GNU General Public License
35 * along with this program; if not, write to the Free Software
36 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 * -------------------------------------
40 * The following file is part of the RTPS packet dissector for Wireshark.
42 * RTPS protocol was developed by Real-Time Innovations, Inc. as wire
43 * protocol for Data Distribution System.
44 * Additional information at:
45 * Full OMG DDS Standard Specification:
46 * http://www.omg.org/cgi-bin/doc?ptc/2003-07-07
48 * NDDS and RTPS information: http://www.rti.com/resources.html
61 #include <epan/packet.h>
62 #include <epan/addr_resolv.h>
65 #include "packet-rtps.h"
67 /* Size of the temp buffers used to format various part of the protocol.
68 * Note: Some of those values are bigger than expected. The reason is
69 * because the string buffer can also contains decoded values.
70 * I.e. port size is an integer, but for value 0x0000, it is interpreted
71 * as a string "PORT_INVALID (0x00000000)"
73 #define MAX_FLAG_SIZE (20)
74 #define MAX_GUID_PREFIX_SIZE (128)
75 #define MAX_GUID_SIZE (160)
76 #define MAX_VENDOR_ID_SIZE (128)
77 #define MAX_NTP_TIME_SIZE (128)
78 #define MAX_PORT_SIZE (32)
79 #define MAX_PARAM_SIZE (256)
80 #define MAX_LOCATOR_SIZE (200)
81 #define MAX_IPV6_SIZE (100)
82 #define MAX_BITMAP_SIZE (200)
83 #define MAX_LABEL_SIZE (64)
84 #define MAX_IPV4_ADDRESS_SIZE (64)
86 /* Max octects printed on the parameter root for a sequence of octects */
87 #define MAX_SEQ_OCTETS_PRINTED (20)
90 static const char * const SM_EXTRA_RPLUS = "(r+)";
91 static const char * const SM_EXTRA_RMINUS = "(r-)";
92 static const char * const SM_EXTRA_WPLUS = "(w+)";
93 static const char * const SM_EXTRA_WMINUS = "(w-)";
94 static const char * const SM_EXTRA_PPLUS = "(p+)";
95 static const char * const SM_EXTRA_PMINUS = "(p-)";
96 static const char * const SM_EXTRA_TPLUS = "(t+)";
97 static const char * const SM_EXTRA_TMINUS = "(t-)";
99 /* This structure is used to keep a list of submessages for the current
100 * packet. The list is ordered by position of the submessage Id inside
102 * Submessages of the same kind are grouped together in one record.
104 struct SMCounterRecord {
105 int id; /* PAD, DATA, ... */
106 const char * extra; /* (r+, w+)... */
107 struct SMCounterRecord * next; /* Ptr to next */
113 /***************************************************************************/
114 /* Protocol Fields Identifiers */
115 static int proto_rtps = -1;
116 static int hf_rtps_protocol_version = -1;
117 static int hf_rtps_protocol_version_major = -1;
118 static int hf_rtps_protocol_version_minor = -1;
119 static int hf_rtps_vendor_id = -1;
121 static int hf_rtps_domain_id = -1;
122 static int hf_rtps_participant_idx = -1;
123 static int hf_rtps_nature_type = -1;
125 static int hf_rtps_guid_prefix = -1;
126 static int hf_rtps_host_id = -1;
127 static int hf_rtps_app_id = -1;
128 static int hf_rtps_app_id_instance_id = -1;
129 static int hf_rtps_app_id_app_kind = -1;
131 static int hf_rtps_sm_id = -1;
132 static int hf_rtps_sm_flags = -1;
133 static int hf_rtps_sm_octets_to_next_header = -1;
134 static int hf_rtps_sm_guid_prefix = -1;
135 static int hf_rtps_sm_host_id = -1;
136 static int hf_rtps_sm_app_id = -1;
137 static int hf_rtps_sm_instance_id = -1;
138 static int hf_rtps_sm_app_kind = -1;
139 static int hf_rtps_sm_entity_id = -1;
140 static int hf_rtps_sm_entity_id_key = -1;
141 static int hf_rtps_sm_entity_id_kind = -1;
142 static int hf_rtps_sm_rdentity_id = -1;
143 static int hf_rtps_sm_rdentity_id_key = -1;
144 static int hf_rtps_sm_rdentity_id_kind = -1;
145 static int hf_rtps_sm_wrentity_id = -1;
146 static int hf_rtps_sm_wrentity_id_key = -1;
147 static int hf_rtps_sm_wrentity_id_kind = -1;
148 static int hf_rtps_sm_seq_number = -1;
150 static int hf_rtps_parameter_id = -1;
151 static int hf_rtps_parameter_length = -1;
152 static int hf_rtps_param_ntpt = -1;
153 static int hf_rtps_param_ntpt_sec = -1;
154 static int hf_rtps_param_ntpt_fraction = -1;
155 static int hf_rtps_param_topic_name = -1;
156 static int hf_rtps_param_strength = -1;
157 static int hf_rtps_param_type_name = -1;
158 static int hf_rtps_param_user_data = -1;
159 static int hf_rtps_param_group_data = -1;
160 static int hf_rtps_param_topic_data = -1;
161 static int hf_rtps_param_content_filter_name = -1;
162 static int hf_rtps_param_related_topic_name = -1;
163 static int hf_rtps_param_filter_name = -1;
164 static int hf_rtps_issue_data = -1;
166 /* Subtree identifiers */
167 static gint ett_rtps = -1;
168 static gint ett_rtps_default_mapping = -1;
169 static gint ett_rtps_proto_version = -1;
170 static gint ett_rtps_submessage = -1;
171 static gint ett_rtps_parameter_sequence = -1;
172 static gint ett_rtps_parameter = -1;
173 static gint ett_rtps_flags = -1;
174 static gint ett_rtps_entity = -1;
175 static gint ett_rtps_rdentity = -1;
176 static gint ett_rtps_wrentity = -1;
177 static gint ett_rtps_guid_prefix = -1;
178 static gint ett_rtps_app_id = -1;
179 static gint ett_rtps_locator_udp_v4 = -1;
180 static gint ett_rtps_locator = -1;
181 static gint ett_rtps_locator_list = -1;
182 static gint ett_rtps_ntp_time = -1;
183 static gint ett_rtps_bitmap = -1;
184 static gint ett_rtps_seq_string = -1;
185 static gint ett_rtps_seq_ulong = -1;
187 /***************************************************************************/
188 /* Value-to-String Tables */
189 static const value_string entity_id_vals[] = {
190 { ENTITYID_UNKNOWN, "ENTITYID_UNKNOWN" },
191 { ENTITYID_BUILTIN_TOPIC_WRITER, "ENTITYID_BUILTIN_TOPIC_WRITER" },
192 { ENTITYID_BUILTIN_TOPIC_READER, "ENTITYID_BUILTIN_TOPIC_READER" },
193 { ENTITYID_BUILTIN_PUBLICATIONS_WRITER, "ENTITYID_BUILTIN_PUBLICATIONS_WRITER" },
194 { ENTITYID_BUILTIN_PUBLICATIONS_READER, "ENTITYID_BUILTIN_PUBLICATIONS_READER" },
195 { ENTITYID_BUILTIN_SUBSCRIPTIONS_WRITER, "ENTITYID_BUILTIN_SUBSCRIPTIONS_WRITER" },
196 { ENTITYID_BUILTIN_SUBSCRIPTIONS_READER, "ENTITYID_BUILTIN_SUBSCRIPTIONS_READER" },
197 { ENTITYID_BUILTIN_SDP_PARTICIPANT_WRITER, "ENTITYID_BUILTIN_SDP_PARTICIPANT_WRITER" },
198 { ENTITYID_BUILTIN_SDP_PARTICIPANT_READER, "ENTITYID_BUILTIN_SDP_PARTICIPANT_READER" },
200 /* Deprecated Items */
201 { ENTITYID_APPLICATIONS_WRITER, "writerApplications [DEPRECATED]" },
202 { ENTITYID_APPLICATIONS_READER, "readerApplications [DEPRECATED]" },
203 { ENTITYID_CLIENTS_WRITER, "writerClients [DEPRECATED]" },
204 { ENTITYID_CLIENTS_READER, "readerClients [DEPRECATED]" },
205 { ENTITYID_SERVICES_WRITER, "writerServices [DEPRECATED]" },
206 { ENTITYID_SERVICES_READER, "readerServices [DEPRECATED]" },
207 { ENTITYID_MANAGERS_WRITER, "writerManagers [DEPRECATED]" },
208 { ENTITYID_MANAGERS_READER, "readerManagers [DEPRECATED]" },
209 { ENTITYID_APPLICATION_SELF, "applicationSelf [DEPRECATED]" },
210 { ENTITYID_APPLICATION_SELF_WRITER, "writerApplicationSelf [DEPRECATED]" },
211 { ENTITYID_APPLICATION_SELF_READER, "readerApplicationSelf [DEPRECATED]" },
215 static const value_string entity_kind_vals [] = {
216 { ENTITYKIND_APPDEF_UNKNOWN, "Application-defined unknown kind" },
217 { ENTITYKIND_APPDEF_PARTICIPANT, "Application-defined participant" },
218 { ENTITYKIND_APPDEF_WRITER_WITH_KEY, "Application-defined writer (with key)" },
219 { ENTITYKIND_APPDEF_WRITER_NO_KEY, "Application-defined writer (no key)" },
220 { ENTITYKIND_APPDEF_READER_WITH_KEY, "Application-defined reader (with key)" },
221 { ENTITYKIND_APPDEF_READER_NO_KEY, "Application-defined reader (no key)" },
222 { ENTITYKIND_BUILTIN_PARTICIPANT, "Built-in participant" },
223 { ENTITYKIND_BUILTIN_WRITER_WITH_KEY, "Built-in writer (with key)" },
224 { ENTITYKIND_BUILTIN_WRITER_NO_KEY, "Built-in writer (no key)" },
225 { ENTITYKIND_BUILTIN_READER_WITH_KEY, "Built-in reader (with key)" },
226 { ENTITYKIND_BUILTIN_READER_NO_KEY, "Built-in reader (no key)" },
231 static const value_string nature_type_vals[] = {
232 { PORT_METATRAFFIC_UNICAST, "UNICAST_METATRAFFIC"},
233 { PORT_METATRAFFIC_MULTICAST, "MULTICAST_METATRAFFIC"},
234 { PORT_USERTRAFFIC_UNICAST, "UNICAST_USERTRAFFIC"},
235 { PORT_USERTRAFFIC_MULTICAST, "MULTICAST_USERTRAFFIC"},
240 static const value_string app_kind_vals[] = {
241 { APPKIND_UNKNOWN, "APPKIND_UNKNOWN" },
242 { APPKIND_MANAGED_APPLICATION, "ManagedApplication" },
243 { APPKIND_MANAGER, "Manager" },
248 static const value_string submessage_id_vals[] = {
251 { NOKEY_DATA, "NOKEY_DATA" },
252 { ACKNACK, "ACKNACK" },
253 { HEARTBEAT, "HEARTBEAT" },
255 { INFO_TS, "INFO_TS" },
256 { INFO_SRC, "INFO_SRC" },
257 { INFO_REPLY_IP4, "INFO_REPLY_IP4" },
258 { INFO_DST, "INFO_DST" },
259 { INFO_REPLY, "INFO_REPLY" },
263 static const value_string typecode_kind_vals[] = {
264 { RTI_CDR_TK_NULL, "(unknown)" },
265 { RTI_CDR_TK_SHORT, "short" },
266 { RTI_CDR_TK_LONG, "long" },
267 { RTI_CDR_TK_USHORT, "unsigned short" },
268 { RTI_CDR_TK_ULONG, "unsigned long" },
269 { RTI_CDR_TK_FLOAT, "float" },
270 { RTI_CDR_TK_DOUBLE, "double" },
271 { RTI_CDR_TK_BOOLEAN, "boolean" },
272 { RTI_CDR_TK_CHAR, "char" },
273 { RTI_CDR_TK_OCTET, "octet" },
274 { RTI_CDR_TK_STRUCT, "struct" },
275 { RTI_CDR_TK_UNION, "union" },
276 { RTI_CDR_TK_ENUM, "enum" },
277 { RTI_CDR_TK_STRING, "string" },
278 { RTI_CDR_TK_SEQUENCE, "sequence" },
279 { RTI_CDR_TK_ARRAY, "array" },
280 { RTI_CDR_TK_ALIAS, "alias" },
281 { RTI_CDR_TK_LONGLONG, "long long" },
282 { RTI_CDR_TK_ULONGLONG, "unsigned long long" },
283 { RTI_CDR_TK_LONGDOUBLE, "long double" },
284 { RTI_CDR_TK_WCHAR, "wchar" },
285 { RTI_CDR_TK_WSTRING, "wstring" },
289 static const value_string parameter_id_vals[] = {
290 { PID_PAD, "PID_PAD" },
291 { PID_SENTINEL, "PID_SENTINEL" },
292 { PID_USER_DATA, "PID_USER_DATA" },
293 { PID_TOPIC_NAME, "PID_TOPIC_NAME" },
294 { PID_TYPE_NAME, "PID_TYPE_NAME" },
295 { PID_GROUP_DATA, "PID_GROUP_DATA" },
296 { PID_DEADLINE, "PID_DEADLINE" },
297 { PID_DEADLINE_OFFERED, "PID_DEADLINE_OFFERED [deprecated]" },
298 { PID_PARTICIPANT_LEASE_DURATION, "PID_PARTICIPANT_LEASE_DURATION" },
299 { PID_PERSISTENCE, "PID_PERSISTENCE" },
300 { PID_TIME_BASED_FILTER, "PID_TIME_BASED_FILTER" },
301 { PID_OWNERSHIP_STRENGTH, "PID_OWNERSHIP_STRENGTH" },
302 { PID_TYPE_CHECKSUM, "PID_TYPE_CHECKSUM [deprecated]" },
303 { PID_TYPE2_NAME, "PID_TYPE2_NAME [deprecated]" },
304 { PID_TYPE2_CHECKSUM, "PID_TYPE2_CHECKSUM [deprecated]" },
305 { PID_METATRAFFIC_MULTICAST_IPADDRESS,"PID_METATRAFFIC_MULTICAST_IPADDRESS"},
306 { PID_DEFAULT_UNICAST_IPADDRESS, "PID_DEFAULT_UNICAST_IPADDRESS" },
307 { PID_METATRAFFIC_UNICAST_PORT, "PID_METATRAFFIC_UNICAST_PORT" },
308 { PID_DEFAULT_UNICAST_PORT, "PID_DEFAULT_UNICAST_PORT" },
309 { PID_IS_RELIABLE, "PID_IS_RELIABLE [deprecated]" },
310 { PID_EXPECTS_ACK, "PID_EXPECTS_ACK" },
311 { PID_MULTICAST_IPADDRESS, "PID_MULTICAST_IPADDRESS" },
312 { PID_MANAGER_KEY, "PID_MANAGER_KEY [deprecated]" },
313 { PID_SEND_QUEUE_SIZE, "PID_SEND_QUEUE_SIZE" },
314 { PID_RELIABILITY_ENABLED, "PID_RELIABILITY_ENABLED" },
315 { PID_PROTOCOL_VERSION, "PID_PROTOCOL_VERSION" },
316 { PID_VENDOR_ID, "PID_VENDOR_ID" },
317 { PID_VARGAPPS_SEQUENCE_NUMBER_LAST, "PID_VARGAPPS_SEQUENCE_NUMBER_LAST [deprecated]" },
318 { PID_RECV_QUEUE_SIZE, "PID_RECV_QUEUE_SIZE [deprecated]" },
319 { PID_RELIABILITY_OFFERED, "PID_RELIABILITY_OFFERED [deprecated]" },
320 { PID_RELIABILITY, "PID_RELIABILITY" },
321 { PID_LIVELINESS, "PID_LIVELINESS" },
322 { PID_LIVELINESS_OFFERED, "PID_LIVELINESS_OFFERED [deprecated]" },
323 { PID_DURABILITY, "PID_DURABILITY" },
324 { PID_DURABILITY_SERVICE, "PID_DURABILITY_SERVICE" },
325 { PID_PRESENTATION_OFFERED, "PID_PRESENTATION_OFFERED [deprecated]" },
326 { PID_OWNERSHIP, "PID_OWNERSHIP" },
327 { PID_OWNERSHIP_OFFERED, "PID_OWNERSHIP_OFFERED [deprecated]" },
328 { PID_PRESENTATION, "PID_PRESENTATION" },
329 { PID_DESTINATION_ORDER, "PID_DESTINATION_ORDER" },
330 { PID_DESTINATION_ORDER_OFFERED, "PID_DESTINATION_ORDER_OFFERED [deprecated]" },
331 { PID_LATENCY_BUDGET, "PID_LATENCY_BUDGET" },
332 { PID_LATENCY_BUDGET_OFFERED, "PID_LATENCY_BUDGET_OFFERED [deprecated]" },
333 { PID_PARTITION, "PID_PARTITION" },
334 { PID_PARTITION_OFFERED, "PID_PARTITION_OFFERED [deprecated]" },
335 { PID_LIFESPAN, "PID_LIFESPAN" },
336 { PID_TOPIC_DATA, "PID_TOPIC_DATA" },
337 { PID_UNICAST_LOCATOR, "PID_UNICAST_LOCATOR" },
338 { PID_MULTICAST_LOCATOR, "PID_MULTICAST_LOCATOR" },
339 { PID_DEFAULT_UNICAST_LOCATOR, "PID_DEFAULT_UNICAST_LOCATOR" },
340 { PID_METATRAFFIC_UNICAST_LOCATOR, "PID_METATRAFFIC_UNICAST_LOCATOR " },
341 { PID_METATRAFFIC_MULTICAST_LOCATOR, "PID_METATRAFFIC_MULTICAST_LOCATOR" },
342 { PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT, "PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT" },
343 { PID_HISTORY, "PID_HISTORY" },
344 { PID_RESOURCE_LIMIT, "PID_RESOURCE_LIMIT" },
345 { PID_METATRAFFIC_MULTICAST_PORT, "PID_METATRAFFIC_MULTICAST_PORT" },
346 { PID_DEFAULT_EXPECTS_INLINE_QOS, "PID_DEFAULT_EXPECTS_INLINE_QOS" },
347 { PID_METATRAFFIC_UNICAST_IPADDRESS, "PID_METATRAFFIC_UNICAST_IPADDRESS" },
348 { PID_PARTICIPANT_BUILTIN_ENDPOINTS, "PID_PARTICIPANT_BUILTIN_ENDPOINTS" },
349 { PID_CONTENT_FILTER_PROPERTY, "PID_CONTENT_FILTER_PROPERTY" },
350 { PID_PROPERTY_LIST, "PID_PROPERTY_LIST" },
351 { PID_FILTER_SIGNATURE, "PID_FILTER_SIGNATURE" },
352 { PID_COHERENT_SET, "PID_COHERENT_SET" },
353 { PID_TYPECODE, "PID_TYPECODE" },
354 { PID_PARTICIPANT_GUID, "PID_PARTICIPANT_GUID" },
355 { PID_PARTICIPANT_ENTITY_ID, "PID_PARTICIPANT_ENTITY_ID" },
356 { PID_GROUP_GUID, "PID_GROUP_GUID" },
357 { PID_GROUP_ENTITY_ID, "PID_GROUP_ENTITY_ID" },
361 static const value_string liveliness_qos_vals[] = {
362 { LIVELINESS_AUTOMATIC, "AUTOMATIC_LIVELINESS_QOS" },
363 { LIVELINESS_BY_PARTICIPANT, "MANUAL_BY_PARTICIPANT_LIVELINESS_QOS" },
364 { LIVELINESS_BY_TOPIC, "MANUAL_BY_TOPIC_LIVELINESS_QOS" },
368 static const value_string durability_qos_vals[] = {
369 { DURABILITY_VOLATILE, "VOLATILE_DURABILITY_QOS" },
370 { DURABILITY_TRANSIENT_LOCAL, "TRANSIENT_LOCAL_DURABILITY_QOS" },
371 { DURABILITY_TRANSIENT, "TRANSIENT_DURABILITY_QOS" },
372 { DURABILITY_PERSISTENT, "PERSISTENT_DURABILITY_QOS" },
376 static const value_string ownership_qos_vals[] = {
377 { OWNERSHIP_SHARED, "SHARED_OWNERSHIP_QOS" },
378 { OWNERSHIP_EXCLUSIVE, "EXCLUSIVE_OWNERSHIP_QOS" },
382 static const value_string presentation_qos_vals[] = {
383 { PRESENTATION_INSTANCE, "INSTANCE_PRESENTATION_QOS" },
384 { PRESENTATION_TOPIC, "TOPIC_PRESENTATION_QOS" },
385 { PRESENTATION_GROUP, "GROUP_PRESENTATION_QOS" },
389 static const value_string history_qos_vals[] = {
390 { HISTORY_KIND_KEEP_LAST, "KEEP_LAST_HISTORY_QOS" },
391 { HISTORY_KIND_KEEP_ALL, "KEEP_ALL_HISTORY_QOS" },
395 static const value_string reliability_qos_vals[] = {
396 { RELIABILITY_BEST_EFFORT, "BEST_EFFORT_RELIABILITY_QOS" },
397 { RELIABILITY_RELIABLE, "RELIABLE_RELIABILITY_QOS" },
401 static const value_string destination_order_qos_vals[] = {
402 { BY_RECEPTION_TIMESTAMP, "BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS" },
403 { BY_SOURCE_TIMESTAMP, "BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS" },
408 /* Flag Decoding defintions ***********************************************/
409 struct Flag_definition {
411 const char *description;
414 #define RESERVEDFLAG_CHAR ('_')
415 #define RESERVEDFLAG_STRING ("reserved bit")
417 static const struct Flag_definition PAD_FLAGS[] = {
418 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
419 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
420 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
421 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 4 */
422 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 3 */
423 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 2 */
424 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 1 */
425 { 'E', "Endianness bit" } /* Bit 0 */
428 static const struct Flag_definition DATA_FLAGS[] = {
429 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
430 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
431 { 'U', "Unregister flag" }, /* Bit 5 */
432 { 'Q', "Inline QoS" }, /* Bit 4 */
433 { 'H', "Hash key flag" }, /* Bit 3 */
434 { 'A', "Alive flag" }, /* Bit 2 */
435 { 'D', "Data present" }, /* Bit 1 */
436 { 'E', "Endianness bit" } /* Bit 0 */
439 static const struct Flag_definition NOKEY_DATA_FLAGS[] = {
440 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
441 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
442 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
443 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 4 */
444 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 3 */
445 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 2 */
446 { 'Q', "Inline QoS" }, /* Bit 1 */
447 { 'E', "Endianness bit" } /* Bit 0 */
450 static const struct Flag_definition ACKNACK_FLAGS[] = {
451 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
452 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
453 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
454 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 4 */
455 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 3 */
456 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 2 */
457 { 'F', "Final flag" }, /* Bit 1 */
458 { 'E', "Endianness bit" } /* Bit 0 */
461 static const struct Flag_definition GAP_FLAGS[] = {
462 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
463 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
464 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
465 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 4 */
466 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 3 */
467 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 2 */
468 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 1 */
469 { 'E', "Endianness bit" } /* Bit 0 */
472 static const struct Flag_definition HEARTBEAT_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 { 'L', "Liveliness flag" }, /* Bit 2 */
479 { 'F', "Final flag" }, /* Bit 1 */
480 { 'E', "Endianness bit" } /* Bit 0 */
483 static const struct Flag_definition INFO_TS_FLAGS[] = {
484 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 7 */
485 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 6 */
486 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 5 */
487 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 4 */
488 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 3 */
489 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 2 */
490 { 'T', "Timestamp flag" }, /* Bit 1 */
491 { 'E', "Endianness bit" } /* Bit 0 */
494 static const struct Flag_definition INFO_SRC_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 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 2 */
501 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 1 */
502 { 'E', "Endianness bit" } /* Bit 0 */
505 static const struct Flag_definition INFO_REPLY_IP4_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 { 'M', "Multicast flag" }, /* Bit 1 */
513 { 'E', "Endianness bit" } /* Bit 0 */
516 static const struct Flag_definition INFO_DST_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 INFO_REPLY_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 { RESERVEDFLAG_CHAR, RESERVEDFLAG_STRING }, /* Bit 2 */
534 { 'M', "Multicast flag" }, /* Bit 1 */
535 { 'E', "Endianness bit" } /* Bit 0 */
539 /***************************************************************************/
545 /***************************************************************************
546 * Function prototypes
547 * ~~~~~~~~~~~~~~~~~~~
551 static struct SMCounterRecord * sm_counter_add(struct SMCounterRecord *, guint8, const char * const extra);
552 static void sm_counter_free(struct SMCounterRecord *);
555 /* Utility to add elements to the protocol tree */
556 static void rtps_util_format_ipv6(guint8 *, guint8 *, gint);
557 static void rtps_util_add_protocol_version(proto_tree *, tvbuff_t *, gint);
558 static void rtps_util_add_vendor_id(proto_tree *, tvbuff_t *,
559 gint, guint8 *, gint);
560 static void rtps_util_add_locator_t(proto_tree *, tvbuff_t *,
561 gint, int, const guint8 *, guint8 *, gint);
562 static void rtps_util_add_locator_list(proto_tree *, tvbuff_t *,
563 gint, const guint8 *, int);
564 static void rtps_util_add_ipv4_address_t(proto_tree *, tvbuff_t *,
565 gint, int, const guint8 *, guint8 *, gint);
566 static void rtps_util_add_locator_udp_v4(proto_tree *, tvbuff_t *,
567 gint, const guint8 *, int);
568 static void rtps_util_add_guid_prefix(proto_tree *, tvbuff_t *,
569 gint, int, int, int, int, int, const guint8 *,
571 static int rtps_util_add_entity_id(proto_tree *, tvbuff_t *,
572 gint, int, int, int, int, const char *, guint32 *);
573 static void rtps_util_add_generic_entity_id(proto_tree *, tvbuff_t *,
576 static void rtps_util_add_generic_guid(proto_tree *, tvbuff_t *,
577 gint, const char *, guint8 *, gint);
578 static guint64 rtps_util_add_seq_number(proto_tree *, tvbuff_t *,
579 gint, int, const char *);
580 static void rtps_util_add_ntp_time(proto_tree *, tvbuff_t *,
581 gint, int, const char *, guint8 *, gint);
582 static gint rtps_util_add_string(proto_tree *, tvbuff_t *,
583 gint, int, int, const guint8 *, guint8 *, size_t);
584 static void rtps_util_add_long(proto_tree *, tvbuff_t *,
585 gint, int, int, gboolean, gboolean, const char *,
587 static void rtps_util_add_port(proto_tree *, tvbuff_t *,
588 gint, int, char *, guint8 *, gint);
589 static void rtps_util_add_boolean(proto_tree *, tvbuff_t *,
590 gint, char *, guint8 *, size_t);
591 static void rtps_util_add_durability_service_qos(proto_tree *, tvbuff_t *,
592 gint, int, guint8 *, gint);
593 static void rtps_util_add_liveliness_qos(proto_tree *, tvbuff_t *,
594 gint, int, guint8 *, gint);
595 static void rtps_util_add_kind_qos(proto_tree *, tvbuff_t *,
596 gint, int, char *, const value_string *, guint8 *, size_t);
597 static gint rtps_util_add_seq_string(proto_tree *, tvbuff_t *,
598 gint, int, int, char *, guint8 *, gint);
599 static void rtps_util_add_seq_octets(proto_tree *, tvbuff_t *,
600 gint, int, int, int, guint8 *, gint);
601 static int rtps_util_add_bitmap(proto_tree *, tvbuff_t *,
602 gint, int, const char *);
603 static void rtps_util_decode_flags(proto_tree *, tvbuff_t *,
604 gint, guint8, const struct Flag_definition *);
605 static gint rtps_util_add_seq_ulong(proto_tree *, tvbuff_t *,
606 gint, int, int, int, int, char *);
610 /* The parameter dissector */
611 static gint dissect_parameter_sequence(proto_tree *, tvbuff_t *,
612 gint, int, int, const char *);
614 /* Sub-message dissector functions */
615 static void dissect_DATA(tvbuff_t *tvb,gint offset,guint8 flags,
616 gboolean little_endian,int next_submsg_offset,
617 proto_tree *rtps_submessage_tree,
618 const char **sm_extra);
620 static void dissect_NOKEY_DATA(tvbuff_t *tvb,gint offset,guint8 flags,
621 gboolean little_endian,int next_submsg_offset,
622 proto_tree *rtps_submessage_tree);
624 static void dissect_ACKNACK(tvbuff_t *tvb,gint offset,guint8 flags,
625 gboolean little_endian,int next_submsg_offset,
626 proto_tree *rtps_submessage_tree);
628 static void dissect_HEARTBEAT(tvbuff_t *tvb,gint offset,guint8 flags,
629 gboolean little_endian,int next_submsg_offset,
630 proto_tree *rtps_submessage_tree);
632 static void dissect_GAP(tvbuff_t *tvb,gint offset,guint8 flags,
633 gboolean little_endian,int next_submsg_offset,
634 proto_tree *rtps_submessage_tree);
636 static void dissect_INFO_TS(tvbuff_t *tvb,gint offset,guint8 flags,
637 gboolean little_endian,int next_submsg_offset,
638 proto_tree *rtps_submessage_tree);
640 static void dissect_INFO_SRC(tvbuff_t *tvb,gint offset,guint8 flags,
641 gboolean little_endian,int next_submsg_offset,
642 proto_tree *rtps_submessage_tree);
644 static void dissect_INFO_REPLY_IP4(tvbuff_t *tvb,gint offset,guint8 flags,
645 gboolean little_endian,int next_submsg_offset,
646 proto_tree *rtps_submessage_tree);
648 static void dissect_INFO_DST(tvbuff_t *tvb,gint offset,guint8 flags,
649 gboolean little_endian,int next_submsg_offset,
650 proto_tree *rtps_submessage_tree);
652 static void dissect_INFO_REPLY(tvbuff_t *tvb,gint offset,guint8 flags,
653 gboolean little_endian,int next_submsg_offset,
654 proto_tree *rtps_submessage_tree);
656 /* The main packet dissector */
657 static gboolean dissect_rtps(tvbuff_t *, packet_info *, proto_tree *);
660 /***************************************************************************/
663 #define NEXT_guint16(tvb, offset, le) \
664 (le ? tvb_get_letohs(tvb, offset) : tvb_get_ntohs(tvb, offset))
666 #define NEXT_guint32(tvb, offset, le) \
667 (le ? tvb_get_letohl(tvb, offset) : tvb_get_ntohl(tvb, offset))
670 /* *********************************************************************** */
671 /* Adds a new record to the SMCounterRecord archive
672 * It always inserts to the end of the list. Insert is not performed if
673 * the last element is like the current one.
675 * last = ptr to the last element or NULL if the list is empty
678 * ptr to the last element of the list or NULL if out of memory occurred.
680 static struct SMCounterRecord * sm_counter_add(
681 struct SMCounterRecord *last,
683 const char * const extra) { /* Can be NULL */
685 if ((last == NULL) || (last->id != submessage)) {
686 struct SMCounterRecord *ptr;
689 ptr = (struct SMCounterRecord *)g_malloc(sizeof(struct SMCounterRecord));
693 ptr->id = submessage;
705 struct SMCounterRecord *ptr;
706 ptr = (struct SMCounterRecord *)g_malloc(sizeof(struct SMCounterRecord));
710 ptr->id = submessage;
720 /* Free the entire list */
721 static void sm_counter_free(struct SMCounterRecord *head) {
722 struct SMCounterRecord *ptr;
723 while (head != NULL) {
732 /* *********************************************************************** */
733 /* Format the given address (16 octects) as an IPv6 address
735 static void rtps_util_format_ipv6(guint8 *addr,
739 guint8 temp[5]; /* Contains a 4-digit hex value */
742 for (i = 0; i < 16; i+=2) {
743 /* Unfortunately %x is the same thing as %02x all the time... sigh */
744 g_snprintf(temp, 5, "%02x%02x", addr[i], addr[i+1]);
745 if (temp[0] == '0') {
746 if (temp[1] == '0') {
747 if (temp[2] == '0') {
748 g_strlcat(buffer, &temp[3], buffer_size);
750 g_strlcat(buffer, &temp[2], buffer_size);
753 g_strlcat(buffer, &temp[1], buffer_size);
756 g_strlcat(buffer, temp, buffer_size);
759 g_strlcat(buffer, ":", buffer_size);
765 /* *********************************************************************** */
766 static void rtps_util_add_protocol_version(proto_tree *tree, /* Can NOT be NULL */
770 proto_tree * version_tree;
774 major = tvb_get_guint8(tvb, offset);
775 minor = tvb_get_guint8(tvb, offset+1);
777 ti = proto_tree_add_none_format(tree,
778 hf_rtps_protocol_version,
782 "Protocol version: %d.%d",
783 tvb_get_guint8(tvb, offset),
784 tvb_get_guint8(tvb, offset+1));
785 version_tree = proto_item_add_subtree(ti,
786 ett_rtps_proto_version);
787 proto_tree_add_item(version_tree,
788 hf_rtps_protocol_version_major,
793 proto_tree_add_item(version_tree,
794 hf_rtps_protocol_version_minor,
803 /* ------------------------------------------------------------------------- */
804 /* Interpret the next bytes as vendor ID. If proto_tree and field ID is
805 * provided, it can also set.
807 static void rtps_util_add_vendor_id(proto_tree *tree, /* Can be NULL */
810 guint8 * buffer, /* Can be NULL */
811 gint buffer_size) { /* Can be 0 */
813 guint32 vendor_id = 0;
814 guint8 vendor_name[MAX_VENDOR_ID_SIZE];
816 major = tvb_get_guint8(tvb, offset);
817 minor = tvb_get_guint8(tvb, offset+1);
818 vendor_id = (major<<8) | minor;
820 case RTPS_VENDOR_UNKNOWN:
821 g_strlcpy(vendor_name, RTPS_VENDOR_UNKNOWN_STRING, MAX_VENDOR_ID_SIZE);
824 case RTPS_VENDOR_RTI:
825 g_strlcpy(vendor_name, RTPS_VENDOR_RTI_STRING, MAX_VENDOR_ID_SIZE);
829 g_snprintf(vendor_name, MAX_VENDOR_ID_SIZE, "%d.%d", major, minor);
833 proto_tree_add_uint_format(tree,
842 if (buffer != NULL) {
843 g_strlcpy(buffer, vendor_name, buffer_size);
849 /* ------------------------------------------------------------------------- */
850 /* Insert in the protocol tree the next 8 bytes interpreted as Locator_t
852 * Locator_t is a struct defined as:
854 * long kind; // kind of locator
855 * unsigned long port;
859 static void rtps_util_add_locator_t(proto_tree *tree, /* Can NOT be NULL */
863 const guint8 * label,
864 guint8 * buffer, /* Can be NULL */
865 gint buffer_size) { /* Can be 0 */
868 proto_tree * locator_tree;
872 char temp_buff[MAX_LOCATOR_SIZE];
873 char addr_buff[MAX_IPV6_SIZE];
874 const char *kind_string = NULL;
878 kind = NEXT_guint32(tvb, offset, little_endian);
879 port = NEXT_guint32(tvb, offset+4, little_endian);
880 for (i = 0; i < 16; ++i) {
881 addr[i] = tvb_get_guint8(tvb, offset + 8 + i);
886 case LOCATOR_KIND_UDPV4:
887 kind_string = "LOCATOR_KIND_UDPV4";
888 g_snprintf(addr_buff, MAX_IPV6_SIZE,
894 g_snprintf(temp_buff, MAX_LOCATOR_SIZE, "%s:%d",
899 case LOCATOR_KIND_UDPV6:
900 kind_string = "LOCATOR_KIND_UDPV6";
901 rtps_util_format_ipv6(addr, &addr_buff[0], MAX_IPV6_SIZE);
902 g_snprintf(temp_buff, MAX_LOCATOR_SIZE,
903 "IPv6: { addr=%s, port=%d }",
908 case LOCATOR_KIND_INVALID:
909 kind_string = "LOCATOR_KIND_INVALID";
911 case LOCATOR_KIND_RESERVED:
912 if (!kind_string) /* Need to guard overrides (no break before) */
913 kind_string = "LOCATOR_KIND_RESERVED";
916 if (!kind_string) /* Need to guard overrides (no break before) */
917 kind_string = "(unknown)";
918 g_snprintf(temp_buff, MAX_LOCATOR_SIZE,
919 "{ kind=%02x, port=%d, addr=%02x %02x %02x ... %02x %02x }",
930 ti = proto_tree_add_text(tree,
938 locator_tree = proto_item_add_subtree(ti,
940 proto_tree_add_text(locator_tree,
947 proto_tree_add_text(locator_tree,
953 (port == 0) ? " (PORT_INVALID)" : "");
954 proto_tree_add_text(locator_tree,
961 g_strlcpy(buffer, temp_buff, buffer_size);
965 /* ------------------------------------------------------------------------- */
966 /* Insert in the protocol tree the next bytes interpreted as a list of
968 * - unsigned long numLocators
974 static void rtps_util_add_locator_list(proto_tree *tree,
977 const guint8 * label,
981 proto_tree *locator_tree;
982 guint32 num_locators;
984 num_locators = NEXT_guint32(tvb, offset, little_endian);
985 ti = proto_tree_add_text(tree,
993 if (num_locators > 0) {
997 locator_tree = proto_item_add_subtree(ti,
998 ett_rtps_locator_udp_v4);
1000 for (i = 0; i < num_locators; ++i) {
1001 g_snprintf(temp_buff, 20, "Locator[%d]", i);
1002 rtps_util_add_locator_t(tree,
1004 offset + 4 + (i * 24),
1014 /* ------------------------------------------------------------------------- */
1015 /* Insert in the protocol tree the next 4 bytes interpreted as IPV4Address_t
1017 static void rtps_util_add_ipv4_address_t(proto_tree *tree, /* Can be NULL */
1021 const guint8 * label,
1022 guint8 * buffer, /* Can be NULL */
1023 gint buffer_size) { /* Can be 0 */
1027 address = NEXT_guint32(tvb, offset, little_endian);
1028 if (address == IPADDRESS_INVALID) {
1030 g_strlcpy(buffer, IPADDRESS_INVALID_STRING, buffer_size);
1033 proto_tree_add_text(tree,
1039 IPADDRESS_INVALID_STRING);
1043 g_snprintf(buffer, buffer_size,
1045 (address >> 24) & 0xff,
1046 (address >> 16) & 0xff,
1047 (address >> 8) & 0xff,
1051 proto_tree_add_text(tree,
1057 (address >> 24) & 0xff,
1058 (address >> 16) & 0xff,
1059 (address >> 8) & 0xff,
1067 /* ------------------------------------------------------------------------- */
1068 /* Insert in the protocol tree the next 8 bytes interpreted as LocatorUDPv4
1070 * LocatorUDPv4 is a struct defined as:
1072 * unsigned long address;
1073 * unsigned long port;
1077 static void rtps_util_add_locator_udp_v4(proto_tree *tree, /* Can NOT be NULL */
1080 const guint8 * label,
1081 int little_endian) {
1084 proto_tree * locator_tree;
1086 char portLabel[MAX_PORT_SIZE];
1087 char address[MAX_IPV4_ADDRESS_SIZE];
1089 port = NEXT_guint32(tvb, offset+4, little_endian);
1091 if (port == PORT_INVALID) {
1092 g_snprintf(portLabel, MAX_PORT_SIZE, "%s (0x00000000)", PORT_INVALID_STRING);
1094 g_snprintf(portLabel, MAX_PORT_SIZE, "%u", port);
1097 ti = proto_tree_add_text(tree,
1101 "addr"); /* Add text later */
1102 locator_tree = proto_item_add_subtree(ti, ett_rtps_locator_udp_v4);
1103 rtps_util_add_ipv4_address_t(locator_tree,
1109 MAX_IPV4_ADDRESS_SIZE);
1110 proto_tree_add_text(locator_tree,
1117 proto_item_set_text(ti, "%s: { address=%s, port=%s }",
1124 /* ------------------------------------------------------------------------- */
1125 /* Insert in the protocol tree the next 8 bytes interpreted as GuidPrefix
1126 * If tree is specified, it fills up the protocol tree item:
1127 * - hf_rtps_guid_prefix
1130 * - hf_rtps_app_id_instance_id
1131 * - hf_rtps_app_id_app_kind
1133 * If buffer is specified, it returns in it a string representation of the
1136 static void rtps_util_add_guid_prefix(proto_tree *tree, /* Can be NULL */
1139 int hf_prefix, /* Cannot be 0 if tree != NULL */
1142 int hf_app_id_instance_id,
1143 int hf_app_id_app_kind,
1144 const guint8 * label, /* Can be NULL */
1145 guint8 * buffer, /* Can be NULL */
1149 guint32 instance_id;
1152 guint8 guid_prefix[8];
1153 const guint8 * safe_label;
1156 safe_label = (label == NULL) ? (const guint8 *)"guidPrefix" : label;
1158 /* Read values from TVB */
1159 host_id = tvb_get_ntohl(tvb, offset);
1160 app_id = tvb_get_ntohl(tvb, offset + 4);
1161 for (i = 0; i < 8; ++i) {
1162 guid_prefix[i] = tvb_get_guint8(tvb, offset+i);
1164 instance_id = (app_id >> 8);
1165 app_kind = (app_id & 0xff);
1167 /* Format the string */
1168 temp_buff = (guint8 *)g_malloc(MAX_GUID_PREFIX_SIZE);
1169 g_snprintf(temp_buff, MAX_GUID_PREFIX_SIZE,
1170 "%s=%02x%02x%02x%02x %02x%02x%02x%02x"
1171 " { hostId=%08x, appId=%08x"
1184 val_to_str(app_kind, app_kind_vals, "%02x"),
1188 proto_item * ti, *hidden_item;
1189 proto_tree * guid_tree;
1190 proto_tree * appid_tree;
1192 /* The numeric value (used for searches) */
1193 hidden_item = proto_tree_add_item(tree,
1199 PROTO_ITEM_SET_HIDDEN(hidden_item);
1201 /* The text node (root of the guid prefix sub-tree) */
1202 ti = proto_tree_add_text(tree,
1208 guid_tree = proto_item_add_subtree(ti,
1209 ett_rtps_guid_prefix);
1212 proto_tree_add_item(guid_tree,
1219 /* AppId (root of the app_id sub-tree */
1220 ti = proto_tree_add_item(guid_tree,
1226 appid_tree = proto_item_add_subtree(ti,
1230 proto_tree_add_item(appid_tree,
1231 hf_app_id_instance_id,
1237 proto_tree_add_item(appid_tree,
1245 if (buffer != NULL) {
1246 g_strlcpy(buffer, temp_buff, buffer_size);
1253 /* ------------------------------------------------------------------------- */
1254 /* Insert the entityId from the next 4 bytes. Since there are more than
1255 * one entityId, we need to specify also the IDs of the entityId (and its
1256 * sub-components), as well as the label identifying it.
1257 * Returns true if the entityKind is one of the NDDS built-in entities.
1259 static int rtps_util_add_entity_id(proto_tree *tree,
1263 int hf_item_entity_key,
1264 int hf_item_entity_kind,
1265 int subtree_entity_id,
1267 guint32 * entity_id_out) { /* Can be NULL */
1268 guint32 entity_id = tvb_get_ntohl(tvb, offset);
1269 guint32 entity_key = (entity_id >> 8);
1270 guint8 entity_kind = (entity_id & 0xff);
1271 const char *str_predef = match_strval(entity_id, entity_id_vals);
1273 if (entity_id_out != NULL) {
1274 *entity_id_out = entity_id;
1279 proto_tree * entity_tree;
1282 if (str_predef == NULL) {
1283 /* entityId is not a predefined value, format it */
1284 ti = proto_tree_add_uint_format(tree,
1290 "%s: 0x%08x (%s: 0x%06x)",
1293 val_to_str(entity_kind, entity_kind_vals,
1297 /* entityId is a predefined value */
1298 ti = proto_tree_add_uint_format(tree,
1304 "%s: %s (0x%08x)", label, str_predef, entity_id);
1307 entity_tree = proto_item_add_subtree(ti,
1310 proto_tree_add_item(entity_tree,
1317 proto_tree_add_item(entity_tree,
1318 hf_item_entity_kind,
1326 /* is a built-in entity if the bit M and R (5 and 6) of the entityKind are set */
1327 /* return ((entity_kind & 0xc0) == 0xc0); */
1328 return ( entity_id == ENTITYID_BUILTIN_TOPIC_WRITER ||
1329 entity_id == ENTITYID_BUILTIN_TOPIC_READER ||
1330 entity_id == ENTITYID_BUILTIN_PUBLICATIONS_WRITER ||
1331 entity_id == ENTITYID_BUILTIN_PUBLICATIONS_READER ||
1332 entity_id == ENTITYID_BUILTIN_SUBSCRIPTIONS_WRITER ||
1333 entity_id == ENTITYID_BUILTIN_SUBSCRIPTIONS_READER ||
1334 entity_id == ENTITYID_BUILTIN_SDP_PARTICIPANT_WRITER ||
1335 entity_id == ENTITYID_BUILTIN_SDP_PARTICIPANT_READER );
1338 /* ------------------------------------------------------------------------- */
1339 /* Insert the entityId from the next 4 bytes as a generic one (not connected
1340 * to any protocol field). It simply insert the content as a simple text entry
1341 * and returns in the passed buffer only the value (without the label).
1343 static void rtps_util_add_generic_entity_id(proto_tree *tree,
1347 guint8 * buffer, /* Can be NULL */
1349 guint32 entity_id = tvb_get_ntohl(tvb, offset);
1350 guint32 entity_key = (entity_id >> 8);
1351 guint8 entity_kind = (entity_id & 0xff);
1352 const char *str_predef = match_strval(entity_id, entity_id_vals);
1353 guint8 temp_buffer[MAX_GUID_SIZE];
1355 if (str_predef == NULL) {
1356 /* entityId is not a predefined value, format it */
1357 g_snprintf(temp_buffer, MAX_GUID_SIZE,
1358 "0x%08x (%s: 0x%06x)",
1360 val_to_str(entity_kind, entity_kind_vals,
1361 "unknown kind (%02x)"),
1364 /* entityId is a predefined value */
1365 g_snprintf(temp_buffer, MAX_GUID_SIZE,
1372 proto_tree_add_text(tree,
1381 if (buffer != NULL) {
1382 g_strlcpy(buffer, temp_buffer, buffer_size);
1388 /* ------------------------------------------------------------------------- */
1389 /* Interpret the next 12 octets as a generic GUID and insert it in the protocol
1390 * tree as simple text (no reference fields are set).
1391 * It is mostly used in situation where is not required to perform search for
1392 * this kind of GUID (i.e. like in some DATA parameter lists).
1394 static void rtps_util_add_generic_guid(proto_tree *tree, /* Cannot be NULL */
1395 tvbuff_t * tvb, /* Cannot be NULL */
1397 const char *label, /* Cannot be NULL */
1398 guint8 * buffer, /* Can be NULL */
1404 guint32 instance_id;
1408 guint8 guid_raw[12];
1409 const char * str_entity_kind;
1410 const char * str_app_kind;
1411 guint8 temp_buff[MAX_GUID_SIZE];
1414 /* Read typed data */
1415 host_id = tvb_get_ntohl(tvb, offset);
1416 app_id = tvb_get_ntohl(tvb, offset + 4);
1417 entity_id = tvb_get_ntohl(tvb, offset + 8);
1419 /* Re-Read raw data */
1420 for (i = 0; i < 12; ++i) {
1421 guid_raw[i] = tvb_get_guint8(tvb, offset+i);
1424 /* Split components from typed data */
1425 instance_id = (app_id >> 8);
1426 app_kind = (app_id & 0xff);
1427 entity_key = (entity_id >> 8);
1428 entity_kind = (entity_id & 0xff);
1430 /* Lookup for predefined app kind and entity kind */
1431 str_entity_kind = val_to_str(entity_kind, entity_kind_vals, "%02x");
1432 str_app_kind = val_to_str(app_kind, app_kind_vals, "%02x");
1434 /* Compose output buffer for raw guid */
1435 g_snprintf(temp_buff, MAX_GUID_SIZE,
1436 "%s=%02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x: "
1437 "{ hostId=%08x, appId=%08x (%s: %06x), entityId=%08x (%s: %06x) }",
1439 guid_raw[0], guid_raw[1], guid_raw[2], guid_raw[3],
1440 guid_raw[4], guid_raw[5], guid_raw[6], guid_raw[7],
1441 guid_raw[8], guid_raw[9], guid_raw[10], guid_raw[11],
1443 app_id, str_app_kind, instance_id,
1444 entity_id, str_entity_kind, entity_key);
1445 proto_tree_add_text(tree, tvb, offset, 12, "%s", temp_buff);
1446 if (buffer != NULL) {
1447 g_strlcpy(buffer, temp_buff, buffer_size);
1452 /* ------------------------------------------------------------------------- */
1453 /* Insert in the protocol tree the next 8 bytes interpreted as sequence
1456 static guint64 rtps_util_add_seq_number(proto_tree *tree,
1460 const char *label _U_) {
1461 guint64 hi = (guint64)NEXT_guint32(tvb, offset, little_endian);
1462 guint64 lo = (guint64)NEXT_guint32(tvb, offset+4, little_endian);
1463 guint64 all = (hi << 32) | lo;
1466 proto_tree_add_int64_format(tree,
1467 hf_rtps_sm_seq_number,
1472 "%s: %" G_GINT64_MODIFIER "u", label, all);
1478 /* ------------------------------------------------------------------------- */
1479 /* Insert in the protocol tree the next 8 bytes interpreted as NtpTime
1481 static void rtps_util_add_ntp_time(proto_tree *tree, /* Can be NULL */
1486 guint8 * buffer, /* Can be NULL */
1488 guint8 tempBuffer[MAX_NTP_TIME_SIZE];
1490 gint32 sec = NEXT_guint32(tvb, offset, little_endian);
1491 guint32 frac = NEXT_guint32(tvb, offset+4, little_endian);
1494 if ((sec == 0x7fffffff) && (frac == 0xffffffff)) {
1495 g_strlcpy(tempBuffer, "INFINITE", MAX_NTP_TIME_SIZE);
1496 } else if ((sec == 0) && (frac == 0)) {
1497 g_strlcpy(tempBuffer, "0 sec", MAX_NTP_TIME_SIZE);
1499 absolute = (double)sec + (double)frac / ((double)(0x80000000) * 2.0);
1500 g_snprintf(tempBuffer, MAX_NTP_TIME_SIZE,
1501 "%f sec (%ds + 0x%08x)", absolute, sec, frac);
1505 proto_tree *time_tree;
1507 ti = proto_tree_add_none_format(tree,
1515 time_tree = proto_item_add_subtree(ti, ett_rtps_ntp_time);
1516 proto_tree_add_item(time_tree,
1517 hf_rtps_param_ntpt_sec,
1522 proto_tree_add_item(time_tree,
1523 hf_rtps_param_ntpt_fraction,
1529 if (buffer != NULL) {
1530 g_strlcpy(buffer, tempBuffer, buffer_size);
1534 /* ------------------------------------------------------------------------- */
1535 /* Insert in the protocol tree the next data interpreted as a String
1536 * Returns the new offset (after reading the string)
1538 static gint rtps_util_add_string(proto_tree *tree, /* Can be NULL */
1541 int hf_item, /* Can be -1 (if label!=NULL) */
1543 const guint8 * label, /* Can be NULL (if hf_item!=-1) */
1544 guint8 * buffer, /* Can be NULL */
1545 size_t buffer_size) {
1546 guint8 * retVal = NULL;
1547 guint32 size = NEXT_guint32(tvb, offset, little_endian);
1550 retVal = tvb_get_string(tvb, offset+4, size);
1554 if (hf_item != -1) {
1555 proto_item * hidden_item;
1556 hidden_item = proto_tree_add_string(tree,
1561 (size == 0) ? (guint8 *)"" : retVal);
1562 PROTO_ITEM_SET_HIDDEN(hidden_item);
1564 proto_tree_add_text(tree,
1569 ((label != NULL) ? label : (const guint8 *)"value") ,
1570 (size == 0) ? (guint8 *)"" : retVal);
1572 if (buffer != NULL) {
1576 g_snprintf(buffer, (gulong) buffer_size, "%s", retVal);
1581 /* NDDS align strings at 4-bytes word. So:
1582 * string_length: 4 -> buffer_length = 4;
1583 * string_length: 5 -> buffer_length = 8;
1584 * string_length: 6 -> buffer_length = 8;
1585 * string_length: 7 -> buffer_length = 8;
1586 * string_length: 8 -> buffer_length = 8;
1589 return offset + 4 + ((size + 3) & 0xfffffffc);
1593 /* ------------------------------------------------------------------------- */
1594 /* Insert in the protocol tree the next data interpreted as a signed long.
1596 static void rtps_util_add_long(proto_tree *tree, /* Can be NULL */
1599 int hf_item, /* Can be -1 */
1601 gboolean is_hex, /* Format as 0x... */
1602 gboolean is_signed, /* Signed/Unsigned */
1603 const char *label, /* Can be NULL */
1605 size_t buffer_size) {
1609 g_snprintf(temp_buff, 16,
1610 (is_hex ? "0x%08x" : (is_signed ? "%d" : "%u")),
1611 NEXT_guint32(tvb, offset, little_endian));
1613 if (hf_item != -1) {
1614 proto_tree_add_item(tree,
1620 } else if (label != NULL) {
1621 proto_tree_add_text(tree,
1630 if (buffer != NULL) {
1631 g_strlcpy(buffer, temp_buff, (gulong) buffer_size);
1635 /* ------------------------------------------------------------------------- */
1636 /* Insert in the protocol tree the next data interpreted as a port (unsigned
1639 static void rtps_util_add_port(proto_tree *tree, /* Can be NULL */
1644 guint8 * buffer, /* Can be NULL */
1646 guint8 tempBuffer[MAX_PORT_SIZE];
1647 guint32 value = NEXT_guint32(tvb, offset, little_endian);
1649 if (value == PORT_INVALID) {
1650 g_snprintf(buffer, buffer_size, "%s (0x00000000)", PORT_INVALID_STRING);
1652 g_snprintf(tempBuffer, MAX_PORT_SIZE, "%u", value);
1656 proto_tree_add_text(tree,
1664 if (buffer != NULL) {
1665 g_strlcpy(buffer, tempBuffer, buffer_size);
1670 /* ------------------------------------------------------------------------- */
1671 /* Insert in the protocol tree the next data interpreted as a boolean
1672 * Returns the pointer to a dynamically allocated buffer containing the
1673 * formatted version of the value.
1675 static void rtps_util_add_boolean(proto_tree *tree, /* Can be NULL */
1679 guint8 * buffer, /* Can be NULL */
1680 size_t buffer_size) {
1682 guint8 value = tvb_get_guint8(tvb, offset);
1684 str = value ? "TRUE" : "FALSE";
1687 g_strlcpy(buffer, str, (gulong) buffer_size);
1691 proto_tree_add_text(tree,
1702 /* ------------------------------------------------------------------------- */
1703 /* Insert in the protocol tree the next bytes interpreted as
1704 * DurabilityServiceQosPolicy
1706 static void rtps_util_add_durability_service_qos(proto_tree *tree,
1712 guint8 temp_buffer[MAX_NTP_TIME_SIZE];
1713 gint32 kind = NEXT_guint32(tvb, offset+8, little_endian);
1714 gint32 history_depth = NEXT_guint32(tvb, offset+12, little_endian);
1715 gint32 max_samples = NEXT_guint32(tvb, offset+16, little_endian);
1716 gint32 max_instances = NEXT_guint32(tvb, offset+20, little_endian);
1717 gint32 max_spi = NEXT_guint32(tvb, offset+24, little_endian);
1719 rtps_util_add_ntp_time(NULL,
1727 g_snprintf(buffer, buffer_size,
1728 "{ service_cleanup_delay=%s, history_kind='%s', "
1729 "history_depth=%d, max_samples=%d, max_instances=%d, "
1730 "max_samples_per_instances=%d }",
1732 val_to_str(kind, history_qos_vals, "0x%08x"),
1738 rtps_util_add_ntp_time(tree,
1742 "service_cleanup_delay",
1745 proto_tree_add_text(tree,
1750 val_to_str(kind, history_qos_vals, "0x%08x"));
1751 proto_tree_add_text(tree,
1755 "history_depth: %d",
1757 proto_tree_add_text(tree,
1763 proto_tree_add_text(tree,
1767 "max_instances: %d",
1769 proto_tree_add_text(tree,
1773 "max_samples_per_instances: %d",
1778 /* ------------------------------------------------------------------------- */
1779 /* Insert in the protocol tree the next bytes interpreted as Liveliness
1780 * QoS Policy structure.
1782 static void rtps_util_add_liveliness_qos(proto_tree *tree,
1788 guint8 temp_buffer[MAX_NTP_TIME_SIZE];
1789 guint32 kind = NEXT_guint32(tvb, offset, little_endian);
1791 rtps_util_add_ntp_time(NULL,
1799 g_snprintf(buffer, buffer_size,
1800 "{ kind=%s, lease_duration=%s }",
1801 val_to_str(kind, liveliness_qos_vals, "0x%08x"),
1804 proto_tree_add_text(tree,
1809 val_to_str(kind, liveliness_qos_vals, "0x%08x"));
1810 rtps_util_add_ntp_time(tree,
1819 /* ------------------------------------------------------------------------- */
1820 /* Insert in the protocol tree the next bytes interpreted as enum type.
1822 static void rtps_util_add_kind_qos(proto_tree *tree, /* Can be NULL */
1827 const value_string *vals,
1828 guint8 * buffer, /* Can be NULL */
1829 size_t buffer_size) {
1830 guint32 kind = NEXT_guint32(tvb, offset, little_endian);
1833 g_strlcpy(buffer, val_to_str(kind, vals, "0x%08x"),
1834 (gulong) buffer_size);
1838 proto_tree_add_text(tree,
1849 /* ------------------------------------------------------------------------- */
1850 /* Insert in the protocol tree the next bytes interpreted as Sequence of
1852 * The formatted buffer is: "string1", "string2", "string3", ...
1853 * Returns the new updated offset
1855 static gint rtps_util_add_seq_string(proto_tree *tree, /* Can NOT be NULL */
1861 guint8 * buffer, /* Can NOT be NULL */
1863 guint32 num_strings;
1865 proto_tree *string_tree;
1867 char temp_buff[MAX_LABEL_SIZE];
1868 guint8 overview_buffer[MAX_LABEL_SIZE];
1870 num_strings = NEXT_guint32(tvb, offset, little_endian);
1871 proto_tree_add_text(tree,
1875 "size: %d", num_strings);
1878 /* Create the string node with a fake string, the replace it later */
1879 ti = proto_tree_add_text(tree,
1884 string_tree = proto_item_add_subtree(ti, ett_rtps_seq_string);
1886 overview_buffer[0] = '\0';
1888 for (i = 0; i < num_strings; ++i) {
1889 g_snprintf(temp_buff, MAX_LABEL_SIZE,
1893 offset = rtps_util_add_string(string_tree,
1899 overview_buffer+strlen(overview_buffer),
1900 MAX_LABEL_SIZE-strlen(overview_buffer));
1902 proto_item_set_text(ti,
1906 if (buffer != NULL) {
1907 g_strlcpy(buffer, overview_buffer, buffer_size);
1912 /* ------------------------------------------------------------------------- */
1913 /* Insert in the protocol tree the next bytes interpreted as Sequence of
1915 * The formatted buffer is: val1, val2, val3, ...
1916 * Returns the new updated offset
1918 static gint rtps_util_add_seq_ulong(proto_tree *tree, /* Can NOT be NULL */
1928 proto_tree *string_tree;
1930 char temp_buff[MAX_LABEL_SIZE];
1931 char overview_buff[MAX_PARAM_SIZE];
1933 num_elem = NEXT_guint32(tvb, offset, little_endian);
1936 /* Create the string node with an empty string, the replace it later */
1937 ti = proto_tree_add_text(tree,
1942 string_tree = proto_item_add_subtree(ti, ett_rtps_seq_ulong);
1944 overview_buff[0] = '\0';
1946 for (i = 0; i < num_elem; ++i) {
1947 g_snprintf(temp_buff, MAX_LABEL_SIZE,
1951 rtps_util_add_long( string_tree,
1959 overview_buff+strlen(overview_buff),
1960 MAX_PARAM_SIZE-strlen(overview_buff));
1963 proto_item_set_text(ti,
1972 #define LONG_ALIGN(x) (x = (x+3)&0xfffffffc)
1973 #define SHORT_ALIGN(x) (x = (x+1)&0xfffffffe)
1974 #define MAX_ARRAY_DIMENSION 10
1975 #define KEY_COMMENT (" //@key")
1978 /* ------------------------------------------------------------------------- */
1979 static const char * rtps_util_typecode_id_to_string(guint32 typecode_id) {
1980 switch(typecode_id) {
1981 case RTI_CDR_TK_ENUM: return "enum";
1982 case RTI_CDR_TK_UNION: return "union";
1983 case RTI_CDR_TK_STRUCT: return "struct";
1984 case RTI_CDR_TK_LONG: return "long";
1985 case RTI_CDR_TK_SHORT: return "short";
1986 case RTI_CDR_TK_USHORT: return "unsigned short";
1987 case RTI_CDR_TK_ULONG: return "unsigned long";
1988 case RTI_CDR_TK_FLOAT: return "float";
1989 case RTI_CDR_TK_DOUBLE: return "double";
1990 case RTI_CDR_TK_BOOLEAN:return "boolean";
1991 case RTI_CDR_TK_CHAR: return "char";
1992 case RTI_CDR_TK_OCTET: return "octet";
1993 case RTI_CDR_TK_LONGLONG:return "longlong";
1994 case RTI_CDR_TK_ULONGLONG: return "unsigned long long";
1995 case RTI_CDR_TK_LONGDOUBLE: return "long double";
1996 case RTI_CDR_TK_WCHAR: return "wchar";
1997 case RTI_CDR_TK_WSTRING:return "wstring";
1998 case RTI_CDR_TK_STRING: return "string";
1999 case RTI_CDR_TK_SEQUENCE: return "sequence";
2000 case RTI_CDR_TK_ARRAY: return "array";
2001 case RTI_CDR_TK_ALIAS: return "alias";
2002 case RTI_CDR_TK_VALUE: return "valuetype";
2004 case RTI_CDR_TK_NULL:
2006 return "<unknown type>";
2010 /* ------------------------------------------------------------------------- */
2011 /* Insert in the protocol tree the next bytes interpreted as typecode info
2012 * Returns the number of bytes parsed
2014 static gint rtps_util_add_typecode(proto_tree *tree,
2022 const gint offset_begin,
2024 int seq_max_len, /* -1 = not a sequence field */
2025 guint32 * arr_dimension, /* if !NULL: array of 10 int */
2027 const gint original_offset = offset;
2031 char indent_string[40];
2035 /* Structure of the typecode data:
2036 * Offset | Size | Field | Notes
2037 * ----------|-------|------------------------------|---------------------
2039 * 0 | 4 | RTI_CDR_TK_XXXXX | 4 bytes aligned
2040 * 4 | 2 | length the struct |
2043 /* Calc indent string */
2044 memset(indent_string, ' ', 40);
2045 indent_string[indent_level*2] = '\0';
2049 tk_id = NEXT_guint32(tvb, offset, little_endian);
2053 tk_size = NEXT_guint16(tvb, offset, little_endian);
2056 retVal = tk_size + 6; /* 6 = 4 (typecode ID) + 2 (size) */
2058 /* The first bit of typecode is set to 1, clear it */
2059 tk_id &= 0x7fffffff;
2061 /* HACK: NDDS 4.0 and NDDS 4.1 has different typecode ID list.
2062 * The ID listed in the RTI_CDR_TK_XXXXX are the one from NDDS 4.1
2063 * In order to correctly dissect NDDS 4.0 packets containing typecode
2064 * information, we check if the ID of the element at level zero is a
2065 * struct or union. If not, it means we are dissecting a ndds 4.0 packet
2066 * (and we can decrement the ID to match the correct values).
2068 if (indent_level == 0) {
2069 if (tk_id == RTI_CDR_TK_OCTET) {
2077 g_strlcpy(type_name, rtps_util_typecode_id_to_string(tk_id), 40);
2079 /* Structure of the typecode data:
2081 * <type_code_header> ::=
2083 * <type_code_length>
2085 * <kind> ::= long (0=TK_NULL, 1=TK_SHORT...)
2086 * <type_code_length> ::= unsugned short
2091 /* Structure of the typecode data:
2093 * <union_type_code> ::=
2094 * <type_code_header>
2097 * <discriminator_type_code>
2100 * <union_member> ::= <member_length><name><union_member_detail>
2101 * <member_length> ::= unsigned short
2102 * <name> ::= <string>
2103 * <string> ::= <length>char+<eol>
2104 * <length> ::= unsigned long
2107 * <union_member_detail> ::= <is_pointer>
2111 * <labels_count> ::= unsigned long
2115 case RTI_CDR_TK_UNION: {
2116 guint32 struct_name_len;
2117 gint8 * struct_name;
2118 const char * discriminator_name = "<unknown>"; /* for unions */
2119 char * discriminator_enum_name = NULL; /* for unions with enum discriminator */
2120 guint32 defaultIdx; /* Currently is ignored */
2121 guint32 disc_id; /* Used temporarily to populate 'discriminator_name' */
2122 guint16 disc_size; /* Currently is ignored */
2123 guint32 disc_offset_begin;
2124 guint32 num_members;
2125 guint16 member_length;
2126 guint32 member_name_len;
2127 guint8 *member_name = NULL;
2128 guint8 member_is_pointer;
2129 guint32 next_offset;
2130 guint32 field_offset_begin;
2131 guint32 member_label_count;
2132 gint32 member_label;
2133 guint32 discriminator_enum_name_length;
2136 /* - - - - - - - Union name - - - - - - - */
2140 /* Get structure name length */
2141 struct_name_len = NEXT_guint32(tvb, offset, little_endian);
2143 struct_name = tvb_get_string(tvb, offset, struct_name_len);
2144 offset += struct_name_len;
2146 /* - - - - - - - Default index - - - - - - - */
2148 defaultIdx = NEXT_guint32(tvb, offset, little_endian);
2151 /* - - - - - - - Discriminator type code - - - - - - - */
2152 /* We don't recursively dissect everything, instead we just read the type */
2153 disc_id = NEXT_guint32(tvb, offset, little_endian);
2156 disc_size = NEXT_guint16(tvb, offset, little_endian);
2158 disc_offset_begin = offset;
2159 disc_id &= 0x7fffffff;
2160 discriminator_name = rtps_util_typecode_id_to_string(disc_id);
2161 if (disc_id == RTI_CDR_TK_ENUM) {
2162 /* Enums has also a name that we should print */
2164 discriminator_enum_name_length = NEXT_guint32(tvb, offset, little_endian);
2165 discriminator_enum_name = tvb_get_string(tvb, offset+4, discriminator_enum_name_length);
2167 offset = disc_offset_begin + disc_size;
2169 field_offset_begin = offset;
2170 offset += rtps_util_add_typecode(
2172 tvb, next_offset = offset;
2188 /* Add the entry of the union in the tree */
2189 proto_tree_add_text(tree,
2193 "%sunion %s (%s%s%s) {",
2197 (discriminator_enum_name ? " " : ""),
2198 (discriminator_enum_name ? discriminator_enum_name : ""));
2200 if (seq_max_len != -1) {
2201 /* We're dissecting a sequence of struct, bypass the seq definition */
2202 g_snprintf(type_name, 40, "%s", struct_name);
2203 g_free(struct_name);
2207 g_free(struct_name);
2208 /* - - - - - - - Number of members - - - - - - - */
2210 num_members = NEXT_guint32(tvb, offset, little_endian);
2213 /* - - - - - - - <union_member>+ - - - - - - - */
2214 next_offset = offset;
2216 for (i = 0; i < num_members; ++i) {
2217 /* Safety: this theoretically should be the same already */
2218 field_offset_begin = offset = next_offset;
2220 SHORT_ALIGN(offset);
2222 /* member's length */
2223 member_length = NEXT_guint16(tvb, offset, little_endian);
2225 next_offset = offset + member_length;
2229 member_name_len = NEXT_guint32(tvb, offset, little_endian);
2233 member_name = tvb_get_string(tvb, offset, member_name_len);
2234 offset += member_name_len;
2237 member_is_pointer = tvb_get_guint8(tvb, offset);
2242 member_label_count = NEXT_guint32(tvb, offset, little_endian);
2245 for (j = 0; j < member_label_count; ++j) {
2248 member_label = NEXT_guint32(tvb, offset, little_endian);
2251 /* Add the entry of the union in the tree */
2252 proto_tree_add_text(tree,
2261 offset += rtps_util_add_typecode(
2275 g_free(member_name);
2277 /* Finally prints the name of the struct (if provided) */
2278 g_strlcpy(type_name, "}", 40);
2281 } /* end of case UNION */
2284 case RTI_CDR_TK_ENUM:
2285 case RTI_CDR_TK_STRUCT: {
2286 /* Structure of the typecode data:
2288 * <union_type_code> ::=
2289 * <type_code_header>
2292 * <discriminator_type_code>
2296 * <struct_type_code> ::=
2297 * <type_code_header>
2302 * <name> ::= <string>
2303 * <string> ::= <length>char+<eol>
2304 * <length> ::= unsigned long
2306 * <member_count> ::= unsigned long
2310 * - A2: 2: member length
2311 * - A4: 4: member name length
2314 * - A2 2: bitfield bits (-1=none)
2316 * - A4 4: Typecode ID
2322 * - A2: 2: member length
2323 * - A4: 4: member name length
2325 * - A4: 4: ordinal number
2327 * -> ----------------------------------------------------- <-
2328 * -> The alignment pad bytes belong to the FOLLOWING field <-
2329 * -> A4 = 4 bytes alignment, A2 = 2 bytes alignment <-
2330 * -> ----------------------------------------------------- <-
2332 guint32 struct_name_len;
2333 gint8 * struct_name;
2334 guint32 num_members;
2335 guint16 member_length;
2336 guint8 member_is_pointer;
2337 guint16 member_bitfield;
2338 guint8 member_is_key;
2339 guint32 member_name_len;
2340 guint8 *member_name = NULL;
2341 guint32 next_offset;
2342 guint32 field_offset_begin;
2343 guint32 ordinal_number;
2344 const char * typecode_name;
2349 /* Get structure name length */
2350 struct_name_len = NEXT_guint32(tvb, offset, little_endian);
2354 struct_name = tvb_get_string(tvb, offset, struct_name_len);
2355 offset += struct_name_len;
2358 if (tk_id == RTI_CDR_TK_ENUM) {
2359 typecode_name = "enum";
2361 typecode_name = "struct";
2364 if (seq_max_len != -1) {
2365 /* We're dissecting a sequence of struct, bypass the seq definition */
2366 g_snprintf(type_name, 40, "%s", struct_name);
2367 g_free(struct_name);
2371 proto_tree_add_text(tree,
2379 g_free(struct_name);
2384 /* number of members */
2385 num_members = NEXT_guint32(tvb, offset, little_endian);
2388 next_offset = offset;
2389 for (i = 0; i < num_members; ++i) {
2390 /* Safety: this theoretically should be the same already */
2391 field_offset_begin = offset = next_offset;
2393 SHORT_ALIGN(offset);
2395 /* member's length */
2396 member_length = NEXT_guint16(tvb, offset, little_endian);
2398 next_offset = offset + member_length;
2402 member_name_len = NEXT_guint32(tvb, offset, little_endian);
2406 member_name = tvb_get_string(tvb, offset, member_name_len);
2407 offset += member_name_len;
2409 if (tk_id == RTI_CDR_TK_ENUM) {
2410 /* ordinal number */
2412 ordinal_number = NEXT_guint32(tvb, offset, little_endian);
2415 proto_tree_add_text(tree,
2418 (offset-field_offset_begin),
2427 member_is_pointer = tvb_get_guint8(tvb, offset);
2431 SHORT_ALIGN(offset);
2432 member_bitfield = NEXT_guint16(tvb, offset, little_endian);
2433 offset += 2; /* pad will be added by typecode dissector */
2436 member_is_key = tvb_get_guint8(tvb, offset);
2439 offset += rtps_util_add_typecode(
2455 g_free(member_name);
2457 /* Finally prints the name of the struct (if provided) */
2458 g_strlcpy(type_name, "}", 40);
2462 case RTI_CDR_TK_WSTRING:
2463 case RTI_CDR_TK_STRING: {
2464 /* Structure of the typecode data:
2465 * Offset | Size | Field | Notes
2466 * ----------|-------|------------------------------|---------------------
2468 * 8 | 4 | String length | 4-bytes aligned
2470 guint32 string_length;
2473 string_length = NEXT_guint32(tvb, offset, little_endian);
2475 g_snprintf(type_name, 40, "%s<%d>",
2476 (tk_id == RTI_CDR_TK_STRING) ? "string" : "wstring",
2481 case RTI_CDR_TK_SEQUENCE: {
2482 /* Structure of the typecode data:
2484 * - A4: 4: Sequence max length
2485 * - the sequence typecode
2487 guint32 seq_max_len;
2489 seq_max_len = NEXT_guint32(tvb, offset, little_endian);
2492 /* Recursive decode seq typecode */
2493 offset += rtps_util_add_typecode(
2507 /* Differently from the other typecodes, the line has been already printed */
2511 case RTI_CDR_TK_ARRAY: {
2512 /* Structure of the typecode data:
2514 * - A4: 4: number of dimensions
2518 * - the array typecode
2520 guint32 size[MAX_ARRAY_DIMENSION]; /* Max dimensions */
2524 dim_max = NEXT_guint32(tvb, offset, little_endian);
2527 for (i = 0; i < MAX_ARRAY_DIMENSION; ++i) size[i] = 0;
2528 for (i = 0; i < dim_max; ++i) {
2529 size[i] = NEXT_guint32(tvb, offset, little_endian);
2533 /* Recursive decode seq typecode */
2534 offset += rtps_util_add_typecode(
2548 /* Differently from the other typecodes, the line has been already printed */
2552 case RTI_CDR_TK_ALIAS: {
2553 /* Structure of the typecode data:
2555 * - A4: 4: alias name size
2556 * - A4: 4: alias name
2557 * - A4: 4: the alias typecode
2559 guint32 alias_name_length;
2563 alias_name_length = NEXT_guint32(tvb, offset, little_endian);
2565 alias_name = tvb_get_string(tvb, offset, alias_name_length);
2566 offset += alias_name_length;
2567 g_strlcpy(type_name, alias_name, 40);
2575 * - A4: 4: name length
2577 * - A2: type modifier
2578 * - A4: base type code
2579 * - A4: number of members
2580 * Foreach member: (it's just like a struct)
2583 case RTI_CDR_TK_VALUE: {
2584 /* Not fully dissected for now */
2586 guint32 value_name_len;
2590 /* Get structure name length */
2591 value_name_len = NEXT_guint32(tvb, offset, little_endian);
2595 value_name = tvb_get_string(tvb, offset, value_name_len);
2596 offset += value_name_len;
2598 g_snprintf(type_name, 40, "valuetype %s", value_name);
2601 } /* switch(tk_id) */
2603 /* Sequence print */
2604 if (seq_max_len != -1) {
2605 proto_tree_add_text(tree,
2608 (offset-offset_begin),
2609 "%ssequence<%s, %d> %s%s;%s",
2613 is_pointer ? "*" : "",
2615 is_key ? KEY_COMMENT : "");
2620 if (arr_dimension != NULL) {
2621 /* Printing an array */
2622 emem_strbuf_t *dim_str = ep_strbuf_new_label(NULL);
2623 for (i = 0; i < MAX_ARRAY_DIMENSION; ++i) {
2624 if (arr_dimension[i] != 0) {
2625 ep_strbuf_append_printf(dim_str, "[%d]", arr_dimension[i]);
2630 proto_tree_add_text(tree,
2633 (offset-offset_begin),
2639 is_key ? KEY_COMMENT : "");
2643 /* Bitfield print */
2644 if (bitfield != 0xffff && name != NULL && is_pointer == 0) {
2645 proto_tree_add_text(tree,
2648 (offset-offset_begin),
2654 is_key ? KEY_COMMENT : "");
2658 /* Everything else */
2659 proto_tree_add_text(tree,
2662 (offset-offset_begin),
2667 is_pointer ? "*" : "",
2669 is_key ? KEY_COMMENT : "");
2674 /* ------------------------------------------------------------------------- */
2675 /* Insert in the protocol tree the next bytes interpreted as Sequence of
2677 * The formatted buffer is: [ 0x01, 0x02, 0x03, 0x04, ...]
2678 * The maximum number of elements displayed is 10, after that a '...' is
2681 static void rtps_util_add_seq_octets(proto_tree *tree,
2692 gint original_offset = offset;
2693 guint32 original_seq_length;
2695 original_seq_length = seq_length = NEXT_guint32(tvb, offset, little_endian);
2698 if (param_length < 4 + (int)seq_length) {
2700 "RTPS PROTOCOL ERROR: parameter value too small",
2702 proto_tree_add_text(tree,
2710 /* Limit the number of octects displayed to MAX_SEQ_OCTETS_PRINTED */
2711 if (seq_length > MAX_SEQ_OCTETS_PRINTED) {
2712 seq_length = MAX_SEQ_OCTETS_PRINTED;
2714 for (i = 0; i < seq_length; ++i) {
2715 idx += g_snprintf(&buffer[idx],
2716 buffer_size - idx - 1,
2718 tvb_get_guint8(tvb, offset++));
2719 if (idx >= buffer_size) {
2723 if (seq_length != original_seq_length) {
2724 /* seq_length was reduced, add '...' */
2725 g_strlcat(buffer, "...", buffer_size);
2729 proto_tree_add_text(tree,
2733 "sequenceSize: %d octects",
2734 original_seq_length);
2735 proto_tree_add_item(tree,
2739 original_seq_length,
2748 /* ------------------------------------------------------------------------- */
2749 /* Insert in the protocol tree the next bytes interpreted as a Bitmap
2751 * SequenceNumber_t bitmapBase;
2752 * sequence<long, 8> bitmap;
2753 * } SequenceNumberSet;
2755 * Returns the new offset after reading the bitmap.
2757 static int rtps_util_add_bitmap(proto_tree *tree,
2761 const char *label _U_) {
2765 char temp_buff[MAX_BITMAP_SIZE];
2768 proto_tree * bitmap_tree;
2769 const gint original_offset = offset;
2772 /* Bitmap base sequence number */
2773 seq_base = rtps_util_add_seq_number(NULL,
2780 /* Reads the bitmap size */
2781 num_bits = NEXT_guint32(tvb, offset, little_endian);
2785 /* Reads the bits (and format the print buffer) */
2787 for (i = 0; i < num_bits; i += 32) {
2788 data = NEXT_guint32(tvb, offset, little_endian);
2790 for (j = 0; j < 32; ++j) {
2791 datamask = (1 << (31-j));
2792 temp_buff[idx] = ((data & datamask) == datamask) ? '1':'0';
2794 if (idx > num_bits) {
2797 if (idx >= MAX_BITMAP_SIZE-1) {
2802 temp_buff[idx] = '\0';
2804 /* removes all the ending '0' */
2805 for (i = (int) strlen(temp_buff) - 1; (i>0 && temp_buff[i] == '0'); --i) {
2806 temp_buff[i] = '\0';
2809 ti = proto_tree_add_text(tree,
2812 offset-original_offset,
2813 "%s: %" G_GINT64_MODIFIER "u/%d:%s",
2818 bitmap_tree = proto_item_add_subtree(ti, ett_rtps_bitmap);
2819 proto_tree_add_text(bitmap_tree,
2823 "bitmapBase: %" G_GINT64_MODIFIER "u",
2825 proto_tree_add_text(bitmap_tree,
2827 original_offset + 8,
2831 if (temp_buff[0] != '\0') {
2832 proto_tree_add_text(bitmap_tree,
2834 original_offset + 12,
2835 offset - original_offset - 12,
2843 /* ------------------------------------------------------------------------- */
2844 /* Decode the submessage flags
2846 static void rtps_util_decode_flags(proto_tree * tree,
2850 const struct Flag_definition * flag_def) {
2853 proto_tree * flags_tree;
2855 char flags_str[MAX_FLAG_SIZE];
2857 flags_str[0] = '\0';
2858 for (i = 0; i < 8; ++i) {
2859 g_snprintf(flags_str + (2 * i), MAX_FLAG_SIZE - (2 * i), "%c ",
2860 ((flags & (1<<(7-i))) ? flag_def[i].letter : RESERVEDFLAG_CHAR));
2863 ti = proto_tree_add_uint_format(tree,
2869 "Flags: 0x%02x (%s)",
2873 flags_tree = proto_item_add_subtree(ti,
2876 for (i = 0; i < 8; ++i) {
2877 int is_set = (flags & (1 << (7-i)));
2879 for (j = 0; j < 8; ++j) {
2880 flags_str[j] = (i == j) ? (is_set ? '1' : '0') : '.';
2882 flags_str[8] = '\0';
2884 proto_tree_add_text(flags_tree,
2890 flag_def[i].description,
2891 is_set ? "Set" : "Not set");
2901 /* *********************************************************************** */
2902 /* * Parameter Sequence dissector * */
2903 /* *********************************************************************** */
2905 * It returns the new offset representing the point where the parameter
2906 * sequence terminates.
2907 * In case of protocol error, it returns 0 (cannot determine the end of
2908 * the sequence, the caller should be responsible to find the end of the
2909 * section if possible or pass the error back and abort dissecting the
2911 * If no error occurred, the returned value is ALWAYS > than the offset passed.
2913 #define ENSURE_LENGTH(size) \
2914 if (param_length < size) { \
2915 proto_tree_add_text(rtps_parameter_tree, \
2916 tvb, offset, param_length, \
2917 "RTPS PROTOCOL ERROR: parameter value too small"\
2918 " (must be at least %d octects)", size); \
2922 static gint dissect_parameter_sequence(proto_tree *tree,
2926 int octects_to_next_header,
2927 const char * label) {
2929 proto_tree * rtps_parameter_sequence_tree;
2930 proto_tree * rtps_parameter_tree;
2931 guint16 parameter, param_length;
2932 guint8 buffer[MAX_PARAM_SIZE];
2933 gint max_param_section = offset + octects_to_next_header;
2937 ti = proto_tree_add_text(tree,
2942 rtps_parameter_sequence_tree = proto_item_add_subtree(ti,
2943 ett_rtps_parameter_sequence);
2946 /* Loop through all the parameters defined until PID_SENTINEL is found */
2948 if (max_param_section-offset < 4) {
2949 proto_tree_add_text(tree,
2953 "RTPS PROTOCOL ERROR: not enough bytes to read "
2954 " the next parameter");
2958 /* Reads parameter and create the sub tree. At this point we don't know
2959 * the final string that will identify the node or its length. It will
2962 parameter = NEXT_guint16(tvb, offset, little_endian);
2963 ti = proto_tree_add_text(rtps_parameter_sequence_tree,
2968 val_to_str(parameter, parameter_id_vals,
2969 "Unknown (0x%04x)"));
2970 rtps_parameter_tree = proto_item_add_subtree(ti, ett_rtps_parameter);
2971 proto_tree_add_uint_format(rtps_parameter_tree,
2972 hf_rtps_parameter_id,
2977 "parameterId: 0x%04x (%s)",
2979 val_to_str(parameter, parameter_id_vals,
2984 /* parameter length */
2985 param_length = NEXT_guint16(tvb, offset, little_endian);
2986 proto_tree_add_item(rtps_parameter_tree,
2987 hf_rtps_parameter_length,
2994 /* Make sure we have enough bytes for the param value */
2995 if ((max_param_section-offset < param_length) &&
2996 (parameter != PID_SENTINEL)) {
2997 proto_tree_add_text(tree,
3001 "RTPS PROTOCOL ERROR: not enough bytes to read "
3002 " the parameter value");
3006 /* Sets the end of this item (now we know it!) */
3007 proto_item_set_len(ti, param_length+4);
3011 /* 0...2...........7...............15.............23...............31
3012 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3013 * | PID_PARTICIPANT_LEASE_DURATION| 0x0008 |
3014 * +---------------+---------------+---------------+---------------+
3015 * | long NtpTime.seconds |
3016 * +---------------+---------------+---------------+---------------+
3017 * | unsigned long NtpTime.fraction |
3018 * +---------------+---------------+---------------+---------------+
3020 case PID_PARTICIPANT_LEASE_DURATION:
3022 rtps_util_add_ntp_time(rtps_parameter_tree,
3032 /* 0...2...........7...............15.............23...............31
3033 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3034 * | PID_TIME_BASED_FILTER | 0x0008 |
3035 * +---------------+---------------+---------------+---------------+
3036 * | long NtpTime.seconds |
3037 * +---------------+---------------+---------------+---------------+
3038 * | unsigned long NtpTime.fraction |
3039 * +---------------+---------------+---------------+---------------+
3041 case PID_TIME_BASED_FILTER:
3043 rtps_util_add_ntp_time(rtps_parameter_tree,
3047 "minimum_separation",
3052 /* 0...2...........7...............15.............23...............31
3053 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3054 * | PID_TOPIC_NAME | length |
3055 * +---------------+---------------+---------------+---------------+
3056 * | unsigned long String.length |
3057 * +---------------+---------------+---------------+---------------+
3058 * | str[0] | str[1] | str[2] | str[3] |
3059 * +---------------+---------------+---------------+---------------+
3061 * +---------------+---------------+---------------+---------------+
3063 case PID_TOPIC_NAME:
3064 rtps_util_add_string(rtps_parameter_tree,
3067 hf_rtps_param_topic_name,
3069 NULL, /* No label, use hf param */
3075 /* 0...2...........7...............15.............23...............31
3076 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3077 * | PID_OWNERSHIP_STRENGTH | 0x0004 |
3078 * +---------------+---------------+---------------+---------------+
3080 * +---------------+---------------+---------------+---------------+
3082 case PID_OWNERSHIP_STRENGTH:
3084 rtps_util_add_long(rtps_parameter_tree,
3087 hf_rtps_param_strength,
3089 FALSE, /* Is Hex ? */
3090 TRUE, /* Is Signed ? */
3091 NULL, /* No Label, use the protocol item ID */
3096 /* 0...2...........7...............15.............23...............31
3097 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3098 * | PID_TYPE_NAME | length |
3099 * +---------------+---------------+---------------+---------------+
3100 * | unsigned long String.length |
3101 * +---------------+---------------+---------------+---------------+
3102 * | str[0] | str[1] | str[2] | str[3] |
3103 * +---------------+---------------+---------------+---------------+
3105 * +---------------+---------------+---------------+---------------+
3108 rtps_util_add_string(rtps_parameter_tree,
3111 hf_rtps_param_type_name,
3113 NULL, /* No label, use hf param */
3120 /* 0...2...........7...............15.............23...............31
3121 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3122 * | PID_XXXXXXXXXXX | 0x0004 |
3123 * +---------------+---------------+---------------+---------------+
3125 * +---------------+---------------+---------------+---------------+
3127 case PID_METATRAFFIC_MULTICAST_PORT:
3128 case PID_METATRAFFIC_UNICAST_PORT:
3129 case PID_DEFAULT_UNICAST_PORT:
3131 rtps_util_add_port(rtps_parameter_tree,
3142 /* 0...2...........7...............15.............23...............31
3143 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3144 * | PID_DEFAULT_EXPECTS_INLINE_QOS| 0x0004 |
3145 * +---------------+---------------+---------------+---------------+
3146 * | boolean | N O T U S E D |
3147 * +---------------+---------------+---------------+---------------+
3149 case PID_DEFAULT_EXPECTS_INLINE_QOS:
3151 rtps_util_add_boolean(rtps_parameter_tree,
3159 /* 0...2...........7...............15.............23...............31
3160 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3161 * | PID_XXXXXXXXXXX | length |
3162 * +---------------+---------------+---------------+---------------+
3163 * | unsigned long ip_address |
3164 * +---------------+---------------+---------------+---------------+
3166 case PID_METATRAFFIC_MULTICAST_IPADDRESS:
3167 case PID_DEFAULT_UNICAST_IPADDRESS:
3168 case PID_MULTICAST_IPADDRESS:
3169 case PID_METATRAFFIC_UNICAST_IPADDRESS:
3170 rtps_util_add_ipv4_address_t(rtps_parameter_tree,
3181 /* 0...2...........7...............15.............23...............31
3182 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3183 * | PID_PROTOCOL_VERSION | 0x0004 |
3184 * +---------------+---------------+---------------+---------------+
3185 * | uint8 major | uint8 minor | N O T U S E D |
3186 * +---------------+---------------+---------------+---------------+
3188 case PID_PROTOCOL_VERSION: {
3193 major = tvb_get_guint8(tvb, offset);
3194 minor = tvb_get_guint8(tvb, offset+1);
3195 g_snprintf(buffer, MAX_PARAM_SIZE, "%d.%d", major, minor);
3196 proto_tree_add_text(rtps_parameter_tree,
3200 "protocolVersion: %s",
3205 /* 0...2...........7...............15.............23...............31
3206 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3207 * | PID_VENDOR_ID | 0x0004 |
3208 * +---------------+---------------+---------------+---------------+
3209 * | uint8 major | uint8 minor | N O T U S E D |
3210 * +---------------+---------------+---------------+---------------+
3214 rtps_util_add_vendor_id(NULL,
3219 proto_tree_add_text(rtps_parameter_tree,
3229 /* 0...2...........7...............15.............23...............31
3230 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3231 * | PID_RELIABILITY | 0x0004 |
3232 * +---------------+---------------+---------------+---------------+
3233 * | unsigned long kind |
3234 * +---------------+---------------+---------------+---------------+
3236 case PID_RELIABILITY_OFFERED: /* Deprecated */
3237 case PID_RELIABILITY:
3239 rtps_util_add_kind_qos(rtps_parameter_tree,
3244 reliability_qos_vals,
3248 /* Older version of the protocol (and for PID_RELIABILITY_OFFERED)
3249 * this parameter was carrying also a NtpTime called
3250 * 'maxBlockingTime'.
3252 if (octects_to_next_header == 12) {
3253 rtps_util_add_ntp_time(rtps_parameter_tree,
3264 /* 0...2...........7...............15.............23...............31
3265 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3266 * | PID_LIVELINESS | 0x000c |
3267 * +---------------+---------------+---------------+---------------+
3268 * | unsigned long kind |
3269 * +---------------+---------------+---------------+---------------+
3270 * | long NtpTime.seconds |
3271 * +---------------+---------------+---------------+---------------+
3272 * | unsigned long NtpTime.fraction |
3273 * +---------------+---------------+---------------+---------------+
3274 * NDDS 3.1 sends only 'kind' on the wire.
3277 case PID_LIVELINESS_OFFERED: /* Deprecated */
3278 case PID_LIVELINESS:
3280 rtps_util_add_liveliness_qos(rtps_parameter_tree,
3289 /* 0...2...........7...............15.............23...............31
3290 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3291 * | PID_DURABILITY | 0x0004 |
3292 * +---------------+---------------+---------------+---------------+
3293 * | unsigned long kind |
3294 * +---------------+---------------+---------------+---------------+
3296 case PID_DURABILITY:
3298 rtps_util_add_kind_qos(rtps_parameter_tree,
3303 durability_qos_vals,
3308 /* 0...2...........7...............15.............23...............31
3309 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3310 * | PID_DURABILITY_SERVICE | 0x0004 |
3311 * +---------------+---------------+---------------+---------------+
3312 * | long NtpTime.seconds |
3313 * +---------------+---------------+---------------+---------------+
3314 * | unsigned long NtpTime.fraction |
3315 * +---------------+---------------+---------------+---------------+
3316 * | unsigned long kind |
3317 * +---------------+---------------+---------------+---------------+
3318 * | long history_depth |
3319 * +---------------+---------------+---------------+---------------+
3320 * | long max_samples |
3321 * +---------------+---------------+---------------+---------------+
3322 * | long max_instances |
3323 * +---------------+---------------+---------------+---------------+
3324 * | long max_samples_per_instance |
3325 * +---------------+---------------+---------------+---------------+
3327 case PID_DURABILITY_SERVICE:
3329 rtps_util_add_durability_service_qos(rtps_parameter_tree,
3338 /* 0...2...........7...............15.............23...............31
3339 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3340 * | PID_OWNERSHIP | 0x0004 |
3341 * +---------------+---------------+---------------+---------------+
3342 * | unsigned long kind |
3343 * +---------------+---------------+---------------+---------------+
3345 case PID_OWNERSHIP_OFFERED: /* Deprecated */
3348 rtps_util_add_kind_qos(rtps_parameter_tree,
3359 /* 0...2...........7...............15.............23...............31
3360 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3361 * | PID_PRESENTATION | 0x0008 |
3362 * +---------------+---------------+---------------+---------------+
3363 * | unsigned long kind |
3364 * +---------------+---------------+---------------+---------------+
3365 * | boolean | boolean | N O T U S E D |
3366 * +---------------+---------------+---------------+---------------+
3368 case PID_PRESENTATION_OFFERED: /* Deprecated */
3369 case PID_PRESENTATION:
3371 g_strlcpy(buffer, "{ ", MAX_PARAM_SIZE);
3372 rtps_util_add_kind_qos(rtps_parameter_tree,
3377 presentation_qos_vals,
3378 buffer+strlen(buffer),
3379 MAX_PARAM_SIZE-strlen(buffer));
3380 g_strlcat(buffer, ", ", MAX_PARAM_SIZE);
3381 rtps_util_add_boolean(rtps_parameter_tree,
3385 buffer+strlen(buffer),
3386 MAX_PARAM_SIZE-strlen(buffer));
3387 g_strlcat(buffer, ", ", MAX_PARAM_SIZE);
3388 rtps_util_add_boolean(rtps_parameter_tree,
3392 buffer+strlen(buffer),
3393 MAX_PARAM_SIZE-strlen(buffer));
3394 g_strlcat(buffer, " }", MAX_PARAM_SIZE);
3398 /* 0...2...........7...............15.............23...............31
3399 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3400 * | PID_DEADLINE | 0x0008 |
3401 * +---------------+---------------+---------------+---------------+
3402 * | long NtpTime.seconds |
3403 * +---------------+---------------+---------------+---------------+
3404 * | unsigned long NtpTime.fraction |
3405 * +---------------+---------------+---------------+---------------+
3407 case PID_DEADLINE_OFFERED: /* Deprecated */
3410 rtps_util_add_ntp_time(rtps_parameter_tree,
3419 /* 0...2...........7...............15.............23...............31
3420 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3421 * | PID_DESTINATION_ORDER | 0x0004 |
3422 * +---------------+---------------+---------------+---------------+
3423 * | unsigned long kind |
3424 * +---------------+---------------+---------------+---------------+
3426 case PID_DESTINATION_ORDER_OFFERED: /* Deprecated */
3427 case PID_DESTINATION_ORDER:
3429 rtps_util_add_kind_qos(rtps_parameter_tree,
3434 destination_order_qos_vals,
3440 /* 0...2...........7...............15.............23...............31
3441 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3442 * | PID_LATENCY_BUDGET | 0x0008 |
3443 * +---------------+---------------+---------------+---------------+
3444 * | long NtpTime.seconds |
3445 * +---------------+---------------+---------------+---------------+
3446 * | unsigned long NtpTime.fraction |
3447 * +---------------+---------------+---------------+---------------+
3449 case PID_LATENCY_BUDGET_OFFERED:
3450 case PID_LATENCY_BUDGET:
3452 rtps_util_add_ntp_time(rtps_parameter_tree,
3462 /* 0...2...........7...............15.............23...............31
3463 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3464 * | PID_PARTITION | length |
3465 * +---------------+---------------+---------------+---------------+
3466 * | unsigned long sequence_size |
3467 * +---------------+---------------+---------------+---------------+
3468 * | unsigned long string[0].size |
3469 * +---------------+---------------+---------------+---------------+
3470 * | string[0][0] | string[0][1] | string[0][2] | string[0][3] |
3471 * +---------------+---------------+---------------+---------------+
3473 * +---------------+---------------+---------------+---------------+
3474 * The value is a sequence of strings.
3476 case PID_PARTITION_OFFERED: /* Deprecated */
3479 rtps_util_add_seq_string(rtps_parameter_tree,
3489 /* 0...2...........7...............15.............23...............31
3490 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3491 * | PID_LIFESPAN | 0x0008 |
3492 * +---------------+---------------+---------------+---------------+
3493 * | long NtpTime.seconds |
3494 * +---------------+---------------+---------------+---------------+
3495 * | unsigned long NtpTime.fraction |
3496 * +---------------+---------------+---------------+---------------+
3500 rtps_util_add_ntp_time(rtps_parameter_tree,
3510 /* 0...2...........7...............15.............23...............31
3511 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3512 * | PID_USER_DATA | length |
3513 * +---------------+---------------+---------------+---------------+
3514 * | unsigned long sequence_size |
3515 * +---------------+---------------+---------------+---------------+
3516 * | octect[0] | octet[1] | octect[2] | octet[3] |
3517 * +---------------+---------------+---------------+---------------+
3519 * +---------------+---------------+---------------+---------------+
3523 rtps_util_add_seq_octets(rtps_parameter_tree,
3528 hf_rtps_param_user_data,
3534 /* 0...2...........7...............15.............23...............31
3535 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3536 * | PID_GROUP_DATA | length |
3537 * +---------------+---------------+---------------+---------------+
3538 * | unsigned long sequence_size |
3539 * +---------------+---------------+---------------+---------------+
3540 * | octect[0] | octet[1] | octect[2] | octet[3] |
3541 * +---------------+---------------+---------------+---------------+
3543 * +---------------+---------------+---------------+---------------+
3545 case PID_GROUP_DATA:
3547 rtps_util_add_seq_octets(rtps_parameter_tree,
3552 hf_rtps_param_group_data,
3557 /* 0...2...........7...............15.............23...............31
3558 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3559 * | PID_TOPIC_DATA | length |
3560 * +---------------+---------------+---------------+---------------+
3561 * | unsigned long sequence_size |
3562 * +---------------+---------------+---------------+---------------+
3563 * | octect[0] | octet[1] | octect[2] | octet[3] |
3564 * +---------------+---------------+---------------+---------------+
3566 * +---------------+---------------+---------------+---------------+
3568 case PID_TOPIC_DATA:
3570 rtps_util_add_seq_octets(rtps_parameter_tree,
3575 hf_rtps_param_topic_data,
3580 /* 0...2...........7...............15.............23...............31
3581 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3582 * | PID_UNICAST_LOCATOR | 0x0018 |
3583 * +---------------+---------------+---------------+---------------+
3585 * +---------------+---------------+---------------+---------------+
3587 * +---------------+---------------+---------------+---------------+
3588 * | ipv6addr[0] | ipv6addr[1] | ipv6addr[2] | ipv6addr[3] |
3589 * +---------------+---------------+---------------+---------------+
3590 * | ipv6addr[4] | ipv6addr[5] | ipv6addr[6] | ipv6addr[7] |
3591 * +---------------+---------------+---------------+---------------+
3592 * | ipv6addr[8] | ipv6addr[9] | ipv6addr[10] | ipv6addr[11] |
3593 * +---------------+---------------+---------------+---------------+
3594 * | ipv6addr[12] | ipv6addr[13] | ipv6addr[14] | ipv6addr[15] |
3595 * +---------------+---------------+---------------+---------------+
3597 case PID_UNICAST_LOCATOR:
3599 rtps_util_add_locator_t(rtps_parameter_tree,
3609 /* 0...2...........7...............15.............23...............31
3610 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3611 * | PID_MULTICAST_LOCATOR | 0x0018 |
3612 * +---------------+---------------+---------------+---------------+
3614 * +---------------+---------------+---------------+---------------+
3616 * +---------------+---------------+---------------+---------------+
3617 * | ipv6addr[0] | ipv6addr[1] | ipv6addr[2] | ipv6addr[3] |
3618 * +---------------+---------------+---------------+---------------+
3619 * | ipv6addr[4] | ipv6addr[5] | ipv6addr[6] | ipv6addr[7] |
3620 * +---------------+---------------+---------------+---------------+
3621 * | ipv6addr[8] | ipv6addr[9] | ipv6addr[10] | ipv6addr[11] |
3622 * +---------------+---------------+---------------+---------------+
3623 * | ipv6addr[12] | ipv6addr[13] | ipv6addr[14] | ipv6addr[15] |
3624 * +---------------+---------------+---------------+---------------+
3626 case PID_MULTICAST_LOCATOR:
3628 rtps_util_add_locator_t(rtps_parameter_tree,
3638 /* 0...2...........7...............15.............23...............31
3639 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3640 * | PID_DEFAULT_UNICAST_LOCATOR | 0x0018 |
3641 * +---------------+---------------+---------------+---------------+
3643 * +---------------+---------------+---------------+---------------+
3645 * +---------------+---------------+---------------+---------------+
3646 * | ipv6addr[0] | ipv6addr[1] | ipv6addr[2] | ipv6addr[3] |
3647 * +---------------+---------------+---------------+---------------+
3648 * | ipv6addr[4] | ipv6addr[5] | ipv6addr[6] | ipv6addr[7] |
3649 * +---------------+---------------+---------------+---------------+
3650 * | ipv6addr[8] | ipv6addr[9] | ipv6addr[10] | ipv6addr[11] |
3651 * +---------------+---------------+---------------+---------------+
3652 * | ipv6addr[12] | ipv6addr[13] | ipv6addr[14] | ipv6addr[15] |
3653 * +---------------+---------------+---------------+---------------+
3655 case PID_DEFAULT_UNICAST_LOCATOR:
3657 rtps_util_add_locator_t(rtps_parameter_tree,
3667 /* 0...2...........7...............15.............23...............31
3668 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3669 * | PID_METATRAFFIC_UNICAST_LOC...| 0x0018 |
3670 * +---------------+---------------+---------------+---------------+
3672 * +---------------+---------------+---------------+---------------+
3674 * +---------------+---------------+---------------+---------------+
3675 * | ipv6addr[0] | ipv6addr[1] | ipv6addr[2] | ipv6addr[3] |
3676 * +---------------+---------------+---------------+---------------+
3677 * | ipv6addr[4] | ipv6addr[5] | ipv6addr[6] | ipv6addr[7] |
3678 * +---------------+---------------+---------------+---------------+
3679 * | ipv6addr[8] | ipv6addr[9] | ipv6addr[10] | ipv6addr[11] |
3680 * +---------------+---------------+---------------+---------------+
3681 * | ipv6addr[12] | ipv6addr[13] | ipv6addr[14] | ipv6addr[15] |
3682 * +---------------+---------------+---------------+---------------+
3684 case PID_METATRAFFIC_UNICAST_LOCATOR:
3686 rtps_util_add_locator_t(rtps_parameter_tree,
3696 /* 0...2...........7...............15.............23...............31
3697 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3698 * | PID_METATRAFFIC_MULTICAST_L...| 0x0018 |
3699 * +---------------+---------------+---------------+---------------+
3701 * +---------------+---------------+---------------+---------------+
3703 * +---------------+---------------+---------------+---------------+
3704 * | ipv6addr[0] | ipv6addr[1] | ipv6addr[2] | ipv6addr[3] |
3705 * +---------------+---------------+---------------+---------------+
3706 * | ipv6addr[4] | ipv6addr[5] | ipv6addr[6] | ipv6addr[7] |
3707 * +---------------+---------------+---------------+---------------+
3708 * | ipv6addr[8] | ipv6addr[9] | ipv6addr[10] | ipv6addr[11] |
3709 * +---------------+---------------+---------------+---------------+
3710 * | ipv6addr[12] | ipv6addr[13] | ipv6addr[14] | ipv6addr[15] |
3711 * +---------------+---------------+---------------+---------------+
3713 case PID_METATRAFFIC_MULTICAST_LOCATOR:
3715 rtps_util_add_locator_t(rtps_parameter_tree,
3725 /* 0...2...........7...............15.............23...............31
3726 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3727 * | PID_PARTICIPANT_MANUAL_LIVE...| 0x0004 |
3728 * +---------------+---------------+---------------+---------------+
3729 * | long livelinessEpoch |
3730 * +---------------+---------------+---------------+---------------+
3732 case PID_PARTICIPANT_BUILTIN_ENDPOINTS:
3733 case PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT:
3735 rtps_util_add_long(rtps_parameter_tree,
3738 -1, /* No protocol ID, use label below */
3740 TRUE, /* Is Hex ? */
3741 FALSE, /* Is Signed ? */
3747 /* 0...2...........7...............15.............23...............31
3748 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3749 * | PID_HISTORY | 0x0004 |
3750 * +---------------+---------------+---------------+---------------+
3752 * +---------------+---------------+---------------+---------------+
3754 * +---------------+---------------+---------------+---------------+
3758 g_strlcpy(buffer, "{ ", MAX_PARAM_SIZE);
3759 rtps_util_add_kind_qos(rtps_parameter_tree,
3765 buffer+strlen(buffer),
3766 MAX_PARAM_SIZE-strlen(buffer));
3767 g_strlcat(buffer, ", ", MAX_PARAM_SIZE);
3769 rtps_util_add_long(rtps_parameter_tree,
3772 -1, /* No protocol ID, use label below */
3774 FALSE, /* Is Hex ? */
3775 TRUE, /* Is Signed ? */
3777 buffer + strlen(buffer),
3778 MAX_PARAM_SIZE-strlen(buffer));
3779 g_strlcat(buffer, " }", MAX_PARAM_SIZE);
3783 /* 0...2...........7...............15.............23...............31
3784 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3785 * | PID_RESOURCE_LIMIT | 0x0004 |
3786 * +---------------+---------------+---------------+---------------+
3787 * | long max_samples |
3788 * +---------------+---------------+---------------+---------------+
3789 * | long max_instances |
3790 * +---------------+---------------+---------------+---------------+
3791 * | long max_samples_per_instances |
3792 * +---------------+---------------+---------------+---------------+
3794 case PID_RESOURCE_LIMIT:
3796 g_strlcpy(buffer, "{ ", MAX_PARAM_SIZE);
3797 rtps_util_add_long(rtps_parameter_tree,
3800 -1, /* No protocol ID, use label below */
3802 FALSE, /* Is Hex ? */
3803 TRUE, /* Is Signed ? */
3805 buffer + strlen(buffer),
3806 MAX_PARAM_SIZE-strlen(buffer));
3807 g_strlcat(buffer, ", ", MAX_PARAM_SIZE);
3808 rtps_util_add_long(rtps_parameter_tree,
3811 -1, /* No protocol ID, use label below */
3813 FALSE, /* Is Hex ? */
3814 TRUE, /* Is Signed ? */
3816 buffer + strlen(buffer),
3817 MAX_PARAM_SIZE-strlen(buffer));
3818 g_strlcat(buffer, ", ", MAX_PARAM_SIZE);
3820 rtps_util_add_long(rtps_parameter_tree,
3823 -1, /* No protocol ID, use label below */
3825 FALSE, /* Is Hex ? */
3826 TRUE, /* Is Signed ? */
3827 "max_samples_per_instances",
3828 buffer + strlen(buffer),
3829 MAX_PARAM_SIZE-strlen(buffer));
3830 g_strlcat(buffer, " }", MAX_PARAM_SIZE);
3834 /* 0...2...........7...............15.............23...............31
3835 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3836 * | PID_CONTENT_FILTER_PROPERTY | length |
3837 * +---------------+---------------+---------------+---------------+
3838 * | unsigned long String1.length |
3839 * +---------------+---------------+---------------+---------------+
3840 * | str1[0] | str1[1] | str1[2] | str1[3] |
3841 * +---------------+---------------+---------------+---------------+
3843 * +---------------+---------------+---------------+---------------+
3844 * | unsigned long String2.length |
3845 * +---------------+---------------+---------------+---------------+
3846 * | str2[0] | str2[1] | str2[2] | str2[3] |
3847 * +---------------+---------------+---------------+---------------+
3849 * +---------------+---------------+---------------+---------------+
3850 * | unsigned long String3.length |
3851 * +---------------+---------------+---------------+---------------+
3852 * | str3[0] | str3[1] | str3[2] | str3[3] |
3853 * +---------------+---------------+---------------+---------------+
3855 * +---------------+---------------+---------------+---------------+
3856 * | unsigned long String4.length |
3857 * +---------------+---------------+---------------+---------------+
3858 * | str4[0] | str4[1] | str4[2] | str4[3] |
3859 * +---------------+---------------+---------------+---------------+
3861 * +---------------+---------------+---------------+---------------+
3863 * | Filter Parameters |
3865 * +---------------+---------------+---------------+---------------+
3867 * String1: ContentFilterName
3868 * String2: RelatedTopicName
3869 * String3: FilterName
3870 * String4: FilterExpression
3871 * FilterParameters: sequence of Strings
3873 * Note: those strings starts all to a word-aligned (4 bytes) offset
3875 case PID_CONTENT_FILTER_PROPERTY: {
3876 guint32 temp_offset = offset;
3878 temp_offset = rtps_util_add_string(rtps_parameter_tree,
3881 hf_rtps_param_content_filter_name,
3883 NULL, /* No label, use hf param */
3886 temp_offset = rtps_util_add_string(rtps_parameter_tree,
3889 hf_rtps_param_related_topic_name,
3894 temp_offset = rtps_util_add_string(rtps_parameter_tree,
3897 hf_rtps_param_filter_name,
3902 temp_offset = rtps_util_add_string(rtps_parameter_tree,
3910 temp_offset = rtps_util_add_seq_string(rtps_parameter_tree,
3921 /* 0...2...........7...............15.............23...............31
3922 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3923 * | PID_PROPERTY_LIST | length |
3924 * +---------------+---------------+---------------+---------------+
3925 * | unsigned long Seq.Length |
3926 * +---------------+---------------+---------------+---------------+
3930 * +---------------+---------------+---------------+---------------+
3934 * +---------------+---------------+---------------+---------------+
3938 * +---------------+---------------+---------------+---------------+
3946 * struct PROPERTY_LIST {
3947 * Sequence<PROPERTY> PropertyList;
3951 case PID_PROPERTY_LIST:
3954 guint32 prev_offset;
3955 guint32 temp_offset;
3956 guint8 tempName[MAX_PARAM_SIZE];
3957 guint8 tempValue[MAX_PARAM_SIZE];
3958 guint32 seq_size = NEXT_guint32(tvb, offset, little_endian);
3959 g_snprintf(buffer, MAX_PARAM_SIZE, "%d properties", seq_size);
3961 proto_tree_add_text(rtps_parameter_tree,
3965 /* 123456789012345678901234567890|123456789012345678901234567890 */
3966 " Property Name | Property Value");
3968 proto_tree_add_text(rtps_parameter_tree,
3972 /* 123456789012345678901234567890|123456789012345678901234567890 */
3973 "------------------------------|------------------------------");
3975 temp_offset = offset+4;
3976 while(seq_size-- > 0) {
3977 prev_offset = temp_offset;
3978 temp_offset = rtps_util_add_string(NULL,
3986 temp_offset = rtps_util_add_string(NULL,
3994 proto_tree_add_text(rtps_parameter_tree,
3997 temp_offset - prev_offset,
4006 /* 0...2...........7...............15.............23...............31
4007 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4008 * | PID_FILTER_SIGNATURE | length |
4009 * +---------------+---------------+---------------+---------------+
4011 * +---------------+---------------+---------------+---------------+
4014 * struct CONTENT_FILTER_SIGNATURE {
4015 * sequence<long> filterBitmap;
4016 * sequence<FILTER_SIGNATURE, 4> filterSignature;
4020 * struct FILTER_SIGNATURE {
4021 * long filterSignature[4];
4024 case PID_FILTER_SIGNATURE: {
4025 guint32 temp_offset = offset;
4026 guint32 prev_offset;
4031 /* Dissect filter bitmap */
4032 temp_offset = rtps_util_add_seq_ulong(rtps_parameter_tree,
4038 FALSE, /* filterSignature: is_signed */
4041 /* Dissect sequence of FILTER_SIGNATURE */
4042 fs_elem = NEXT_guint32(tvb, temp_offset, little_endian);
4044 while (fs_elem-- > 0) {
4045 prev_offset = temp_offset;
4046 /* Dissect the next FILTER_SIGNATURE object */
4047 fs[0] = NEXT_guint32(tvb, temp_offset, little_endian);
4049 fs[1] = NEXT_guint32(tvb, temp_offset, little_endian);
4051 fs[2] = NEXT_guint32(tvb, temp_offset, little_endian);
4053 fs[3] = NEXT_guint32(tvb, temp_offset, little_endian);
4055 proto_tree_add_text(rtps_parameter_tree,
4058 temp_offset - prev_offset,
4059 "filterSignature: %08x %08x %08x %08x",
4060 fs[0], fs[1], fs[2], fs[3]);
4067 /* 0...2...........7...............15.............23...............31
4068 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4069 * | PID_COHERENT_SET | length |
4070 * +---------------+---------------+---------------+---------------+
4072 * + SequenceNumber seqNumber +
4074 * +---------------+---------------+---------------+---------------+
4076 case PID_COHERENT_SET:
4078 rtps_util_add_seq_number(rtps_parameter_tree,
4085 /* 0...2...........7...............15.............23...............31
4086 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4087 * | PID_TYPECODE | length |
4088 * +---------------+---------------+---------------+---------------+
4090 * + Type code description +
4092 * +---------------+---------------+---------------+---------------+
4095 rtps_util_add_typecode(rtps_parameter_tree,
4099 0, /* indent level */
4105 -1, /* not a seq field */
4106 NULL, /* not an array */
4107 0); /* ndds 4.0 hack: init to false */
4110 /* 0...2...........7...............15.............23...............31
4111 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4112 * | PID_PARTICIPANT_GUID | 0x000c |
4113 * +---------------+---------------+---------------+---------------+
4114 * | guid[0] | guid[1] | guid[2] | guid[3] |
4115 * +---------------+---------------+---------------+---------------+
4116 * | guid[4] | guid[5] | guid[6] | guid[7] |
4117 * +---------------+---------------+---------------+---------------+
4118 * | guid[8] | guid[9] | guid[10] | guid[11] |
4119 * +---------------+---------------+---------------+---------------+
4121 case PID_PARTICIPANT_GUID:
4123 rtps_util_add_generic_guid(rtps_parameter_tree,
4132 /* 0...2...........7...............15.............23...............31
4133 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4134 * | PID_PARTICIPANT_ENTITY_ID | 0x0004 |
4135 * +---------------+---------------+---------------+---------------+
4136 * | entity[0] | entity[1] | entity[2] | entity[3] |
4137 * +---------------+---------------+---------------+---------------+
4139 case PID_PARTICIPANT_ENTITY_ID:
4141 rtps_util_add_generic_entity_id(rtps_parameter_tree,
4144 "Participant entity ID",
4149 /* 0...2...........7...............15.............23...............31
4150 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4151 * | PID_GROUP_GUID | 0x000c |
4152 * +---------------+---------------+---------------+---------------+
4153 * | guid[0] | guid[1] | guid[2] | guid[3] |
4154 * +---------------+---------------+---------------+---------------+
4155 * | guid[4] | guid[5] | guid[6] | guid[7] |
4156 * +---------------+---------------+---------------+---------------+
4157 * | guid[8] | guid[9] | guid[10] | guid[11] |
4158 * +---------------+---------------+---------------+---------------+
4160 case PID_GROUP_GUID:
4162 rtps_util_add_generic_guid(rtps_parameter_tree,
4171 /* 0...2...........7...............15.............23...............31
4172 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4173 * | PID_GROUP_ENTITY_ID | 0x0004 |
4174 * +---------------+---------------+---------------+---------------+
4175 * | entity[0] | entity[1] | entity[2] | entity[3] |
4176 * +---------------+---------------+---------------+---------------+
4178 case PID_GROUP_ENTITY_ID:
4181 rtps_util_add_generic_entity_id(rtps_parameter_tree,
4191 /* ==================================================================
4192 * Here are all the deprecated items.
4195 case PID_PERSISTENCE:
4197 rtps_util_add_ntp_time(rtps_parameter_tree,
4206 case PID_TYPE_CHECKSUM:
4208 rtps_util_add_long(rtps_parameter_tree,
4214 FALSE, /* Is signed ? */
4220 case PID_EXPECTS_ACK:
4222 rtps_util_add_boolean(rtps_parameter_tree,
4230 case PID_MANAGER_KEY: {
4233 guint32 manager_key;
4236 while (param_length >= 4) {
4237 manager_key = NEXT_guint32(tvb, offset, little_endian);
4238 g_snprintf(buffer+strlen(buffer),
4239 MAX_PARAM_SIZE-(gulong) strlen(buffer),
4243 proto_tree_add_text(rtps_parameter_tree,
4247 "Key[%d]: 0x%X", i, manager_key);
4251 param_length -= 4; /* decrement count */
4253 offset += param_length;
4258 case PID_RECV_QUEUE_SIZE:
4259 case PID_SEND_QUEUE_SIZE:
4261 rtps_util_add_long(rtps_parameter_tree,
4267 FALSE, /* Is signed ? */
4274 case PID_VARGAPPS_SEQUENCE_NUMBER_LAST:
4276 rtps_util_add_seq_number(rtps_parameter_tree,
4280 "sequenceNumberLast");
4284 /* PID_SENTINEL should ignore any value of parameter length */
4288 /* This is the default branch when we don't have enough information
4289 * on how to decode the parameter. It can be used also for known
4292 /* 0...2...........7...............15.............23...............31
4293 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4294 * | <pid_id> | 0x0000 |
4295 * +---------------+---------------+---------------+---------------+
4297 case PID_IS_RELIABLE:
4298 case PID_TYPE2_NAME:
4299 case PID_TYPE2_CHECKSUM:
4300 g_strlcpy(buffer, "[DEPRECATED] - Parameter not decoded", MAX_PARAM_SIZE);
4303 case PID_RELIABILITY_ENABLED:
4305 if (param_length > 0) {
4306 proto_tree_add_text(rtps_parameter_tree,
4315 proto_item_append_text(ti, ": %s", buffer);
4318 offset += param_length;
4320 } while(parameter != PID_SENTINEL); /* for all the parameters */
4323 #undef ENSURE_LENGTH
4328 /* *********************************************************************** */
4330 /* *********************************************************************** */
4331 static void dissect_PAD(tvbuff_t *tvb,
4334 gboolean little_endian,
4335 int octects_to_next_header,
4337 /* 0...2...........7...............15.............23...............31
4338 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4339 * | PAD |X|X|X|X|X|X|X|E| octetsToNextHeader |
4340 * +---------------+---------------+---------------+---------------+
4342 rtps_util_decode_flags(tree, tvb, offset + 1, flags, PAD_FLAGS);
4344 if (octects_to_next_header != 0) {
4345 proto_tree_add_uint_format(tree,
4346 hf_rtps_sm_octets_to_next_header,
4350 octects_to_next_header,
4351 "octectsToNextHeader: %u (Error: should be ZERO)",
4352 octects_to_next_header);
4356 proto_tree_add_item(tree,
4357 hf_rtps_sm_octets_to_next_header,
4368 /* *********************************************************************** */
4370 /* *********************************************************************** */
4371 static void dissect_DATA(tvbuff_t *tvb,
4374 gboolean little_endian,
4375 int octects_to_next_header,
4377 const char ** sm_data) { /* May be set to some known values */
4379 * 0...2...........7...............15.............23...............31
4380 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4381 * | DATA |X|X|X|U|H|A|P|E| octetsToNextHeader |
4382 * +---------------+---------------+---------------+---------------+
4383 * | ObjectId readerObjectId |
4384 * +---------------+---------------+---------------+---------------+
4385 * | ObjectId writerObjectId |
4386 * +---------------+---------------+---------------+---------------+
4387 * | HostId hostId (iff H==1) |
4388 * +---------------+---------------+---------------+---------------+
4389 * | AppId appId (iff H==1) |
4390 * +---------------+---------------+---------------+---------------+
4391 * | ObjectId objectId |
4392 * +---------------+---------------+---------------+---------------+
4394 * + SequenceNumber writerSeqNumber +
4396 * +---------------+---------------+---------------+---------------+
4398 * ~ ParameterSequence parameters [only if P==1] ~
4400 * +---------------+---------------+---------------+---------------+
4401 * Note: on RTPS 1.0, flag U is not present
4404 * 0...2...........7...............15.............23...............31
4405 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4406 * | DATA |X|X|U|Q|H|A|D|E| octetsToNextHeader |
4407 * +---------------+---------------+---------------+---------------+
4408 * | EntityId readerEntityId |
4409 * +---------------+---------------+---------------+---------------+
4410 * | EntityId writerEntityId |
4411 * +---------------+---------------+---------------+---------------+
4413 * + KeyHashPrefix keyHashPrefix [only if H==1] +
4415 * +---------------+---------------+---------------+---------------+
4416 * | KeyHashSuffix keyHashSuffix |
4417 * +---------------+---------------+---------------+---------------+
4419 * + SequenceNumber writerSeqNum +
4421 * +---------------+---------------+---------------+---------------+
4423 * ~ ParameterList inlineQos [only if Q==1] ~
4425 * +---------------+---------------+---------------+---------------+
4427 * ~ SerializedData serializedData [only if D==1] ~
4429 * +---------------+---------------+---------------+---------------+
4431 * - inlineQos is NEW
4432 * - serializedData is equivalent to the old 'parameters'
4435 int is_builtin_entity = 0; /* true=entityId.entityKind = built-in */
4436 gint old_offset = offset;
4437 guint32 wid; /* Writer EntityID */
4438 rtps_util_decode_flags(tree, tvb, offset + 1, flags, DATA_FLAGS);
4441 /* Calculates the minimum length for this submessage */
4443 if ((flags & FLAG_DATA_H) != 0) min_len += 8;
4444 if ((flags & FLAG_DATA_Q) != 0) min_len += 4;
4445 if ((flags & FLAG_DATA_D) != 0) min_len += 4;
4447 if (octects_to_next_header < min_len) {
4448 proto_tree_add_uint_format(tree,
4449 hf_rtps_sm_octets_to_next_header,
4453 octects_to_next_header,
4454 "octectsToNextHeader: %u (Error: should be >= %u)",
4455 octects_to_next_header,
4459 proto_tree_add_item(tree,
4460 hf_rtps_sm_octets_to_next_header,
4468 /* readerEntityId */
4469 is_builtin_entity |= rtps_util_add_entity_id(tree,
4472 hf_rtps_sm_rdentity_id,
4473 hf_rtps_sm_rdentity_id_key,
4474 hf_rtps_sm_rdentity_id_kind,
4480 /* writerEntityId */
4481 is_builtin_entity |= rtps_util_add_entity_id(tree,
4484 hf_rtps_sm_wrentity_id,
4485 hf_rtps_sm_wrentity_id_key,
4486 hf_rtps_sm_wrentity_id_kind,
4492 /* Checks for predefined declarations
4494 * writerEntityId value | A flag | Extra
4495 * -------------------------------------------|--------|-------------
4496 * ENTITYID_BUILTIN_SUBSCRIPTIONS_WRITER | 1 | r+
4497 * ENTITYID_BUILTIN_SUBSCRIPTIONS_WRITER | 0 | r-
4498 * ENTITYID_BUILTIN_PUBLICATIONS_WRITER | 1 | w+
4499 * ENTITYID_BUILTIN_PUBLICATIONS_WRITER | 0 | w-
4500 * ENTITYID_BUILTIN_SDP_PARTICIPANT_WRITER | 1 | p+
4501 * ENTITYID_BUILTIN_SDP_PARTICIPANT_WRITER | 0 | p- (*)
4502 * ENTITYID_BUILTIN_TOPIC_WRITER | 1 | t+ (*)
4503 * ENTITYID_BUILTIN_TOPIC_WRITER | 0 | t- (*)
4505 * Note (*): Currently NDDS does not publish those values
4507 if (wid == ENTITYID_BUILTIN_PUBLICATIONS_WRITER && (flags & FLAG_DATA_A) != 0) {
4508 *sm_data = SM_EXTRA_WPLUS;
4509 } else if (wid == ENTITYID_BUILTIN_PUBLICATIONS_WRITER && (flags & FLAG_DATA_A) == 0) {
4510 *sm_data = SM_EXTRA_WMINUS;
4511 } else if (wid == ENTITYID_BUILTIN_SUBSCRIPTIONS_WRITER && (flags & FLAG_DATA_A) != 0) {
4512 *sm_data = SM_EXTRA_RPLUS;
4513 } else if (wid == ENTITYID_BUILTIN_SUBSCRIPTIONS_WRITER && (flags & FLAG_DATA_A) == 0) {
4514 *sm_data = SM_EXTRA_RMINUS;
4515 } else if (wid == ENTITYID_BUILTIN_SDP_PARTICIPANT_WRITER && (flags & FLAG_DATA_A) != 0) {
4516 *sm_data = SM_EXTRA_PPLUS;
4517 } else if (wid == ENTITYID_BUILTIN_SDP_PARTICIPANT_WRITER && (flags & FLAG_DATA_A) == 0) {
4518 *sm_data = SM_EXTRA_PMINUS;
4519 } else if (wid == ENTITYID_BUILTIN_TOPIC_WRITER && (flags & FLAG_DATA_A) != 0) {
4520 *sm_data = SM_EXTRA_TPLUS;
4521 } else if (wid == ENTITYID_BUILTIN_TOPIC_WRITER && (flags & FLAG_DATA_A) == 0) {
4522 *sm_data = SM_EXTRA_TMINUS;
4525 /* If flag H is defined, read the HostId and AppId fields */
4526 if ((flags & FLAG_DATA_H) != 0) {
4527 rtps_util_add_guid_prefix(tree,
4530 hf_rtps_sm_guid_prefix,
4533 hf_rtps_sm_instance_id,
4534 hf_rtps_sm_app_kind,
4541 /* Flag H not set, use hostId, appId from the packet header */
4544 /* Complete the GUID by reading the Object ID */
4545 rtps_util_add_entity_id(tree,
4548 hf_rtps_sm_entity_id,
4549 hf_rtps_sm_entity_id_key,
4550 hf_rtps_sm_entity_id_kind,
4556 /* Sequence number */
4557 rtps_util_add_seq_number(tree,
4565 if ((flags & FLAG_DATA_Q) != 0) {
4566 offset = dissect_parameter_sequence(tree,
4570 octects_to_next_header,
4574 /* SerializedData */
4575 if ((flags & FLAG_DATA_D) != 0) {
4576 if (is_builtin_entity) {
4577 offset = dissect_parameter_sequence(tree,
4581 octects_to_next_header,
4584 proto_tree_add_item(tree,
4588 octects_to_next_header - (offset - old_offset) + 4,
4594 /* *********************************************************************** */
4595 /* * N O K E Y _ D A T A * */
4596 /* *********************************************************************** */
4597 static void dissect_NOKEY_DATA(tvbuff_t *tvb,
4600 gboolean little_endian,
4601 int octects_to_next_header,
4604 * 0...2...........7...............15.............23...............31
4605 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4606 * | ISSUE |X|X|X|X|X|X|P|E| octetsToNextHeader |
4607 * +---------------+---------------+---------------+---------------+
4608 * | ObjectId readerObjectId |
4609 * +---------------+---------------+---------------+---------------+
4610 * | ObjectId writerObjectId |
4611 * +---------------+---------------+---------------+---------------+
4613 * + SequenceNumber writerSeqNumber +
4615 * +---------------+---------------+---------------+---------------+
4617 * ~ ParameterSequence parameters [only if P==1] ~
4619 * +---------------+---------------+---------------+---------------+
4621 * ~ UserData issueData ~
4623 * +---------------+---------------+---------------+---------------+
4626 * 0...2...........7...............15.............23...............31
4627 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4628 * | NOKEY_DATA |X|X|X|X|X|D|Q|E| octetsToNextHeader |
4629 * +---------------+---------------+---------------+---------------+
4630 * | EntityId readerEntityId |
4631 * +---------------+---------------+---------------+---------------+
4632 * | EntityId writerEntityId |
4633 * +---------------+---------------+---------------+---------------+
4635 * + SequenceNumber writerSeqNum +
4637 * +---------------+---------------+---------------+---------------+
4639 * ~ ParameterList inlineQos [only if Q==1] ~
4641 * +---------------+---------------+---------------+---------------+
4643 * ~ SerializedData serializedData [only if D==0] ~
4645 * +---------------+---------------+---------------+---------------+
4647 * - inlineQos is equivalent to the old 'parameters'
4648 * - serializedData is equivalent to the old 'issueData'
4652 gint old_offset = offset;
4653 rtps_util_decode_flags(tree, tvb, offset + 1, flags, NOKEY_DATA_FLAGS);
4656 /* Calculates the minimum length for this submessage */
4658 if ((flags & FLAG_NOKEY_DATA_Q) != 0) min_len += 4;
4660 if (octects_to_next_header < min_len) {
4661 proto_tree_add_uint_format(tree,
4662 hf_rtps_sm_octets_to_next_header,
4666 octects_to_next_header,
4667 "octectsToNextHeader: %u (Error: should be >= %u)",
4668 octects_to_next_header,
4672 proto_tree_add_item(tree,
4673 hf_rtps_sm_octets_to_next_header,
4680 /* readerEntityId */
4681 rtps_util_add_entity_id(tree,
4684 hf_rtps_sm_rdentity_id,
4685 hf_rtps_sm_rdentity_id_key,
4686 hf_rtps_sm_rdentity_id_kind,
4692 /* writerEntityId */
4693 rtps_util_add_entity_id(tree,
4696 hf_rtps_sm_wrentity_id,
4697 hf_rtps_sm_wrentity_id_key,
4698 hf_rtps_sm_wrentity_id_kind,
4704 /* Sequence number */
4705 rtps_util_add_seq_number(tree,
4713 if ((flags & FLAG_NOKEY_DATA_Q) != 0) {
4714 offset = dissect_parameter_sequence(tree,
4718 octects_to_next_header,
4724 if ((flags & FLAG_NOKEY_DATA_D) == 0) {
4725 proto_tree_add_item(tree,
4729 octects_to_next_header - (offset - old_offset) + 4,
4735 /* *********************************************************************** */
4736 /* * A C K N A C K * */
4737 /* *********************************************************************** */
4738 static void dissect_ACKNACK(tvbuff_t *tvb,
4741 gboolean little_endian,
4742 int octects_to_next_header,
4745 * 0...2...........7...............15.............23...............31
4746 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4747 * | ACK |X|X|X|X|X|X|F|E| octetsToNextHeader |
4748 * +---------------+---------------+---------------+---------------+
4749 * | ObjectId readerObjectId |
4750 * +---------------+---------------+---------------+---------------+
4751 * | ObjectId writerObjectId |
4752 * +---------------+---------------+---------------+---------------+
4756 * +---------------+---------------+---------------+---------------+
4758 * +---------------+---------------+---------------+---------------+
4761 * 0...2...........7...............15.............23...............31
4762 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4763 * | ACKNACK |X|X|X|X|X|X|F|E| octetsToNextHeader |
4764 * +---------------+---------------+---------------+---------------+
4765 * | EntityId readerEntityId |
4766 * +---------------+---------------+---------------+---------------+
4767 * | EntityId writerEntityId |
4768 * +---------------+---------------+---------------+---------------+
4770 * + SequenceNumberSet readerSNState +
4772 * +---------------+---------------+---------------+---------------+
4774 * +---------------+---------------+---------------+---------------+
4776 gint original_offset; /* Offset to the readerEntityId */
4778 rtps_util_decode_flags(tree, tvb, offset + 1, flags, ACKNACK_FLAGS);
4780 if (octects_to_next_header < 20) {
4781 proto_tree_add_uint_format(tree,
4782 hf_rtps_sm_octets_to_next_header,
4786 octects_to_next_header,
4787 "octectsToNextHeader: %u (Error: should be >= 20)",
4788 octects_to_next_header);
4791 proto_tree_add_item(tree,
4792 hf_rtps_sm_octets_to_next_header,
4798 original_offset = offset;
4800 /* readerEntityId */
4801 rtps_util_add_entity_id(tree,
4804 hf_rtps_sm_rdentity_id,
4805 hf_rtps_sm_rdentity_id_key,
4806 hf_rtps_sm_rdentity_id_kind,
4812 /* writerEntityId */
4813 rtps_util_add_entity_id(tree,
4816 hf_rtps_sm_wrentity_id,
4817 hf_rtps_sm_wrentity_id_key,
4818 hf_rtps_sm_wrentity_id_kind,
4825 offset = rtps_util_add_bitmap(tree,
4832 /* RTPS 1.0 didn't have count: make sure we don't decode it wrong
4835 if (offset + 4 == original_offset + octects_to_next_header) {
4836 /* Count is present */
4837 rtps_util_add_long(tree,
4842 FALSE, /* Is Hex ? */
4843 TRUE, /* Is Signed ? */
4844 "counter", /* No Label, use the protocol item ID */
4847 } else if (offset < original_offset + octects_to_next_header) {
4848 /* In this case there must be something wrong in the bitmap: there
4849 * are some extra bytes that we don't know how to decode
4851 proto_tree_add_text(tree,
4854 octects_to_next_header - offset,
4855 "Packet malformed: don't know how to decode those "
4857 octects_to_next_header - offset);
4858 } else if (offset > original_offset + octects_to_next_header) {
4859 /* Decoding the bitmap went over the end of this submessage.
4860 * Enter an item in the protocol tree that spans over the entire
4863 proto_tree_add_text(tree,
4866 octects_to_next_header + original_offset,
4867 "Packet malformed: not enough bytes to decode");
4874 /* *********************************************************************** */
4875 /* * H E A R T B E A T * */
4876 /* *********************************************************************** */
4877 static void dissect_HEARTBEAT(tvbuff_t *tvb,
4880 gboolean little_endian,
4881 int octects_to_next_header,
4884 * 0...2...........7...............15.............23...............31
4885 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4886 * | HEARTBEAT |X|X|X|X|X|L|F|E| octetsToNextHeader |
4887 * +---------------+---------------+---------------+---------------+
4888 * | ObjectId readerObjectId |
4889 * +---------------+---------------+---------------+---------------+
4890 * | ObjectId writerObjectId |
4891 * +---------------+---------------+---------------+---------------+
4893 * + SequenceNumber firstAvailableSeqNumber +
4895 * +---------------+---------------+---------------+---------------+
4897 * + SequenceNumber lastSeqNumber +
4899 * +---------------+---------------+---------------+---------------+
4901 * +---------------+---------------+---------------+---------------+
4904 * - on RTPS 1.0, counter is not present
4905 * - on RTPS 1.0, L flag is not present
4908 * 0...2...........7...............15.............23...............31
4909 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4910 * | HEARTBEAT |X|X|X|X|X|X|F|E| octetsToNextHeader |
4911 * +---------------+---------------+---------------+---------------+
4912 * | EntityId readerEntityId |
4913 * +---------------+---------------+---------------+---------------+
4914 * | EntityId writerEntityId |
4915 * +---------------+---------------+---------------+---------------+
4917 * + SequenceNumber firstAvailableSeqNumber +
4919 * +---------------+---------------+---------------+---------------+
4921 * + SequenceNumber lastSeqNumber +
4923 * +---------------+---------------+---------------+---------------+
4925 * +---------------+---------------+---------------+---------------+
4929 rtps_util_decode_flags(tree, tvb, offset + 1, flags, HEARTBEAT_FLAGS);
4932 if (octects_to_next_header < 24) {
4933 proto_tree_add_uint_format(tree,
4934 hf_rtps_sm_octets_to_next_header,
4938 octects_to_next_header,
4939 "octectsToNextHeader: %u (Error: should be >= 24)",
4940 octects_to_next_header);
4943 proto_tree_add_item(tree,
4944 hf_rtps_sm_octets_to_next_header,
4951 /* readerEntityId */
4952 rtps_util_add_entity_id(tree,
4955 hf_rtps_sm_rdentity_id,
4956 hf_rtps_sm_rdentity_id_key,
4957 hf_rtps_sm_rdentity_id_kind,
4963 /* writerEntityId */
4964 rtps_util_add_entity_id(tree,
4967 hf_rtps_sm_wrentity_id,
4968 hf_rtps_sm_wrentity_id_key,
4969 hf_rtps_sm_wrentity_id_kind,
4975 /* First available Sequence Number */
4976 rtps_util_add_seq_number(tree,
4980 "firstAvailableSeqNumber");
4983 /* Last Sequence Number */
4984 rtps_util_add_seq_number(tree,
4991 /* Counter: it was not present in RTPS 1.0 */
4992 if (octects_to_next_header == 0x28) {
4993 counter = NEXT_guint32(tvb, offset, little_endian);
4994 proto_tree_add_text(tree,
5004 /* *********************************************************************** */
5006 /* *********************************************************************** */
5007 static void dissect_GAP(tvbuff_t *tvb,
5010 gboolean little_endian,
5011 int octects_to_next_header,
5014 * 0...2...........7...............15.............23...............31
5015 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5016 * | GAP |X|X|X|X|X|X|X|E| octetsToNextHeader |
5017 * +---------------+---------------+---------------+---------------+
5018 * | ObjectId readerObjectId |
5019 * +---------------+---------------+---------------+---------------+
5020 * | ObjectId writerObjectId |
5021 * +---------------+---------------+---------------+---------------+
5023 * + SequenceNumber firstSeqNumber +
5025 * +---------------+---------------+---------------+---------------+
5029 * +---------------+---------------+---------------+---------------+
5031 * 0...2...........7...............15.............23...............31
5032 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5033 * | GAP |X|X|X|X|X|X|F|E| octetsToNextHeader |
5034 * +---------------+---------------+---------------+---------------+
5035 * | EntityId readerEntityId |
5036 * +---------------+---------------+---------------+---------------+
5037 * | EntityId writerEntityId |
5038 * +---------------+---------------+---------------+---------------+
5040 * + SequenceNumber gapStart +
5042 * +---------------+---------------+---------------+---------------+
5044 * ~ SequenceNumberSet gapList ~
5046 * +---------------+---------------+---------------+---------------+
5049 rtps_util_decode_flags(tree, tvb, offset + 1, flags, GAP_FLAGS);
5051 if (octects_to_next_header < 24) {
5052 proto_tree_add_uint_format(tree,
5053 hf_rtps_sm_octets_to_next_header,
5057 octects_to_next_header,
5058 "octectsToNextHeader: %u (Error: should be >= 24)",
5059 octects_to_next_header);
5062 proto_tree_add_item(tree,
5063 hf_rtps_sm_octets_to_next_header,
5070 /* readerEntityId */
5071 rtps_util_add_entity_id(tree,
5074 hf_rtps_sm_rdentity_id,
5075 hf_rtps_sm_rdentity_id_key,
5076 hf_rtps_sm_rdentity_id_kind,
5082 /* writerEntityId */
5083 rtps_util_add_entity_id(tree,
5086 hf_rtps_sm_wrentity_id,
5087 hf_rtps_sm_wrentity_id_key,
5088 hf_rtps_sm_wrentity_id_kind,
5095 /* First Sequence Number */
5096 rtps_util_add_seq_number(tree,
5104 rtps_util_add_bitmap(tree,
5112 /* *********************************************************************** */
5113 /* * I N F O _ T S * */
5114 /* *********************************************************************** */
5115 static void dissect_INFO_TS(tvbuff_t *tvb,
5118 gboolean little_endian,
5119 int octects_to_next_header,
5122 * 0...2...........7...............15.............23...............31
5123 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5124 * | INFO_TS |X|X|X|X|X|X|I|E| octetsToNextHeader |
5125 * +---------------+---------------+---------------+---------------+
5127 * + NtpTime ntpTimestamp [only if I==0] +
5129 * +---------------+---------------+---------------+---------------+
5132 * 0...2...........7...............15.............23...............31
5133 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5134 * | INFO_TS |X|X|X|X|X|X|T|E| octetsToNextHeader |
5135 * +---------------+---------------+---------------+---------------+
5137 * + Timestamp timestamp [only if T==1] +
5139 * +---------------+---------------+---------------+---------------+
5143 rtps_util_decode_flags(tree, tvb, offset + 1, flags, INFO_TS_FLAGS);
5146 if ((flags & FLAG_INFO_TS_T) == 0) min_len += 8;
5148 if (octects_to_next_header != min_len) {
5149 proto_tree_add_uint_format(tree,
5150 hf_rtps_sm_octets_to_next_header,
5154 octects_to_next_header,
5155 "octectsToNextHeader: %u (Error: should be == %u)",
5156 octects_to_next_header,
5161 proto_tree_add_item(tree,
5162 hf_rtps_sm_octets_to_next_header,
5169 if ((flags & FLAG_INFO_TS_T) == 0) {
5170 rtps_util_add_ntp_time(tree,
5181 /* *********************************************************************** */
5182 /* * I N F O _ S R C * */
5183 /* *********************************************************************** */
5184 static void dissect_INFO_SRC(tvbuff_t *tvb,
5187 gboolean little_endian,
5188 int octects_to_next_header,
5191 * 0...2...........7...............15.............23...............31
5192 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5193 * | INFO_SRC |X|X|X|X|X|X|X|E| octetsToNextHeader |
5194 * +---------------+---------------+---------------+---------------+
5195 * | IPAddress appIpAddress |
5196 * +---------------+---------------+---------------+---------------+
5197 * | ProtocolVersion version | VendorId vendor |
5198 * +---------------+---------------+---------------+---------------+
5200 * +---------------+---------------+---------------+---------------+
5202 * +---------------+---------------+---------------+---------------+
5205 * 0...2...........7...............15.............23...............31
5206 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5207 * | INFO_SRC |X|X|X|X|X|X|X|E| octetsToNextHeader |
5208 * +---------------+---------------+---------------+---------------+
5210 * +---------------+---------------+---------------+---------------+
5211 * | ProtocolVersion version | VendorId vendor |
5212 * +---------------+---------------+---------------+---------------+
5214 * + GuidPrefix guidPrefix +
5216 * +---------------+---------------+---------------+---------------+
5219 rtps_util_decode_flags(tree, tvb, offset + 1, flags, INFO_SRC_FLAGS);
5221 if (octects_to_next_header != 16) {
5222 proto_tree_add_uint_format(tree,
5223 hf_rtps_sm_octets_to_next_header,
5227 octects_to_next_header,
5228 "octectsToNextHeader: %u (Error: should be == 16)",
5229 octects_to_next_header);
5233 proto_tree_add_item(tree,
5234 hf_rtps_sm_octets_to_next_header,
5243 guint32 ip = NEXT_guint32(tvb, offset, little_endian);
5244 proto_tree_add_text(tree,
5248 "unused: 0x%08x (appIpAddress: %d.%d.%d.%d)",
5261 major = tvb_get_guint8(tvb, offset);
5262 minor = tvb_get_guint8(tvb, offset+1);
5264 proto_tree_add_text(tree,
5276 guint8 vendor[MAX_VENDOR_ID_SIZE];
5277 rtps_util_add_vendor_id(NULL,
5281 MAX_VENDOR_ID_SIZE);
5282 proto_tree_add_text(tree,
5292 /* guint8 temp_buffer[MAX_GUID_PREFIX_SIZE]; */
5293 rtps_util_add_guid_prefix(tree,
5296 hf_rtps_sm_guid_prefix,
5299 hf_rtps_sm_instance_id,
5300 hf_rtps_sm_app_kind,
5301 NULL, /* Use default 'guidPrefix' */
5306 MAX_GUID_PREFIX_SIZE);
5307 proto_tree_add_text(tree,
5318 /* *********************************************************************** */
5319 /* * I N F O _ R E P L Y _ I P 4 * */
5320 /* *********************************************************************** */
5321 static void dissect_INFO_REPLY_IP4(tvbuff_t *tvb,
5324 gboolean little_endian,
5325 int octects_to_next_header,
5328 * 0...2...........7...............15.............23...............31
5329 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5330 * | INFO_REPLY |X|X|X|X|X|X|M|E| octetsToNextHeader |
5331 * +---------------+---------------+---------------+---------------+
5332 * | IPAddress unicastReplyIpAddress |
5333 * +---------------+---------------+---------------+---------------+
5334 * | Port unicastReplyPort |
5335 * +---------------+---------------+---------------+---------------+
5336 * | IPAddress multicastReplyIpAddress [ only if M==1 ] |
5337 * +---------------+---------------+---------------+---------------+
5338 * | Port multicastReplyPort [ only if M==1 ] |
5339 * +---------------+---------------+---------------+---------------+
5342 * 0...2...........7...............15.............23...............31
5343 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5344 * |INFO_REPLY_IP4 |X|X|X|X|X|X|M|E| octetsToNextHeader |
5345 * +---------------+---------------+---------------+---------------+
5347 * + LocatorUDPv4 unicastReplyLocator +
5349 * +---------------+---------------+---------------+---------------+
5351 * + LocatorUDPv4 multicastReplyLocator [only if M==1] +
5353 * +---------------+---------------+---------------+---------------+
5357 rtps_util_decode_flags(tree, tvb, offset + 1, flags, INFO_REPLY_IP4_FLAGS);
5360 if ((flags & FLAG_INFO_REPLY_IP4_M) == 1) min_len += 8;
5363 if (octects_to_next_header != min_len) {
5364 proto_tree_add_uint_format(tree,
5365 hf_rtps_sm_octets_to_next_header,
5369 octects_to_next_header,
5370 "octectsToNextHeader: %u (Error: should be == %u)",
5371 octects_to_next_header,
5376 proto_tree_add_item(tree,
5377 hf_rtps_sm_octets_to_next_header,
5385 /* unicastReplyLocator */
5386 rtps_util_add_locator_udp_v4(tree,
5389 "unicastReplyLocator",
5394 /* multicastReplyLocator */
5395 if ((flags & FLAG_INFO_REPLY_IP4_M) == 1) {
5396 rtps_util_add_locator_udp_v4(tree,
5399 "multicastReplyLocator",
5405 /* *********************************************************************** */
5406 /* * I N F O _ D S T * */
5407 /* *********************************************************************** */
5408 static void dissect_INFO_DST(tvbuff_t *tvb,
5411 gboolean little_endian,
5412 int octects_to_next_header,
5415 * 0...2...........7...............15.............23...............31
5416 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5417 * | INFO_DST |X|X|X|X|X|X|X|E| octetsToNextHeader |
5418 * +---------------+---------------+---------------+---------------+
5420 * +---------------+---------------+---------------+---------------+
5422 * +---------------+---------------+---------------+---------------+
5425 * 0...2...........7...............15.............23...............31
5426 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5427 * | INFO_DST |X|X|X|X|X|X|X|E| octetsToNextHeader |
5428 * +---------------+---------------+---------------+---------------+
5430 * + GuidPrefix guidPrefix +
5432 * +---------------+---------------+---------------+---------------+
5435 rtps_util_decode_flags(tree, tvb, offset + 1, flags, INFO_DST_FLAGS);
5437 if (octects_to_next_header != 8) {
5438 proto_tree_add_uint_format(tree,
5439 hf_rtps_sm_octets_to_next_header,
5443 octects_to_next_header,
5444 "octectsToNextHeader: %u (Error: should be == 8)",
5445 octects_to_next_header);
5449 proto_tree_add_item(tree,
5450 hf_rtps_sm_octets_to_next_header,
5458 rtps_util_add_guid_prefix(tree,
5461 hf_rtps_sm_guid_prefix,
5464 hf_rtps_sm_instance_id,
5465 hf_rtps_sm_app_kind,
5474 /* *********************************************************************** */
5475 /* * I N F O _ R E P L Y * */
5476 /* *********************************************************************** */
5477 static void dissect_INFO_REPLY(tvbuff_t *tvb,
5480 gboolean little_endian,
5481 int octects_to_next_header,
5484 * INFO_REPLY is *NOT* the same thing as the old INFO_REPLY.
5487 * 0...2...........7...............15.............23...............31
5488 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5489 * | INFO_REPLY |X|X|X|X|X|X|M|E| octetsToNextHeader |
5490 * +---------------+---------------+---------------+---------------+
5492 * ~ LocatorList unicastReplyLocatorList ~
5494 * +---------------+---------------+---------------+---------------+
5496 * ~ LocatorList multicastReplyLocatorList [only if M==1] ~
5498 * +---------------+---------------+---------------+---------------+
5502 rtps_util_decode_flags(tree, tvb, offset + 1, flags, INFO_REPLY_FLAGS);
5505 if ((flags & FLAG_INFO_REPLY_M) == 1) min_len += 8;
5508 if (octects_to_next_header != min_len) {
5509 proto_tree_add_uint_format(tree,
5510 hf_rtps_sm_octets_to_next_header,
5514 octects_to_next_header,
5515 "octectsToNextHeader: %u (Error: should be == %u)",
5516 octects_to_next_header,
5521 proto_tree_add_item(tree,
5522 hf_rtps_sm_octets_to_next_header,
5530 /* unicastReplyLocatorList */
5531 rtps_util_add_locator_list(tree,
5534 "unicastReplyLocatorList",
5539 /* multicastReplyLocatorList */
5540 if ((flags & FLAG_INFO_REPLY_M) == 1) {
5541 rtps_util_add_locator_list(tree,
5544 "multicastReplyLocatorList",
5554 /***************************************************************************/
5555 /* The main packet dissector function
5557 static gboolean dissect_rtps(tvbuff_t *tvb,
5560 proto_item *ti = NULL;
5561 proto_tree *rtps_tree=NULL;
5563 proto_tree *rtps_submessage_tree;
5564 guint8 submessageId;
5566 gboolean little_endian;
5567 gboolean is_ping = FALSE;
5568 gint next_submsg, octects_to_next_header;
5569 struct SMCounterRecord *smcr_head = NULL;
5570 struct SMCounterRecord *smcr_last = NULL;
5571 const gboolean is_tcp = (pinfo->ptype == PT_TCP);
5572 const char * sm_extra = NULL;
5575 /* In RTPS over TCP the first 4 bytes are the packet length
5576 * as 32-bit unsigned int coded as BIG ENDIAN
5577 guint32 tcp_len = tvb_get_ntohl(tvb, offset);
5582 /* Check 'RTPS' signature:
5583 * A header is invalid if it has less than 16 octets
5585 if (!tvb_bytes_exist(tvb, offset, 16)) return FALSE;
5586 if (tvb_get_guint8(tvb,offset) != 'R') return FALSE;
5587 if (tvb_get_guint8(tvb,offset+1) != 'T') return FALSE;
5588 if (tvb_get_guint8(tvb,offset+2) != 'P') return FALSE;
5589 if (tvb_get_guint8(tvb,offset+3) != 'S') return FALSE;
5590 /* Distinguish between RTPS 1.x and 2.x here */
5591 if (tvb_get_guint8(tvb,offset+4) != 1) return FALSE;
5593 /* --- Make entries in Protocol column ---*/
5594 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
5595 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTPS");
5598 if (check_col(pinfo->cinfo, COL_INFO)) {
5599 col_clear(pinfo->cinfo, COL_INFO);
5605 /* create display subtree for the protocol */
5606 ti = proto_tree_add_item(tree, proto_rtps, tvb, 0, -1, FALSE);
5607 rtps_tree = proto_item_add_subtree(ti, ett_rtps);
5609 /* Protocol Version */
5610 rtps_util_add_protocol_version(rtps_tree, tvb, offset+4);
5613 rtps_util_add_vendor_id(rtps_tree, tvb, offset+6, NULL, 0);
5615 tvb_memcpy(tvb, nddsPing, offset+8, 8);
5616 if (nddsPing[0] == 'N' &&
5617 nddsPing[1] == 'D' &&
5618 nddsPing[2] == 'D' &&
5619 nddsPing[3] == 'S' &&
5620 nddsPing[4] == 'P' &&
5621 nddsPing[5] == 'I' &&
5622 nddsPing[6] == 'N' &&
5623 nddsPing[7] == 'G') {
5628 rtps_util_add_guid_prefix(rtps_tree,
5631 hf_rtps_guid_prefix,
5634 hf_rtps_app_id_instance_id,
5635 hf_rtps_app_id_app_kind,
5642 /* Extract the domain id and participant index */
5645 int participant_idx;
5648 proto_tree *mapping_tree;
5650 domain_id = ((pinfo->destport - PORT_BASE)/10) % 100;
5651 participant_idx = (pinfo->destport - PORT_BASE) / 1000;
5652 nature = (pinfo->destport % 10);
5654 ti = proto_tree_add_text(rtps_tree,
5658 "Default port mapping: domainId=%d, "
5659 "participantIdx=%d, nature=%s",
5662 val_to_str(nature, nature_type_vals, "%02x"));
5664 mapping_tree = proto_item_add_subtree(ti, ett_rtps_default_mapping);
5665 proto_tree_add_uint(mapping_tree,
5671 proto_tree_add_uint(mapping_tree,
5672 hf_rtps_participant_idx,
5677 proto_tree_add_uint(mapping_tree,
5678 hf_rtps_nature_type,
5686 /* offset behind RTPS's Header (need to be set in case tree=NULL)*/
5689 while (tvb_reported_length_remaining(tvb, offset) > 0) {
5691 submessageId = tvb_get_guint8(tvb, offset);
5693 /* Creates the subtree 'Submessage: XXXX' */
5694 if (submessageId & 0x80) {
5695 ti = proto_tree_add_text(rtps_tree,
5700 val_to_str(submessageId, submessage_id_vals,
5701 "Vendor-specific (0x%02x)"));
5703 ti = proto_tree_add_text(rtps_tree,
5708 val_to_str(submessageId, submessage_id_vals,
5709 "Unknown (0x%02x)"));
5711 rtps_submessage_tree = proto_item_add_subtree(ti, ett_rtps_submessage);
5713 /* Decode the submessage ID */
5714 if (submessageId & 0x80) {
5715 proto_tree_add_uint_format(rtps_submessage_tree,
5721 "submessageId: Vendor-specific (0x%02x)",
5724 proto_tree_add_uint(rtps_submessage_tree, hf_rtps_sm_id,
5725 tvb, offset, 1, submessageId);
5728 /* Gets the flags */
5729 flags = tvb_get_guint8(tvb, offset + 1);
5731 /* Gets the E (Little endian) flag */
5732 little_endian = ((flags & FLAG_E) != 0);
5734 /* Octect-to-next-header */
5735 octects_to_next_header = NEXT_guint16(tvb, offset + 2, little_endian);
5736 next_submsg = offset + octects_to_next_header + 4;
5738 /* Set length of this item */
5739 proto_item_set_len(ti, octects_to_next_header + 4);
5741 /* Now decode each single submessage */
5742 /* Note: if tree==NULL, we don't care about the details, so each
5743 * sub-message dissector is not invoked. We still need to go
5744 * through this switch to count the number of each submessage IDs
5745 * The offset passed to the dissectors points to the start of the
5746 * submessage (at the ID byte).
5748 switch (submessageId)
5756 octects_to_next_header,
5757 rtps_submessage_tree);
5767 octects_to_next_header,
5768 rtps_submessage_tree,
5775 dissect_NOKEY_DATA(tvb,
5779 octects_to_next_header,
5780 rtps_submessage_tree);
5786 dissect_ACKNACK(tvb,
5790 octects_to_next_header,
5791 rtps_submessage_tree);
5797 dissect_HEARTBEAT(tvb,
5801 octects_to_next_header,
5802 rtps_submessage_tree);
5812 octects_to_next_header,
5813 rtps_submessage_tree);
5819 dissect_INFO_TS(tvb,
5823 octects_to_next_header,
5824 rtps_submessage_tree);
5830 dissect_INFO_SRC(tvb,
5834 octects_to_next_header,
5835 rtps_submessage_tree);
5839 case INFO_REPLY_IP4:
5841 dissect_INFO_REPLY_IP4(tvb,
5845 octects_to_next_header,
5846 rtps_submessage_tree);
5852 dissect_INFO_DST(tvb,
5856 octects_to_next_header,
5857 rtps_submessage_tree);
5863 dissect_INFO_REPLY(tvb,
5867 octects_to_next_header,
5868 rtps_submessage_tree);
5874 proto_tree_add_uint(rtps_submessage_tree, hf_rtps_sm_flags,
5875 tvb, offset + 1, 1, flags);
5876 proto_tree_add_uint(rtps_submessage_tree,
5877 hf_rtps_sm_octets_to_next_header,
5878 tvb, offset + 2, 2, next_submsg);
5883 /* Record the submessage type in the counter record list */
5884 smcr_last = sm_counter_add(smcr_last, submessageId, sm_extra);
5885 if (smcr_head == NULL) {
5886 smcr_head = smcr_last;
5889 /* next submessage's offset */
5890 offset = next_submsg;
5893 /* Compose the content of the 'summary' column */
5894 if ((pinfo != NULL) && (pinfo->cinfo != NULL) &&
5895 (check_col(pinfo->cinfo, COL_INFO))) {
5896 emem_strbuf_t *info_buf = ep_strbuf_new_label(NULL);
5897 struct SMCounterRecord *smcr_ptr = smcr_head;
5901 ep_strbuf_append(info_buf, "PING");
5903 /* Counts of submessages - for Information Frame */
5904 while (smcr_ptr != NULL) {
5905 if (info_buf->len > 0) {
5906 ep_strbuf_append(info_buf, ", ");
5909 if (smcr_ptr->counter > 1) {
5910 ep_strbuf_append_printf(info_buf, "%s(%d)",
5911 val_to_str(smcr_ptr->id,
5917 ep_strbuf_append_printf(info_buf, "%s%s",
5918 val_to_str(smcr_ptr->id,
5921 smcr_ptr->extra ? smcr_ptr->extra : "");
5922 /* XXX - Ellipsis code removed when we converted to a strbuf. */
5926 smcr_ptr = smcr_ptr->next;
5929 col_add_str(pinfo->cinfo, COL_INFO, info_buf->str);
5931 sm_counter_free(smcr_head);
5933 /* If TCP there's an extra OOB byte at the end of the message */
5934 /* TODO: What to do with it? */
5937 } /* dissect_rtps(...) */
5943 /***************************************************************************
5944 * Register the protocol with Wireshark
5945 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5947 void proto_register_rtps(void) {
5949 /* Definition of the protocol tree items:
5950 * This section declares all the protocol items that are parsed in the
5952 * Structure of each element:
5955 * name, // As appears in the GUI tree
5956 * abbrev, // Referenced by filters (rtps.xxxx[.yyyy])
5957 * type, // FT_BOOLEAN, FT_UINT8, ...
5958 * display, // BASE_HEX | BASE_DEC | BASE_OCT or other meanings
5959 * strings, // String table (for enums) or NULL
5960 * bitmask, // only for bitfields
5961 * blurb, // Complete description of this item
5966 static hf_register_info hf[] = {
5968 /* Protocol Version (composed as major.minor) -------------------------- */
5969 { &hf_rtps_protocol_version, {
5976 "RTPS protocol version number",
5979 { &hf_rtps_protocol_version_major, {
5981 "rtps.version.major",
5986 "RTPS major protocol version number",
5989 { &hf_rtps_protocol_version_minor, {
5991 "rtps.version.minor",
5996 "RTPS minor protocol version number",
6000 /* Domain Participant and Participant Index ---------------------------- */
6001 { &hf_rtps_domain_id, {
6012 { &hf_rtps_participant_idx, {
6014 "rtps.participant_idx",
6019 "Participant index",
6022 { &hf_rtps_nature_type, {
6024 "rtps.traffic_nature",
6027 VALS(nature_type_vals),
6029 "Nature of the traffic (meta/user-traffic uni/multi-cast)",
6033 /* Vendor ID ----------------------------------------------------------- */
6034 { &hf_rtps_vendor_id, {
6041 "Unique identifier of the DDS vendor that generated this packet",
6045 /* Guid Prefix for the Packet ------------------------------------------ */
6046 { &hf_rtps_guid_prefix, {
6053 "GuidPrefix of the RTPS packet",
6057 /* Host ID ------------------------------------------------------------- */
6058 { &hf_rtps_host_id, { /* HIDDEN */
6065 "Sub-component 'hostId' of the GuidPrefix of the RTPS packet",
6069 /* AppID (composed as instanceId, appKind) ----------------------------- */
6070 { &hf_rtps_app_id, {
6077 "Sub-component 'appId' of the GuidPrefix of the RTPS packet",
6080 { &hf_rtps_app_id_instance_id, {
6082 "rtps.appId.instanceId",
6087 "'instanceId' field of the 'AppId' structure",
6090 { &hf_rtps_app_id_app_kind, {
6092 "rtps.appId.appKind",
6095 VALS(app_kind_vals),
6097 "'appKind' field of the 'AppId' structure",
6103 /* Submessage ID ------------------------------------------------------- */
6109 VALS(submessage_id_vals),
6111 "defines the type of submessage",
6115 /* Submessage flags ---------------------------------------------------- */
6116 { &hf_rtps_sm_flags, {
6123 "bitmask representing the flags associated with a submessage",
6127 /* Octects to next header ---------------------------------------------- */
6128 { &hf_rtps_sm_octets_to_next_header, {
6129 "octetsToNextHeader",
6130 "rtps.sm.octetsToNextHeader",
6135 "Size of the submessage payload",
6139 /* GUID as {GuidPrefix, EntityId} ------------------------------------ */
6140 { &hf_rtps_sm_guid_prefix, {
6142 "rtps.sm.guidPrefix",
6147 "a generic guidPrefix that is transmitted inside the submessage "
6148 "(this is NOT the guidPrefix described in the packet header",
6152 { &hf_rtps_sm_host_id, {
6154 "rtps.sm.guidPrefix.hostId",
6159 "The hostId component of the rtps.sm.guidPrefix",
6163 { &hf_rtps_sm_app_id, {
6165 "rtps.sm.guidPrefix.appId",
6170 "AppId component of the rtps.sm.guidPrefix",
6173 { &hf_rtps_sm_instance_id, {
6175 "rtps.sm.guidPrefix.appId.instanceId",
6180 "instanceId component of the AppId of the rtps.sm.guidPrefix",
6183 { &hf_rtps_sm_app_kind, {
6185 "rtps.sm.guidPrefix.appId.appKind",
6190 "appKind component of the AppId of the rtps.sm.guidPrefix",
6195 /* Entity ID (composed as entityKey, entityKind) ----------------------- */
6196 { &hf_rtps_sm_entity_id, {
6201 VALS(entity_id_vals),
6203 "Object entity ID as it appears in a DATA submessage (keyHashSuffix)",
6206 { &hf_rtps_sm_entity_id_key, {
6208 "rtps.sm.entityId.entityKey",
6213 "'entityKey' field of the object entity ID",
6216 { &hf_rtps_sm_entity_id_kind, {
6218 "rtps.sm.entityId.entityKind",
6221 VALS(entity_kind_vals),
6223 "'entityKind' field of the object entity ID",
6227 { &hf_rtps_sm_rdentity_id, {
6229 "rtps.sm.rdEntityId",
6232 VALS(entity_id_vals),
6234 "Reader entity ID as it appears in a submessage",
6237 { &hf_rtps_sm_rdentity_id_key, {
6239 "rtps.sm.rdEntityId.entityKey",
6244 "'entityKey' field of the reader entity ID",
6247 { &hf_rtps_sm_rdentity_id_kind, {
6249 "rtps.sm.rdEntityId.entityKind",
6252 VALS(entity_kind_vals),
6254 "'entityKind' field of the reader entity ID",
6258 { &hf_rtps_sm_wrentity_id, {
6260 "rtps.sm.wrEntityId",
6263 VALS(entity_id_vals),
6265 "Writer entity ID as it appears in a submessage",
6268 { &hf_rtps_sm_wrentity_id_key, {
6270 "rtps.sm.wrEntityId.entityKey",
6275 "'entityKey' field of the writer entity ID",
6278 { &hf_rtps_sm_wrentity_id_kind, {
6280 "rtps.sm.wrEntityId.entityKind",
6283 VALS(entity_kind_vals),
6285 "'entityKind' field of the writer entity ID",
6291 /* Sequence number ----------------------------------------------------- */
6292 { &hf_rtps_sm_seq_number, {
6294 "rtps.sm.seqNumber",
6299 "Writer sequence number",
6303 /* Parameter Id -------------------------------------------------------- */
6304 { &hf_rtps_parameter_id, {
6309 VALS(parameter_id_vals),
6315 /* Parameter Length ---------------------------------------------------- */
6316 { &hf_rtps_parameter_length, {
6318 "rtps.param.length",
6327 /* Parameter / NtpTime ------------------------------------------------- */
6328 { &hf_rtps_param_ntpt, {
6330 "rtps.param.ntpTime",
6335 "Time using the NTP standard format",
6338 { &hf_rtps_param_ntpt_sec, {
6340 "rtps.param.ntpTime.sec",
6345 "The 'second' component of a NTP time",
6348 { &hf_rtps_param_ntpt_fraction, {
6350 "rtps.param.ntpTime.fraction",
6355 "The 'fraction' component of a NTP time",
6360 /* Parameter / Topic --------------------------------------------------- */
6361 { &hf_rtps_param_topic_name, {
6363 "rtps.param.topicName",
6368 "String representing the value value of a PID_TOPIC parameter",
6372 /* Parameter / Strength ------------------------------------------------ */
6373 { &hf_rtps_param_strength, {
6375 "rtps.param.strength",
6380 "Decimal value representing the value of a PID_OWNERSHIP_STRENGTH "
6385 /* Parameter / Type Name ----------------------------------------------- */
6386 { &hf_rtps_param_type_name, {
6388 "rtps.param.typeName",
6393 "String representing the value of a PID_TYPE_NAME parameter",
6397 /* Parameter / User Data ----------------------------------------------- */
6398 { &hf_rtps_param_user_data, {
6400 "rtps.param.userData",
6405 "The user data sent in a PID_USER_DATA parameter",
6409 /* Parameter / Group Data ---------------------------------------------- */
6410 { &hf_rtps_param_group_data, {
6412 "rtps.param.groupData",
6417 "The user data sent in a PID_GROUP_DATA parameter",
6421 /* Parameter / Topic Data ---------------------------------------------- */
6422 { &hf_rtps_param_topic_data, {
6424 "rtps.param.topicData",
6429 "The user data sent in a PID_TOPIC_DATA parameter",
6434 /* Parameter / Content Filter Name ------------------------------------- */
6435 { &hf_rtps_param_content_filter_name, {
6436 "contentFilterName",
6437 "rtps.param.contentFilterName",
6442 "Value of the content filter name as sent in a PID_CONTENT_FILTER_PROPERTY parameter",
6445 { &hf_rtps_param_related_topic_name, {
6447 "rtps.param.relatedTopicName",
6452 "Value of the related topic name as sent in a PID_CONTENT_FILTER_PROPERTY parameter",
6455 { &hf_rtps_param_filter_name, {
6457 "rtps.param.filterName",
6462 "Value of the filter name as sent in a PID_CONTENT_FILTER_PROPERTY parameter",
6467 /* Finally the raw issue data ------------------------------------------ */
6468 { &hf_rtps_issue_data, {
6475 "The user data transferred in a ISSUE submessage",
6480 static gint *ett[] = {
6482 &ett_rtps_default_mapping,
6483 &ett_rtps_proto_version,
6484 &ett_rtps_submessage,
6485 &ett_rtps_parameter_sequence,
6486 &ett_rtps_parameter,
6491 &ett_rtps_guid_prefix,
6493 &ett_rtps_locator_udp_v4,
6495 &ett_rtps_locator_list,
6498 &ett_rtps_seq_string,
6499 &ett_rtps_seq_ulong,
6502 proto_rtps = proto_register_protocol(
6503 "Real-Time Publish-Subscribe Wire Protocol",
6506 proto_register_field_array(proto_rtps, hf, array_length(hf));
6507 proto_register_subtree_array(ett, array_length(ett));
6511 void proto_reg_handoff_rtps(void) {
6512 heur_dissector_add("udp", dissect_rtps, proto_rtps);
6513 heur_dissector_add("tcp", dissect_rtps, proto_rtps);