Enable Lua tcp tap userdata.
[obnox/wireshark/wip.git] / epan / dissectors / packet-rtps.c
1 /* packet-rtps.c
2  * ~~~~~~~~~~~~~
3  *
4  * Routines for Real-Time Publish-Subscribe Protocol (RTPS) dissection
5  *
6  * Copyright 2005, Fabrizio Bertocci <fabrizio@rti.com>
7  * Real-Time Innovations, Inc.
8  * 3975 Freedom Circle
9  * Santa Clara, CA 95054
10  *
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>                
17  *                   
18  * $Id$
19  *
20  * Wireshark - Network traffic analyzer
21  * By Gerald Combs <gerald@wireshark.org>
22  * Copyright 1998 Gerald Combs
23  *
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.
28  *  
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.
33  *  
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.
37  *
38  *                  -------------------------------------
39  *
40  * The following file is part of the RTPS packet dissector for Wireshark.
41  *
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
47  *   
48  *   NDDS and RTPS information: http://www.rti.com/resources.html
49  *
50  */
51
52
53 #ifdef HAVE_CONFIG_H
54 # include "config.h"
55 #endif
56
57 #include  <stdio.h>
58 #include  <stdlib.h>
59 #include  <string.h>
60 #include  <glib.h>
61 #include  <epan/packet.h>
62 #include  <epan/addr_resolv.h>
63
64
65 #include "packet-rtps.h"
66
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)"
72  */
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)
85
86 /* Max octects printed on the parameter root for a sequence of octects */
87 #define MAX_SEQ_OCTETS_PRINTED  (20)
88
89
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-)";
98
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
101  * the packet.
102  * Submessages of the same kind are grouped together in one record.
103  */
104 struct SMCounterRecord {
105   int                      id;          /* PAD, DATA, ... */
106   const char *             extra;       /* (r+, w+)... */
107   struct SMCounterRecord * next;        /* Ptr to next */
108 };
109
110
111
112
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;
120
121 static int hf_rtps_domain_id                    = -1;
122 static int hf_rtps_participant_idx              = -1;
123 static int hf_rtps_nature_type                  = -1;
124
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;
130
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;
149
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;
165
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;
186
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" },
199
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]" },
212   { 0, NULL }
213 };
214
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)" },
227   { 0, NULL }
228 };
229
230
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"},
236   { 0, NULL }
237 };
238
239
240 static const value_string app_kind_vals[] = {
241   { APPKIND_UNKNOWN,                    "APPKIND_UNKNOWN" },
242   { APPKIND_MANAGED_APPLICATION,        "ManagedApplication" },
243   { APPKIND_MANAGER,                    "Manager" },
244   { 0, NULL }
245 };
246
247
248 static const value_string submessage_id_vals[] = {
249   { PAD,                                "PAD" },
250   { DATA,                               "DATA" },
251   { NOKEY_DATA,                         "NOKEY_DATA" },
252   { ACKNACK,                            "ACKNACK" },
253   { HEARTBEAT,                          "HEARTBEAT" },
254   { GAP,                                "GAP" },
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" },
260   { 0, NULL }
261 };
262
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" },
286   { 0,                                  NULL }
287 };
288
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" },
358   { 0, NULL }
359 };
360
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" },
365   { 0, NULL }
366 };
367
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" },
373   { 0, NULL }
374 };
375   
376 static const value_string ownership_qos_vals[] = {
377   { OWNERSHIP_SHARED,                   "SHARED_OWNERSHIP_QOS" },
378   { OWNERSHIP_EXCLUSIVE,                "EXCLUSIVE_OWNERSHIP_QOS" },
379   { 0, NULL }
380 };
381
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" },
386   { 0, NULL }
387 };
388
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" },
392   { 0, NULL }
393 };
394
395 static const value_string reliability_qos_vals[] = {
396   { RELIABILITY_BEST_EFFORT,            "BEST_EFFORT_RELIABILITY_QOS" },
397   { RELIABILITY_RELIABLE,               "RELIABLE_RELIABILITY_QOS" },
398   { 0, NULL }
399 };
400
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" },
404   { 0, NULL }
405 };
406
407
408 /* Flag Decoding defintions ***********************************************/
409 struct Flag_definition {
410   const char letter;
411   const char *description;
412 };
413
414 #define RESERVEDFLAG_CHAR               ('_')
415 #define RESERVEDFLAG_STRING             ("reserved bit")
416
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 */
426 };
427
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 */
437 };
438
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 */
448 };
449
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 */
459 };
460
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 */
470 };
471
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 */
481 };
482
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 */
492 };
493
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 */
503 };
504
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 */
514 };
515
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 */
525 };
526
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 */
536 };
537
538
539 /***************************************************************************/
540
541
542
543
544
545 /***************************************************************************
546  * Function prototypes
547  * ~~~~~~~~~~~~~~~~~~~
548  */
549
550 /* Sm management */
551 static struct SMCounterRecord * sm_counter_add(struct SMCounterRecord *, guint8, const char * const extra);
552 static void                     sm_counter_free(struct SMCounterRecord *);
553
554
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 *,
570                         guint8 *, gint);
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 *,
574                         gint, const char *, 
575                         guint8 *, gint);
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 *,
586                         guint8 *, size_t);
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 *);
607
608
609
610 /* The parameter dissector */
611 static gint dissect_parameter_sequence(proto_tree *, tvbuff_t *,
612                         gint, int, int, const char *);
613
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);
619
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);
623
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);
627
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);
631
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);
635
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);
639
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);
643
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);
647
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);
651
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);
655
656 /* The main packet dissector */
657 static gboolean dissect_rtps(tvbuff_t *, packet_info *, proto_tree *);
658
659
660 /***************************************************************************/
661 /* Inline macros */
662
663 #define NEXT_guint16(tvb, offset, le)    \
664                 (le ? tvb_get_letohs(tvb, offset) : tvb_get_ntohs(tvb, offset))
665
666 #define NEXT_guint32(tvb, offset, le)    \
667                 (le ? tvb_get_letohl(tvb, offset) : tvb_get_ntohl(tvb, offset))
668
669
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.
674  * Parameters:
675  *   last = ptr to the last element or NULL if the list is empty
676  *
677  * Returns:
678  *   ptr to the last element of the list or NULL if out of memory occurred.
679  */
680 static struct SMCounterRecord * sm_counter_add(
681                         struct SMCounterRecord *last,
682                         guint8  submessage, 
683                         const char * const extra) {     /* Can be NULL */
684 #if 0
685   if ((last == NULL) || (last->id != submessage)) {
686     struct SMCounterRecord *ptr;
687
688     /* Add message */
689     ptr = (struct SMCounterRecord *)g_malloc(sizeof(struct SMCounterRecord));
690     if (ptr == NULL) {
691       return NULL;
692     }
693     ptr->id = submessage;
694     ptr->counter = 1;
695     ptr->next = NULL;
696     if (last) {
697       last->next = ptr;
698     }
699     return ptr;
700   }
701
702   last->counter++;
703 #endif
704   
705     struct SMCounterRecord *ptr;
706     ptr = (struct SMCounterRecord *)g_malloc(sizeof(struct SMCounterRecord));
707     if (ptr == NULL) {
708       return NULL;
709     }
710     ptr->id = submessage;
711     ptr->extra = extra;
712     ptr->next = NULL;
713     if (last) {
714       last->next = ptr;
715     }
716     return ptr;
717 }
718
719
720 /* Free the entire list */
721 static void sm_counter_free(struct SMCounterRecord *head) {
722   struct SMCounterRecord *ptr;
723   while (head != NULL) {
724     ptr = head->next;
725     g_free(ptr);
726     head = ptr;
727   }
728 }
729
730
731
732 /* *********************************************************************** */
733 /* Format the given address (16 octects) as an IPv6 address
734  */
735 static void rtps_util_format_ipv6(guint8 *addr, 
736                         guint8 *buffer,
737                         gint    buffer_size) {
738   guint32 i;
739   guint8 temp[5]; /* Contains a 4-digit hex value */
740
741   buffer[0] = '\0';
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);
749         } else {
750           g_strlcat(buffer, &temp[2], buffer_size);
751         }
752       } else {
753         g_strlcat(buffer, &temp[1], buffer_size);
754       }
755     } else {
756       g_strlcat(buffer, temp, buffer_size);
757     }
758     if (i < 14) {
759       g_strlcat(buffer, ":", buffer_size);
760     }
761   }
762 }
763
764
765 /* *********************************************************************** */
766 static void rtps_util_add_protocol_version(proto_tree *tree, /* Can NOT be NULL */
767                         tvbuff_t *  tvb,
768                         gint        offset) {
769   proto_item * ti;
770   proto_tree * version_tree;
771   guint8       major = 0;
772   guint8       minor = 0;
773
774   major = tvb_get_guint8(tvb, offset);
775   minor = tvb_get_guint8(tvb, offset+1);
776
777   ti = proto_tree_add_none_format(tree, 
778                         hf_rtps_protocol_version,
779                         tvb, 
780                         offset, 
781                         2,
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,
789                         tvb,
790                         offset,
791                         1,
792                         FALSE);
793   proto_tree_add_item(version_tree, 
794                         hf_rtps_protocol_version_minor,
795                         tvb,
796                         offset+1,
797                         1,
798                         FALSE);
799
800 }
801
802
803 /* ------------------------------------------------------------------------- */
804 /* Interpret the next bytes as vendor ID. If proto_tree and field ID is
805  * provided, it can also set. 
806  */
807 static void rtps_util_add_vendor_id(proto_tree *tree,   /* Can be NULL */
808                         tvbuff_t * tvb,
809                         gint       offset,
810                         guint8 *   buffer,              /* Can be NULL */
811                         gint       buffer_size) {       /* Can be 0 */
812   guint8 major, minor;
813   guint32 vendor_id = 0;
814   guint8 vendor_name[MAX_VENDOR_ID_SIZE];
815
816   major = tvb_get_guint8(tvb, offset);
817   minor = tvb_get_guint8(tvb, offset+1);
818   vendor_id = (major<<8) | minor;
819   switch(vendor_id) {
820     case RTPS_VENDOR_UNKNOWN:
821       g_strlcpy(vendor_name, RTPS_VENDOR_UNKNOWN_STRING, MAX_VENDOR_ID_SIZE);
822       break;
823
824     case RTPS_VENDOR_RTI:
825       g_strlcpy(vendor_name, RTPS_VENDOR_RTI_STRING, MAX_VENDOR_ID_SIZE);
826       break;
827
828     default:
829       g_snprintf(vendor_name, MAX_VENDOR_ID_SIZE, "%d.%d", major, minor);
830   }
831
832   if (tree != NULL) {
833     proto_tree_add_uint_format(tree, 
834                         hf_rtps_vendor_id,
835                         tvb,
836                         offset,
837                         2,
838                         vendor_id,
839                         "vendor: %s",
840                         vendor_name);
841   }
842   if (buffer != NULL) {
843     g_strlcpy(buffer, vendor_name, buffer_size);
844   }
845 }
846
847
848
849 /* ------------------------------------------------------------------------- */
850 /* Insert in the protocol tree the next 8 bytes interpreted as Locator_t
851  * 
852  * Locator_t is a struct defined as:
853  * struct { 
854  *    long kind;                // kind of locator 
855  *    unsigned long port; 
856  *    octet[16] address; 
857  * } Locator_t;
858  */
859 static void rtps_util_add_locator_t(proto_tree *tree, /* Can NOT be NULL */
860                         tvbuff_t * tvb,
861                         gint       offset,
862                         int        little_endian,
863                         const guint8 * label,
864                         guint8 *   buffer,              /* Can be NULL */
865                         gint       buffer_size) {       /* Can be 0 */
866
867   proto_item * ti;
868   proto_tree * locator_tree;
869   gint32  kind;
870   guint8  addr[16];
871   guint32 port;
872   char temp_buff[MAX_LOCATOR_SIZE];
873   char addr_buff[MAX_IPV6_SIZE];
874   const char *kind_string = NULL;
875   int i;
876
877
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);
882   }
883
884
885   switch(kind) {
886     case LOCATOR_KIND_UDPV4:
887         kind_string = "LOCATOR_KIND_UDPV4";
888         g_snprintf(addr_buff, MAX_IPV6_SIZE,
889                         "%d.%d.%d.%d",
890                         addr[12],
891                         addr[13],
892                         addr[14],
893                         addr[15]);
894         g_snprintf(temp_buff, MAX_LOCATOR_SIZE, "%s:%d",
895                         addr_buff,
896                         port);
897         break;
898
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 }",
904                         addr_buff,
905                         port);
906         break;
907
908     case LOCATOR_KIND_INVALID:
909         kind_string = "LOCATOR_KIND_INVALID";
910
911     case LOCATOR_KIND_RESERVED:
912         if (!kind_string)  /* Need to guard overrides (no break before) */
913           kind_string = "LOCATOR_KIND_RESERVED";
914         
915     default:
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 }",
920                         kind,
921                         port,
922                         addr[0],
923                         addr[1],
924                         addr[2],
925                         /* ... */
926                         addr[14],
927                         addr[15]);
928   }
929         
930   ti = proto_tree_add_text(tree,
931                         tvb,
932                         offset,
933                         24,
934                         "%s: %s", 
935                         label,
936                         temp_buff);
937
938   locator_tree = proto_item_add_subtree(ti,
939                         ett_rtps_locator);
940   proto_tree_add_text(locator_tree,
941                         tvb,
942                         offset,
943                         4,
944                         "kind: %02x (%s)",
945                         kind,
946                         kind_string);
947   proto_tree_add_text(locator_tree,
948                         tvb,
949                         offset+4,
950                         4,
951                         "port: %d%s",
952                         port,
953                         (port == 0) ? " (PORT_INVALID)" : "");
954   proto_tree_add_text(locator_tree,
955                         tvb,
956                         offset + 8,
957                         16,
958                         "address: %s",
959                         addr_buff);
960   if (buffer) {
961     g_strlcpy(buffer, temp_buff, buffer_size);
962   }
963 }
964
965 /* ------------------------------------------------------------------------- */
966 /* Insert in the protocol tree the next bytes interpreted as a list of
967  * Locators:
968  *   - unsigned long numLocators
969  *   - locator 1
970  *   - locator 2
971  *   - ...
972  *   - locator n
973  */
974 static void rtps_util_add_locator_list(proto_tree *tree,
975                         tvbuff_t * tvb,
976                         gint       offset,
977                         const guint8 * label,
978                         int        little_endian) {
979
980   proto_item *ti;
981   proto_tree *locator_tree;
982   guint32 num_locators;
983
984   num_locators = NEXT_guint32(tvb, offset, little_endian);
985   ti = proto_tree_add_text(tree,
986                         tvb,
987                         offset,
988                         4,
989                         "%s: %d Locators", 
990                         label,
991                         num_locators);
992
993   if (num_locators > 0) {
994     guint32 i;
995     char temp_buff[20];
996
997     locator_tree = proto_item_add_subtree(ti,
998                         ett_rtps_locator_udp_v4);
999   
1000     for (i = 0; i < num_locators; ++i) {
1001       g_snprintf(temp_buff, 20, "Locator[%d]", i);
1002       rtps_util_add_locator_t(tree,
1003                         tvb,
1004                         offset + 4 + (i * 24),
1005                         little_endian,
1006                         temp_buff,
1007                         NULL,
1008                         0);
1009     }
1010   }
1011 }  
1012
1013
1014 /* ------------------------------------------------------------------------- */
1015 /* Insert in the protocol tree the next 4 bytes interpreted as IPV4Address_t 
1016  */
1017 static void rtps_util_add_ipv4_address_t(proto_tree *tree, /* Can be NULL */
1018                         tvbuff_t * tvb,
1019                         gint       offset,
1020                         int        little_endian,
1021                         const guint8 * label,
1022                         guint8 *   buffer,              /* Can be NULL */
1023                         gint       buffer_size) {       /* Can be 0 */
1024     
1025   guint32 address;
1026
1027   address = NEXT_guint32(tvb, offset, little_endian);
1028   if (address == IPADDRESS_INVALID) {
1029     if (buffer) {
1030       g_strlcpy(buffer, IPADDRESS_INVALID_STRING, buffer_size);
1031     }
1032     if (tree) {
1033       proto_tree_add_text(tree,
1034                         tvb,
1035                         offset,
1036                         4,
1037                         "%s: %s", 
1038                         label,
1039                         IPADDRESS_INVALID_STRING);
1040     }
1041   } else {
1042     if (buffer) {
1043       g_snprintf(buffer, buffer_size,
1044                         "%d.%d.%d.%d",
1045                         (address >> 24) & 0xff,
1046                         (address >> 16) & 0xff,
1047                         (address >> 8) & 0xff,
1048                         address & 0xff);
1049     }
1050     if (tree) {
1051       proto_tree_add_text(tree,
1052                         tvb,
1053                         offset,
1054                         4,
1055                         "%s: %d.%d.%d.%d", 
1056                         label,
1057                         (address >> 24) & 0xff,
1058                         (address >> 16) & 0xff,
1059                         (address >> 8) & 0xff,
1060                         address & 0xff);
1061     }
1062   }
1063 }
1064
1065
1066
1067 /* ------------------------------------------------------------------------- */
1068 /* Insert in the protocol tree the next 8 bytes interpreted as LocatorUDPv4
1069  * 
1070  * LocatorUDPv4 is a struct defined as:
1071  * struct { 
1072  *    unsigned long address; 
1073  *    unsigned long port; 
1074  * } LocatorUDPv4_t;
1075  *
1076  */
1077 static void rtps_util_add_locator_udp_v4(proto_tree *tree, /* Can NOT be NULL */
1078                         tvbuff_t * tvb,
1079                         gint       offset,
1080                         const guint8 * label,
1081                         int        little_endian) {
1082
1083   proto_item * ti;
1084   proto_tree * locator_tree;
1085   guint32 port;
1086   char portLabel[MAX_PORT_SIZE];
1087   char address[MAX_IPV4_ADDRESS_SIZE];
1088
1089   port = NEXT_guint32(tvb, offset+4, little_endian);
1090
1091   if (port == PORT_INVALID) {
1092     g_snprintf(portLabel, MAX_PORT_SIZE, "%s (0x00000000)", PORT_INVALID_STRING);
1093   } else {
1094     g_snprintf(portLabel, MAX_PORT_SIZE, "%u", port);
1095   }
1096
1097   ti = proto_tree_add_text(tree,
1098                         tvb,
1099                         offset,
1100                         8,
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,
1104                         tvb,
1105                         offset,
1106                         little_endian,
1107                         "address",
1108                         address,
1109                         MAX_IPV4_ADDRESS_SIZE);
1110   proto_tree_add_text(locator_tree,
1111                         tvb,
1112                         offset + 4,
1113                         4,
1114                         "port: %s",
1115                         portLabel);
1116
1117   proto_item_set_text(ti, "%s: { address=%s, port=%s }", 
1118                         label,
1119                         address,
1120                         portLabel);
1121 }
1122
1123
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
1128  *  - hf_rtps_host_id
1129  *  - hf_rtps_app_id
1130  *  - hf_rtps_app_id_instance_id
1131  *  - hf_rtps_app_id_app_kind
1132  * 
1133  * If buffer is specified, it returns in it a string representation of the
1134  * data read.
1135  */
1136 static void rtps_util_add_guid_prefix(proto_tree *tree, /* Can be NULL */
1137                         tvbuff_t * tvb,
1138                         gint       offset,
1139                         int        hf_prefix,           /* Cannot be 0 if tree != NULL */
1140                         int        hf_host_id,
1141                         int        hf_app_id,
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 */
1146                         gint       buffer_size) {
1147   guint32  host_id;
1148   guint32  app_id;
1149   guint32  instance_id;
1150   guint8   app_kind;
1151   guint8 * temp_buff;
1152   guint8   guid_prefix[8];
1153   const guint8 * safe_label;
1154   int i;
1155
1156   safe_label = (label == NULL) ? (const guint8 *)"guidPrefix" : label;
1157
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);
1163   }
1164   instance_id = (app_id >> 8);
1165   app_kind    = (app_id & 0xff);
1166
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"
1172                         " (%s: %06x) }",
1173                         safe_label,
1174                         guid_prefix[0],
1175                         guid_prefix[1],
1176                         guid_prefix[2],
1177                         guid_prefix[3],
1178                         guid_prefix[4],
1179                         guid_prefix[5],
1180                         guid_prefix[6],
1181                         guid_prefix[7],
1182                         host_id,
1183                         app_id,
1184                         val_to_str(app_kind, app_kind_vals, "%02x"),
1185                         instance_id);
1186
1187   if (tree != NULL) {
1188     proto_item * ti, *hidden_item;
1189     proto_tree * guid_tree;
1190     proto_tree * appid_tree;
1191
1192     /* The numeric value (used for searches) */
1193     hidden_item = proto_tree_add_item(tree,
1194                         hf_prefix,
1195                         tvb,
1196                         offset,
1197                         8,
1198                         FALSE);
1199     PROTO_ITEM_SET_HIDDEN(hidden_item);
1200
1201     /* The text node (root of the guid prefix sub-tree) */
1202     ti = proto_tree_add_text(tree,
1203                         tvb,
1204                         offset,
1205                         8, "%s",
1206                         temp_buff);
1207
1208     guid_tree = proto_item_add_subtree(ti,
1209                         ett_rtps_guid_prefix);
1210
1211     /* Host Id */
1212     proto_tree_add_item(guid_tree,
1213                         hf_host_id,
1214                         tvb,
1215                         offset,
1216                         4,
1217                         FALSE);
1218
1219     /* AppId (root of the app_id sub-tree */
1220     ti = proto_tree_add_item(guid_tree,
1221                         hf_app_id,
1222                         tvb,
1223                         offset+4,
1224                         4,
1225                         FALSE);
1226     appid_tree = proto_item_add_subtree(ti,
1227                         ett_rtps_app_id);
1228
1229     /* InstanceId */
1230     proto_tree_add_item(appid_tree,
1231                         hf_app_id_instance_id,
1232                         tvb,
1233                         offset+4,
1234                         3,
1235                         FALSE);
1236     /* AppKind */
1237     proto_tree_add_item(appid_tree,
1238                         hf_app_id_app_kind,
1239                         tvb,
1240                         offset+7,
1241                         1,
1242                         FALSE);
1243   }
1244
1245   if (buffer != NULL) {
1246     g_strlcpy(buffer, temp_buff, buffer_size);
1247   }
1248   g_free(temp_buff);
1249 }
1250
1251
1252
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.
1258   */
1259 static int rtps_util_add_entity_id(proto_tree *tree,
1260                         tvbuff_t * tvb,
1261                         gint       offset,
1262                         int        hf_item,
1263                         int        hf_item_entity_key,
1264                         int        hf_item_entity_kind,
1265                         int        subtree_entity_id,
1266                         const char *label,
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);
1272
1273   if (entity_id_out != NULL) {
1274     *entity_id_out = entity_id;
1275   }
1276
1277
1278   if (tree != NULL) {
1279     proto_tree * entity_tree;
1280     proto_item * ti;
1281
1282     if (str_predef == NULL) {
1283       /* entityId is not a predefined value, format it */
1284       ti = proto_tree_add_uint_format(tree, 
1285                         hf_item,
1286                         tvb, 
1287                         offset, 
1288                         4,
1289                         entity_id,
1290                         "%s: 0x%08x (%s: 0x%06x)",
1291                         label,
1292                         entity_id,
1293                         val_to_str(entity_kind, entity_kind_vals, 
1294                                         "unknown (%02x)"),
1295                         entity_key);
1296     } else {
1297       /* entityId is a predefined value */
1298       ti = proto_tree_add_uint_format(tree, 
1299                         hf_item,
1300                         tvb, 
1301                         offset, 
1302                         4,
1303                         entity_id,
1304                         "%s: %s (0x%08x)", label, str_predef, entity_id);
1305     }
1306
1307     entity_tree = proto_item_add_subtree(ti,
1308                         subtree_entity_id);
1309
1310     proto_tree_add_item(entity_tree, 
1311                         hf_item_entity_key,
1312                         tvb,
1313                         offset,
1314                         3,
1315                         FALSE);
1316
1317     proto_tree_add_item(entity_tree, 
1318                         hf_item_entity_kind,
1319                         tvb,
1320                         offset+3,
1321                         1,
1322                         FALSE);
1323   
1324   }
1325
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 );
1336 }
1337
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).
1342   */
1343 static void rtps_util_add_generic_entity_id(proto_tree *tree,
1344                         tvbuff_t * tvb,
1345                         gint       offset,
1346                         const char *label,
1347                         guint8 *   buffer,                      /* Can be NULL */
1348                         gint       buffer_size) {
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];
1354
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)",
1359                         entity_id,
1360                         val_to_str(entity_kind, entity_kind_vals, 
1361                                       "unknown kind (%02x)"),
1362                         entity_key);
1363   } else {
1364     /* entityId is a predefined value */
1365     g_snprintf(temp_buffer, MAX_GUID_SIZE,
1366                         "%s (0x%08x)", 
1367                         str_predef, 
1368                         entity_id);
1369   }
1370
1371   if (tree != NULL) {
1372       proto_tree_add_text(tree, 
1373                         tvb, 
1374                         offset, 
1375                         4,
1376                         "%s: %s",
1377                         label,
1378                         temp_buffer);
1379   }
1380
1381   if (buffer != NULL) {
1382       g_strlcpy(buffer, temp_buffer, buffer_size);
1383   }
1384 }
1385
1386
1387
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).
1393   */
1394 static void rtps_util_add_generic_guid(proto_tree *tree,                /* Cannot be NULL */
1395                         tvbuff_t * tvb,                         /* Cannot be NULL */
1396                         gint       offset,
1397                         const char *label,                      /* Cannot be NULL */
1398                         guint8 *   buffer,                      /* Can be NULL */
1399                         gint       buffer_size) {
1400
1401   guint32 host_id;
1402   guint32 app_id;
1403   guint8  app_kind;
1404   guint32 instance_id;
1405   guint32 entity_id;
1406   guint32 entity_key;
1407   guint8  entity_kind;
1408   guint8  guid_raw[12];
1409   const char * str_entity_kind;
1410   const char * str_app_kind;
1411   guint8 temp_buff[MAX_GUID_SIZE];
1412   int i;
1413
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);
1418
1419   /* Re-Read raw data */
1420   for (i = 0; i < 12; ++i) {
1421     guid_raw[i] = tvb_get_guint8(tvb, offset+i);
1422   }
1423
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);
1429
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");
1433
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) }",
1438                         label,
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],
1442                         host_id,
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);
1448   }
1449 }
1450
1451
1452 /* ------------------------------------------------------------------------- */
1453 /* Insert in the protocol tree the next 8 bytes interpreted as sequence
1454  * number.
1455  */
1456 static guint64 rtps_util_add_seq_number(proto_tree *tree,
1457                         tvbuff_t * tvb,
1458                         gint       offset,
1459                         int        little_endian,
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;
1464
1465   if (tree != NULL) {
1466     proto_tree_add_int64_format(tree, 
1467                         hf_rtps_sm_seq_number,
1468                         tvb,
1469                         offset,
1470                         8,
1471                         all,
1472                         "%s: %" G_GINT64_MODIFIER "u", label, all);
1473   }
1474   return all;
1475 }
1476
1477
1478 /* ------------------------------------------------------------------------- */
1479 /* Insert in the protocol tree the next 8 bytes interpreted as NtpTime
1480  */
1481 static void rtps_util_add_ntp_time(proto_tree *tree,    /* Can be NULL */
1482                         tvbuff_t * tvb,
1483                         gint       offset,
1484                         int        little_endian,
1485                         const char * label,
1486                         guint8 *   buffer,              /* Can be NULL */
1487                         gint       buffer_size) {
1488   guint8  tempBuffer[MAX_NTP_TIME_SIZE];
1489
1490   gint32 sec = NEXT_guint32(tvb, offset, little_endian);
1491   guint32 frac = NEXT_guint32(tvb, offset+4, little_endian);
1492   double absolute;
1493
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);
1498   } else {
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);
1502   }
1503   if (tree != NULL) {
1504     proto_item * ti;
1505     proto_tree *time_tree;
1506
1507     ti = proto_tree_add_none_format(tree,
1508                         hf_rtps_param_ntpt,
1509                         tvb,
1510                         offset,
1511                         8,
1512                         "%s: %s",
1513                         label,
1514                         tempBuffer);
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,
1518                         tvb,
1519                         offset,
1520                         4,
1521                         little_endian);
1522     proto_tree_add_item(time_tree, 
1523                         hf_rtps_param_ntpt_fraction,
1524                         tvb,
1525                         offset+4,
1526                         4,
1527                         little_endian);
1528   }
1529   if (buffer != NULL) {
1530     g_strlcpy(buffer, tempBuffer, buffer_size);
1531   }
1532 }
1533
1534 /* ------------------------------------------------------------------------- */
1535 /* Insert in the protocol tree the next data interpreted as a String
1536  * Returns the new offset (after reading the string)
1537  */
1538 static gint rtps_util_add_string(proto_tree *tree,      /* Can be NULL */
1539                         tvbuff_t * tvb,
1540                         gint       offset,
1541                         int        hf_item,             /* Can be -1 (if label!=NULL) */
1542                         int        little_endian,
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);
1548
1549   if (size > 0) {
1550     retVal = tvb_get_string(tvb, offset+4, size);
1551   } 
1552
1553   if (tree != NULL) {
1554     if (hf_item != -1) {
1555       proto_item * hidden_item;
1556       hidden_item = proto_tree_add_string(tree, 
1557                         hf_item,
1558                         tvb,
1559                         offset,
1560                         size+4,
1561                         (size == 0) ? (guint8 *)"" : retVal);
1562       PROTO_ITEM_SET_HIDDEN(hidden_item);
1563     }
1564     proto_tree_add_text(tree,
1565                         tvb,
1566                         offset,
1567                         size+4,
1568                         "%s: \"%s\"", 
1569                         ((label != NULL) ? label : (const guint8 *)"value") , 
1570                         (size == 0) ? (guint8 *)"" : retVal);
1571   }
1572   if (buffer != NULL) {
1573     if (size == 0) {
1574         buffer[0] = '\0';
1575     } else {
1576       g_snprintf(buffer, (gulong) buffer_size, "%s", retVal);
1577     }
1578   }
1579   g_free(retVal);
1580
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;
1587    * ...
1588    */
1589   return offset + 4 + ((size + 3) & 0xfffffffc);
1590 }
1591
1592
1593 /* ------------------------------------------------------------------------- */
1594 /* Insert in the protocol tree the next data interpreted as a signed long.
1595  */
1596 static void rtps_util_add_long(proto_tree *tree,        /* Can be NULL */
1597                         tvbuff_t * tvb,
1598                         gint       offset,
1599                         int        hf_item,             /* Can be -1 */
1600                         int        little_endian,
1601                         gboolean   is_hex,              /* Format as 0x... */
1602                         gboolean   is_signed,           /* Signed/Unsigned */
1603                         const char *label,              /* Can be NULL */
1604                         guint8 *   buffer,
1605                         size_t     buffer_size) {
1606
1607   char temp_buff[16];
1608
1609   g_snprintf(temp_buff, 16, 
1610                         (is_hex ? "0x%08x" : (is_signed ? "%d" : "%u")), 
1611                         NEXT_guint32(tvb, offset, little_endian));
1612   if (tree != NULL) {
1613     if (hf_item != -1) {
1614       proto_tree_add_item(tree, 
1615                         hf_item,
1616                         tvb,
1617                         offset,
1618                         4,
1619                         little_endian);
1620     } else if (label != NULL) {
1621       proto_tree_add_text(tree,
1622                         tvb,
1623                         offset,
1624                         4,
1625                         "%s: %s", 
1626                         label,
1627                         temp_buff);
1628     }
1629   }
1630   if (buffer != NULL) {
1631     g_strlcpy(buffer, temp_buff, (gulong) buffer_size);
1632   }
1633 }
1634
1635 /* ------------------------------------------------------------------------- */
1636 /* Insert in the protocol tree the next data interpreted as a port (unsigned
1637  * 32-bit integer)
1638  */
1639 static void rtps_util_add_port(proto_tree *tree,        /* Can be NULL */
1640                         tvbuff_t * tvb,
1641                         gint       offset,
1642                         int        little_endian,
1643                         char *     label,
1644                         guint8 *   buffer,              /* Can be NULL */
1645                         gint       buffer_size) {
1646   guint8 tempBuffer[MAX_PORT_SIZE];
1647   guint32 value = NEXT_guint32(tvb, offset, little_endian);
1648
1649   if (value == PORT_INVALID) {
1650     g_snprintf(buffer, buffer_size, "%s (0x00000000)", PORT_INVALID_STRING);
1651   } else {
1652     g_snprintf(tempBuffer, MAX_PORT_SIZE, "%u", value);
1653   }
1654
1655   if (tree != NULL) {
1656     proto_tree_add_text(tree,
1657                         tvb,
1658                         offset,
1659                         4,
1660                         "%s: %s", 
1661                         label,
1662                         tempBuffer);
1663   }
1664   if (buffer != NULL) {
1665     g_strlcpy(buffer, tempBuffer, buffer_size);
1666   }
1667 }
1668
1669
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.
1674  */
1675 static void rtps_util_add_boolean(proto_tree *tree,     /* Can be NULL */
1676                         tvbuff_t * tvb,
1677                         gint       offset,
1678                         char *     label,
1679                         guint8 *   buffer,              /* Can be NULL */
1680                         size_t     buffer_size) {
1681   const char *str;
1682   guint8 value = tvb_get_guint8(tvb, offset);
1683
1684   str = value ? "TRUE" : "FALSE";
1685
1686   if (buffer) {
1687     g_strlcpy(buffer, str, (gulong) buffer_size);
1688   }
1689
1690   if (tree) {
1691     proto_tree_add_text(tree,
1692                         tvb,
1693                         offset,
1694                         1,
1695                         "%s: %s", 
1696                         label,
1697                         str);
1698   }
1699 }
1700
1701
1702 /* ------------------------------------------------------------------------- */
1703 /* Insert in the protocol tree the next bytes interpreted as 
1704  * DurabilityServiceQosPolicy
1705  */
1706 static void rtps_util_add_durability_service_qos(proto_tree *tree,
1707                         tvbuff_t * tvb,
1708                         gint       offset,
1709                         int        little_endian,
1710                         guint8 *   buffer,
1711                         gint       buffer_size) {
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);
1718
1719   rtps_util_add_ntp_time(NULL,
1720                         tvb,
1721                         offset,
1722                         little_endian,
1723                         NULL,
1724                         temp_buffer,
1725                         MAX_NTP_TIME_SIZE);
1726
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 }", 
1731                         temp_buffer,
1732                         val_to_str(kind, history_qos_vals, "0x%08x"),
1733                         history_depth,
1734                         max_samples,
1735                         max_instances,
1736                         max_spi);
1737
1738   rtps_util_add_ntp_time(tree,
1739                         tvb,
1740                         offset,
1741                         little_endian,
1742                         "service_cleanup_delay",
1743                         NULL,
1744                         0);
1745   proto_tree_add_text(tree,
1746                         tvb,
1747                         offset+8,
1748                         4,
1749                         "history_kind: %s",
1750                         val_to_str(kind, history_qos_vals, "0x%08x"));
1751   proto_tree_add_text(tree,
1752                         tvb,
1753                         offset+12,
1754                         4,
1755                         "history_depth: %d",
1756                         history_depth);
1757   proto_tree_add_text(tree,
1758                         tvb,
1759                         offset+16,
1760                         4,
1761                         "max_samples: %d",
1762                         max_samples);
1763   proto_tree_add_text(tree,
1764                         tvb,
1765                         offset+20,
1766                         4,
1767                         "max_instances: %d",
1768                         max_instances);
1769   proto_tree_add_text(tree,
1770                         tvb,
1771                         offset+24,
1772                         4,
1773                         "max_samples_per_instances: %d",
1774                         max_spi);
1775
1776 }
1777
1778 /* ------------------------------------------------------------------------- */
1779 /* Insert in the protocol tree the next bytes interpreted as Liveliness
1780  * QoS Policy structure.
1781  */
1782 static void rtps_util_add_liveliness_qos(proto_tree *tree,
1783                         tvbuff_t * tvb,
1784                         gint       offset,
1785                         int        little_endian,
1786                         guint8 *   buffer,
1787                         gint       buffer_size) {
1788   guint8  temp_buffer[MAX_NTP_TIME_SIZE];
1789   guint32 kind = NEXT_guint32(tvb, offset, little_endian);
1790
1791   rtps_util_add_ntp_time(NULL,
1792                         tvb,
1793                         offset+4,
1794                         little_endian,
1795                         NULL,
1796                         temp_buffer,
1797                         MAX_NTP_TIME_SIZE);
1798
1799   g_snprintf(buffer, buffer_size, 
1800                     "{ kind=%s, lease_duration=%s }", 
1801                     val_to_str(kind, liveliness_qos_vals, "0x%08x"),
1802                     temp_buffer);
1803
1804   proto_tree_add_text(tree,
1805                         tvb,
1806                         offset,
1807                         4,
1808                         "kind: %s",
1809                         val_to_str(kind, liveliness_qos_vals, "0x%08x"));
1810   rtps_util_add_ntp_time(tree,
1811                         tvb,
1812                         offset+4,
1813                         little_endian,
1814                         "lease_duration",
1815                         NULL,
1816                         0);
1817 }
1818
1819 /* ------------------------------------------------------------------------- */
1820 /* Insert in the protocol tree the next bytes interpreted as enum type.
1821  */
1822 static void rtps_util_add_kind_qos(proto_tree *tree,    /* Can be NULL */
1823                         tvbuff_t * tvb,
1824                         gint       offset,
1825                         int        little_endian,
1826                         char *     label,
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);
1831
1832   if (buffer) {
1833     g_strlcpy(buffer, val_to_str(kind, vals, "0x%08x"),
1834                         (gulong) buffer_size);
1835   }
1836
1837   if (tree) {
1838     proto_tree_add_text(tree,
1839                         tvb,
1840                         offset,
1841                         4,
1842                         "%s: %s",
1843                         label,
1844                         buffer);
1845   }
1846 }
1847
1848
1849 /* ------------------------------------------------------------------------- */
1850 /* Insert in the protocol tree the next bytes interpreted as Sequence of
1851  * Strings.
1852  * The formatted buffer is: "string1", "string2", "string3", ...
1853  * Returns the new updated offset
1854  */
1855 static gint rtps_util_add_seq_string(proto_tree *tree,  /* Can NOT be NULL */
1856                         tvbuff_t * tvb,
1857                         gint       offset,
1858                         int        little_endian,
1859                         int        param_length,
1860                         char *     label,
1861                         guint8 *   buffer,              /* Can NOT be NULL */
1862                         gint       buffer_size) {
1863   guint32 num_strings;
1864   guint32 i;
1865   proto_tree *string_tree;
1866   proto_item *ti;
1867   char temp_buff[MAX_LABEL_SIZE];
1868   guint8 overview_buffer[MAX_LABEL_SIZE];
1869
1870   num_strings = NEXT_guint32(tvb, offset, little_endian);
1871   proto_tree_add_text(tree,
1872                         tvb,
1873                         offset,
1874                         4,
1875                         "size: %d", num_strings);
1876   offset += 4;
1877
1878   /* Create the string node with a fake string, the replace it later */
1879   ti = proto_tree_add_text(tree, 
1880                         tvb,
1881                         offset,
1882                         param_length-8,
1883                         "Strings");
1884   string_tree = proto_item_add_subtree(ti, ett_rtps_seq_string);
1885   
1886   overview_buffer[0] = '\0';
1887
1888   for (i = 0; i < num_strings; ++i) {
1889     g_snprintf(temp_buff, MAX_LABEL_SIZE, 
1890                         "%s[%d]",
1891                         label,
1892                         i);
1893     offset = rtps_util_add_string(string_tree,
1894                         tvb,
1895                         offset,
1896                         -1,
1897                         little_endian,
1898                         temp_buff,
1899                         overview_buffer+strlen(overview_buffer),
1900                         MAX_LABEL_SIZE-strlen(overview_buffer));
1901   }
1902   proto_item_set_text(ti,
1903                         "%s: %s",
1904                         label,
1905                         overview_buffer);
1906   if (buffer != NULL) {
1907     g_strlcpy(buffer, overview_buffer, buffer_size);
1908   }
1909   return offset;
1910 }
1911
1912 /* ------------------------------------------------------------------------- */
1913 /* Insert in the protocol tree the next bytes interpreted as Sequence of
1914  * longs.
1915  * The formatted buffer is: val1, val2, val3, ...
1916  * Returns the new updated offset
1917  */
1918 static gint rtps_util_add_seq_ulong(proto_tree *tree,   /* Can NOT be NULL */
1919                         tvbuff_t * tvb,
1920                         gint       offset,
1921                         int        little_endian,
1922                         int        param_length,
1923                         int        is_hex,
1924                         int        is_signed,
1925                         char *     label) {
1926   guint32 num_elem;
1927   guint32 i;
1928   proto_tree *string_tree;
1929   proto_item *ti;
1930   char temp_buff[MAX_LABEL_SIZE];
1931   char overview_buff[MAX_PARAM_SIZE];
1932
1933   num_elem = NEXT_guint32(tvb, offset, little_endian);
1934   offset += 4;
1935
1936   /* Create the string node with an empty string, the replace it later */
1937   ti = proto_tree_add_text(tree, 
1938                         tvb,
1939                         offset,
1940                         param_length-8,
1941                         "Seq");
1942   string_tree = proto_item_add_subtree(ti, ett_rtps_seq_ulong);
1943   
1944   overview_buff[0] = '\0';
1945
1946   for (i = 0; i < num_elem; ++i) {
1947     g_snprintf(temp_buff, MAX_LABEL_SIZE, 
1948                         "%s[%d]",
1949                         label,
1950                         i);
1951     rtps_util_add_long( string_tree,
1952                         tvb,
1953                         offset,
1954                         -1,
1955                         little_endian,
1956                         is_hex,
1957                         is_signed,
1958                         temp_buff,
1959                         overview_buff+strlen(overview_buff),
1960                         MAX_PARAM_SIZE-strlen(overview_buff));
1961     offset += 4;
1962   }
1963   proto_item_set_text(ti,
1964                         "%s: %s",
1965                         label,
1966                         overview_buff);
1967                         
1968   return offset;
1969 }
1970
1971
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")
1976
1977
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";
2003
2004         case RTI_CDR_TK_NULL:
2005         default:
2006             return "<unknown type>";
2007     }
2008 }
2009
2010 /* ------------------------------------------------------------------------- */
2011 /* Insert in the protocol tree the next bytes interpreted as typecode info
2012  * Returns the number of bytes parsed 
2013  */
2014 static gint rtps_util_add_typecode(proto_tree *tree,
2015                         tvbuff_t * tvb,
2016                         gint       offset,
2017                         int        little_endian,
2018                         int        indent_level,
2019                         int        is_pointer,
2020                         guint16    bitfield,
2021                         int        is_key,
2022                         const gint offset_begin,
2023                         char     * name,
2024                         int        seq_max_len, /* -1 = not a sequence field */
2025                         guint32 *  arr_dimension, /* if !NULL: array of 10 int */
2026                         int        ndds_40_hack) {
2027   const gint original_offset = offset;
2028   guint32 tk_id;
2029   guint16 tk_size;
2030   unsigned int i;
2031   char    indent_string[40];
2032   gint    retVal;
2033   char    type_name[40];
2034   
2035     /* Structure of the typecode data:
2036      *  Offset   | Size  | Field                        | Notes
2037      * ----------|-------|------------------------------|---------------------
2038      *       ?   |    ?  | pad?                         |
2039      *       0   |    4  | RTI_CDR_TK_XXXXX             | 4 bytes aligned
2040      *       4   |    2  | length the struct            |
2041      */
2042
2043   /* Calc indent string */
2044   memset(indent_string, ' ', 40);
2045   indent_string[indent_level*2] = '\0';
2046   
2047   /* Gets TK ID */
2048   LONG_ALIGN(offset);
2049   tk_id = NEXT_guint32(tvb, offset, little_endian);
2050   offset += 4;
2051   
2052   /* Gets TK size */
2053   tk_size = NEXT_guint16(tvb, offset, little_endian);
2054   offset += 2;
2055
2056   retVal = tk_size + 6; /* 6 = 4 (typecode ID) + 2 (size) */
2057
2058   /* The first bit of typecode is set to 1, clear it */
2059   tk_id &= 0x7fffffff;
2060
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).
2067    */
2068   if (indent_level == 0) {
2069     if (tk_id == RTI_CDR_TK_OCTET) {
2070       ndds_40_hack = 1;
2071     }
2072   }
2073   if (ndds_40_hack) {
2074     ++tk_id;
2075   }
2076
2077   g_strlcpy(type_name, rtps_util_typecode_id_to_string(tk_id), 40);
2078
2079     /* Structure of the typecode data:
2080      *
2081      * <type_code_header> ::=
2082      *          <kind>
2083      *          <type_code_length>
2084      *
2085      * <kind> ::= long (0=TK_NULL, 1=TK_SHORT...)
2086      * <type_code_length> ::= unsugned short
2087      *
2088      */
2089   switch(tk_id) {
2090
2091     /* Structure of the typecode data:
2092      *
2093      * <union_type_code> ::=
2094      *          <type_code_header>
2095      *          <name>
2096      *          <default_index>
2097      *          <discriminator_type_code>
2098      *          <member_count>
2099      *          <union_member>+
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
2105      * <eol>    ::= (char)0
2106      * 
2107      * <union_member_detail> ::= <is_pointer>
2108      *          <labels_count> 
2109      *          <label>+
2110      *          <type_code> 
2111      * <labels_count> ::= unsigned long
2112      * <label> ::= long
2113      * 
2114      */
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;
2134         guint   j;
2135
2136         /* - - - - - - -      Union name      - - - - - - - */
2137         /* Pad-align */
2138         LONG_ALIGN(offset);
2139
2140         /* Get structure name length */
2141         struct_name_len = NEXT_guint32(tvb, offset, little_endian);
2142         offset += 4;
2143         struct_name = tvb_get_string(tvb, offset, struct_name_len);
2144         offset += struct_name_len;
2145
2146         /* - - - - - - -      Default index      - - - - - - - */
2147         LONG_ALIGN(offset);
2148         defaultIdx = NEXT_guint32(tvb, offset, little_endian);
2149         offset += 4;
2150
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);
2154         offset += 4;
2155
2156         disc_size = NEXT_guint16(tvb, offset, little_endian);
2157         offset += 2;
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 */
2163             LONG_ALIGN(offset);
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);
2166         }        
2167         offset = disc_offset_begin + disc_size;
2168 /*
2169             field_offset_begin = offset;
2170             offset += rtps_util_add_typecode(
2171                           tree,
2172                           tvb,         next_offset = offset;
2173
2174                           offset, 
2175                           little_endian, 
2176                           indent_level+1,
2177                           0,
2178                           0,
2179                           0,
2180                           field_offset_begin,
2181                           member_name,
2182                           -1,
2183                           NULL,
2184                           ndds_40_hack);
2185 */
2186
2187
2188         /* Add the entry of the union in the tree */
2189         proto_tree_add_text(tree,
2190                     tvb,
2191                     original_offset,
2192                     retVal,
2193                     "%sunion %s (%s%s%s) {",
2194                     indent_string,
2195                     struct_name,
2196                     discriminator_name,
2197                     (discriminator_enum_name ? " " : ""),
2198                     (discriminator_enum_name ? discriminator_enum_name : ""));
2199
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);
2204           break;
2205         }
2206
2207         g_free(struct_name);
2208         /* - - - - - - -      Number of members     - - - - - - - */
2209         LONG_ALIGN(offset);
2210         num_members = NEXT_guint32(tvb, offset, little_endian);
2211         offset += 4;
2212    
2213         /* - - - - - - -      <union_member>+     - - - - - - - */
2214         next_offset = offset;
2215
2216         for (i = 0; i < num_members; ++i) {
2217           /* Safety: this theoretically should be the same already */
2218           field_offset_begin = offset = next_offset;
2219
2220           SHORT_ALIGN(offset);
2221
2222           /* member's length */
2223           member_length = NEXT_guint16(tvb, offset, little_endian);
2224           offset += 2;
2225           next_offset = offset + member_length;
2226
2227           /* Name length */
2228           LONG_ALIGN(offset);
2229           member_name_len = NEXT_guint32(tvb, offset, little_endian);
2230           offset += 4;
2231
2232           /* Name */
2233           member_name = tvb_get_string(tvb, offset, member_name_len);
2234           offset += member_name_len;
2235
2236           /* is Pointer ? */
2237           member_is_pointer = tvb_get_guint8(tvb, offset);
2238           offset++;
2239
2240           /* Label count */
2241           LONG_ALIGN(offset);
2242           member_label_count = NEXT_guint32(tvb, offset, little_endian);
2243           offset += 4;
2244  
2245           for (j = 0; j < member_label_count; ++j) {
2246             /* Label count */
2247             LONG_ALIGN(offset);
2248             member_label = NEXT_guint32(tvb, offset, little_endian);
2249             offset += 4;
2250
2251             /* Add the entry of the union in the tree */
2252             proto_tree_add_text(tree,
2253                     tvb,
2254                     field_offset_begin,
2255                     retVal,
2256                     "%s  case %d:",
2257                     indent_string,
2258                     member_label);
2259           }
2260
2261           offset += rtps_util_add_typecode(
2262                     tree,
2263                     tvb, 
2264                     offset, 
2265                     little_endian, 
2266                     indent_level+2,
2267                     member_is_pointer,
2268                     0,
2269                     0,
2270                     field_offset_begin,
2271                     member_name,
2272                     -1,
2273                     NULL,
2274                     ndds_40_hack);
2275           g_free(member_name);
2276         }
2277         /* Finally prints the name of the struct (if provided) */
2278         g_strlcpy(type_name, "}", 40);
2279         break;
2280
2281     } /* end of case UNION */
2282
2283
2284     case RTI_CDR_TK_ENUM:
2285     case RTI_CDR_TK_STRUCT: {
2286     /* Structure of the typecode data:
2287      *
2288      * <union_type_code> ::=
2289      *          <type_code_header>
2290      *          <name>
2291      *          <default_index>
2292      *          <discriminator_type_code>
2293      *          <member_count>
2294      *          <member>+
2295      *
2296      * <struct_type_code> ::=
2297      *          <type_code_header>
2298      *          <name>
2299      *          <member_count>
2300      *          <member>+
2301      *
2302      * <name>   ::= <string>
2303      * <string> ::= <length>char+<eol>
2304      * <length> ::= unsigned long
2305      * <eol>    ::= (char)0
2306      * <member_count> ::= unsigned long
2307      *           
2308      * STRUCT / UNION:
2309      *     Foreach member {
2310      *          - A2: 2: member length  
2311      *          - A4: 4: member name length
2312      *          -     n: member name
2313      *          -     1: isPointer?
2314      *          - A2  2: bitfield bits (-1=none)
2315      *          -     1: isKey?
2316      *          - A4  4: Typecode ID
2317      *          - A2  2: length
2318      * }
2319      *
2320      * ENUM:
2321      *     Foreach member {
2322      *          - A2: 2: member length
2323      *          - A4: 4: member name length
2324      *          -     n: member name
2325      *          - A4: 4: ordinal number
2326      * 
2327      * -> ----------------------------------------------------- <-
2328      * -> The alignment pad bytes belong to the FOLLOWING field <-
2329      * ->    A4 = 4 bytes alignment, A2 = 2 bytes alignment     <-
2330      * -> ----------------------------------------------------- <-
2331      */
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;
2345
2346         /* Pad-align */
2347         LONG_ALIGN(offset);
2348
2349         /* Get structure name length */
2350         struct_name_len = NEXT_guint32(tvb, offset, little_endian);
2351         offset += 4;
2352
2353         /* struct name */
2354         struct_name = tvb_get_string(tvb, offset, struct_name_len);
2355         offset += struct_name_len;
2356
2357
2358         if (tk_id == RTI_CDR_TK_ENUM) {
2359             typecode_name = "enum";
2360         } else {
2361             typecode_name = "struct";
2362         }
2363
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);
2368           break;
2369         }
2370         /* Prints it */
2371         proto_tree_add_text(tree,
2372                     tvb,
2373                     original_offset,
2374                     retVal,
2375                     "%s%s %s {",
2376                     indent_string,
2377                     typecode_name,
2378                     struct_name);
2379         g_free(struct_name);
2380
2381         /* PAD align */
2382         LONG_ALIGN(offset);
2383
2384         /* number of members */
2385         num_members = NEXT_guint32(tvb, offset, little_endian);
2386         offset += 4;
2387
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;
2392
2393           SHORT_ALIGN(offset);
2394
2395           /* member's length */
2396           member_length = NEXT_guint16(tvb, offset, little_endian);
2397           offset += 2;
2398           next_offset = offset + member_length;
2399
2400           /* Name length */
2401           LONG_ALIGN(offset);
2402           member_name_len = NEXT_guint32(tvb, offset, little_endian);
2403           offset += 4;
2404
2405           /* Name */
2406           member_name = tvb_get_string(tvb, offset, member_name_len);
2407           offset += member_name_len;
2408
2409           if (tk_id == RTI_CDR_TK_ENUM) {
2410             /* ordinal number */
2411             LONG_ALIGN(offset);
2412             ordinal_number = NEXT_guint32(tvb, offset, little_endian);
2413             offset += 4;
2414
2415             proto_tree_add_text(tree,
2416                   tvb,
2417                   field_offset_begin,
2418                   (offset-field_offset_begin),
2419                   "%s  %s = %d;",
2420                   indent_string,
2421                   member_name,
2422                   ordinal_number);
2423           } else {
2424             /* Structs */
2425
2426             /* is Pointer ? */
2427             member_is_pointer = tvb_get_guint8(tvb, offset);
2428             offset++;
2429
2430             /* Bitfield */
2431             SHORT_ALIGN(offset);
2432             member_bitfield = NEXT_guint16(tvb, offset, little_endian);
2433             offset += 2; /* pad will be added by typecode dissector */
2434             
2435             /* is Key ? */
2436             member_is_key = tvb_get_guint8(tvb, offset);
2437             offset++;
2438
2439             offset += rtps_util_add_typecode(
2440                           tree,
2441                           tvb, 
2442                           offset, 
2443                           little_endian, 
2444                           indent_level+1,
2445                           member_is_pointer,
2446                           member_bitfield,
2447                           member_is_key,
2448                           field_offset_begin,
2449                           member_name,
2450                           -1,
2451                           NULL,
2452                           ndds_40_hack);
2453           }
2454
2455           g_free(member_name);
2456         }
2457         /* Finally prints the name of the struct (if provided) */
2458         g_strlcpy(type_name, "}", 40);
2459         break;
2460       }
2461
2462     case RTI_CDR_TK_WSTRING:
2463     case RTI_CDR_TK_STRING: {
2464     /* Structure of the typecode data:
2465      *  Offset   | Size  | Field                        | Notes
2466      * ----------|-------|------------------------------|---------------------
2467      *     6     |   2   | pad                          |
2468      *     8     |   4   | String length                | 4-bytes aligned
2469      */
2470         guint32 string_length;
2471
2472         LONG_ALIGN(offset);
2473         string_length = NEXT_guint32(tvb, offset, little_endian);
2474         offset += 4;
2475         g_snprintf(type_name, 40, "%s<%d>",
2476                 (tk_id == RTI_CDR_TK_STRING) ? "string" : "wstring",
2477                 string_length);
2478         break;
2479     }
2480
2481     case RTI_CDR_TK_SEQUENCE: {
2482     /* Structure of the typecode data:
2483      *
2484      * - A4: 4: Sequence max length
2485      * - the sequence typecode
2486      */
2487         guint32 seq_max_len;
2488         LONG_ALIGN(offset);
2489         seq_max_len = NEXT_guint32(tvb, offset, little_endian);
2490         offset += 4;
2491
2492         /* Recursive decode seq typecode */
2493         offset += rtps_util_add_typecode(
2494                           tree,
2495                           tvb, 
2496                           offset, 
2497                           little_endian, 
2498                           indent_level,
2499                           is_pointer,
2500                           bitfield,
2501                           is_key,
2502                           offset_begin,
2503                           name,
2504                           seq_max_len,
2505                           NULL,
2506                           ndds_40_hack);
2507         /* Differently from the other typecodes, the line has been already printed */
2508         return retVal;
2509     }
2510
2511     case RTI_CDR_TK_ARRAY: {
2512     /* Structure of the typecode data:
2513      *
2514      * - A4: 4: number of dimensions
2515      * - A4: 4: dim1
2516      * - <A4: 4: dim2>
2517      * - ...
2518      * - the array typecode
2519      */
2520         guint32 size[MAX_ARRAY_DIMENSION]; /* Max dimensions */
2521         guint32 dim_max;
2522
2523         LONG_ALIGN(offset);
2524         dim_max = NEXT_guint32(tvb, offset, little_endian);
2525         offset += 4;
2526
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);
2530           offset += 4;
2531         }
2532
2533         /* Recursive decode seq typecode */
2534         offset += rtps_util_add_typecode(
2535                           tree,
2536                           tvb, 
2537                           offset, 
2538                           little_endian, 
2539                           indent_level,
2540                           is_pointer,
2541                           bitfield,
2542                           is_key,
2543                           offset_begin,
2544                           name,
2545                           -1,
2546                           size,
2547                           ndds_40_hack);
2548         /* Differently from the other typecodes, the line has been already printed */
2549         return retVal;
2550     }
2551
2552     case RTI_CDR_TK_ALIAS: {
2553     /* Structure of the typecode data:
2554      *
2555      * - A4: 4: alias name size
2556      * - A4: 4: alias name
2557      * - A4: 4: the alias typecode
2558      */
2559         guint32 alias_name_length;
2560         guint8 *alias_name;
2561
2562         LONG_ALIGN(offset);
2563         alias_name_length = NEXT_guint32(tvb, offset, little_endian);
2564         offset += 4;
2565         alias_name = tvb_get_string(tvb, offset, alias_name_length);
2566         offset += alias_name_length;
2567         g_strlcpy(type_name, alias_name, 40);
2568         g_free(alias_name);
2569         break;
2570     }
2571
2572
2573     /*
2574      * VALUETYPES:
2575      * - A4: 4: name length
2576      * -     n: name
2577      * - A2: type modifier
2578      * - A4: base type code
2579      * - A4: number of members
2580      * Foreach member: (it's just like a struct)           
2581      *
2582      */
2583     case RTI_CDR_TK_VALUE: {
2584         /* Not fully dissected for now */
2585         /* Pad-align */
2586         guint32 value_name_len;
2587         gint8 * value_name;
2588         LONG_ALIGN(offset);
2589
2590         /* Get structure name length */
2591         value_name_len = NEXT_guint32(tvb, offset, little_endian);
2592         offset += 4;
2593
2594         /* value name */
2595         value_name = tvb_get_string(tvb, offset, value_name_len);
2596         offset += value_name_len;
2597
2598         g_snprintf(type_name, 40, "valuetype %s", value_name);
2599         break;
2600     }
2601   } /* switch(tk_id) */
2602
2603   /* Sequence print */
2604   if (seq_max_len != -1) {
2605     proto_tree_add_text(tree,
2606                   tvb,
2607                   offset_begin,
2608                   (offset-offset_begin),
2609                   "%ssequence<%s, %d> %s%s;%s",
2610                   indent_string,
2611                   type_name,
2612                   seq_max_len,
2613                   is_pointer ? "*" : "",
2614                   name ? name : "",
2615                   is_key ? KEY_COMMENT : "");
2616     return retVal;
2617   }
2618     
2619   /* Array print */
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]);
2626       } else {
2627         break;
2628       }
2629     }
2630     proto_tree_add_text(tree,
2631                   tvb,
2632                   offset_begin,
2633                   (offset-offset_begin),
2634                   "%s%s %s%s;%s",
2635                   indent_string,
2636                   type_name,
2637                   name ? name : "",
2638                   dim_str->str,
2639                   is_key ? KEY_COMMENT : "");
2640     return retVal;
2641   }
2642
2643   /* Bitfield print */
2644   if (bitfield != 0xffff && name != NULL && is_pointer == 0) {
2645     proto_tree_add_text(tree,
2646                   tvb,
2647                   offset_begin,
2648                   (offset-offset_begin),
2649                   "%s%s %s:%d;%s",
2650                   indent_string,
2651                   type_name,
2652                   name ? name : "",
2653                   bitfield,
2654                   is_key ? KEY_COMMENT : "");
2655     return retVal;
2656   }
2657
2658   /* Everything else */
2659   proto_tree_add_text(tree,
2660                   tvb,
2661                   offset_begin,
2662                   (offset-offset_begin),
2663                   "%s%s%s%s%s;%s",
2664                   indent_string,
2665                   type_name,
2666                   name ? " " : "",
2667                   is_pointer ? "*" : "",
2668                   name ? name : "",
2669                   is_key ? KEY_COMMENT : "");
2670   return retVal;
2671 }
2672
2673
2674 /* ------------------------------------------------------------------------- */
2675 /* Insert in the protocol tree the next bytes interpreted as Sequence of
2676  * Octects.
2677  * The formatted buffer is: [ 0x01, 0x02, 0x03, 0x04, ...]
2678  * The maximum number of elements displayed is 10, after that a '...' is
2679  * inserted.
2680  */
2681 static void rtps_util_add_seq_octets(proto_tree *tree,
2682                         tvbuff_t * tvb,
2683                         gint       offset,
2684                         int        little_endian,
2685                         int        param_length,
2686                         int        hf_id,
2687                         guint8 *   buffer,
2688                         gint       buffer_size) {
2689   gint idx = 0;
2690   guint32 seq_length;
2691   guint32 i;
2692   gint original_offset = offset;
2693   guint32 original_seq_length;
2694
2695   original_seq_length = seq_length = NEXT_guint32(tvb, offset, little_endian);
2696
2697   offset += 4;
2698   if (param_length < 4 + (int)seq_length) {
2699     g_strlcpy(buffer,
2700                         "RTPS PROTOCOL ERROR: parameter value too small",
2701                         buffer_size);
2702     proto_tree_add_text(tree,
2703                       tvb, 
2704                       offset, 
2705                       param_length, "%s",
2706                       buffer);
2707     return ;
2708   }
2709
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;
2713   }
2714   for (i = 0; i < seq_length; ++i) {
2715     idx += g_snprintf(&buffer[idx], 
2716                         buffer_size - idx - 1,
2717                         "%02x", 
2718                         tvb_get_guint8(tvb, offset++));
2719     if (idx >= buffer_size) {
2720         break;
2721     }
2722   }
2723   if (seq_length != original_seq_length) {
2724     /* seq_length was reduced, add '...' */
2725     g_strlcat(buffer, "...", buffer_size);
2726   }
2727
2728   if (tree != NULL) {
2729     proto_tree_add_text(tree,
2730                         tvb,
2731                         original_offset,
2732                         4,
2733                         "sequenceSize: %d octects",
2734                         original_seq_length);
2735     proto_tree_add_item(tree,
2736                         hf_id,
2737                         tvb,
2738                         original_offset+4,
2739                         original_seq_length,
2740                         little_endian);
2741
2742   }
2743 }
2744
2745
2746
2747
2748 /* ------------------------------------------------------------------------- */
2749 /* Insert in the protocol tree the next bytes interpreted as a Bitmap
2750  * struct {
2751  *     SequenceNumber_t    bitmapBase;
2752  *     sequence<long, 8>   bitmap;
2753  * } SequenceNumberSet;
2754  * 
2755  * Returns the new offset after reading the bitmap.
2756  */
2757 static int rtps_util_add_bitmap(proto_tree *tree,
2758                         tvbuff_t * tvb,
2759                         gint       offset,
2760                         int        little_endian,
2761                         const char *label _U_) {
2762   guint64 seq_base;
2763   gint32 num_bits;
2764   guint32 data;
2765   char temp_buff[MAX_BITMAP_SIZE];
2766   int i, j, idx;
2767   proto_item * ti;
2768   proto_tree * bitmap_tree;
2769   const gint original_offset = offset;
2770   guint32 datamask;
2771
2772   /* Bitmap base sequence number */
2773   seq_base = rtps_util_add_seq_number(NULL,
2774                         tvb,
2775                         offset,
2776                         little_endian,
2777                         NULL);
2778   offset += 8;
2779
2780   /* Reads the bitmap size */
2781   num_bits = NEXT_guint32(tvb, offset, little_endian);
2782
2783   offset += 4;
2784
2785   /* Reads the bits (and format the print buffer) */
2786   idx = 0;
2787   for (i = 0; i < num_bits; i += 32) {
2788     data = NEXT_guint32(tvb, offset, little_endian);
2789     offset += 4;
2790     for (j = 0; j < 32; ++j) {
2791       datamask = (1 << (31-j));
2792       temp_buff[idx] = ((data & datamask) == datamask) ? '1':'0';
2793       ++idx;
2794       if (idx > num_bits) {
2795         break;
2796       }
2797       if (idx >= MAX_BITMAP_SIZE-1) {
2798         break;
2799       }
2800     }
2801   }
2802   temp_buff[idx] = '\0';
2803
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';
2807   }
2808
2809   ti = proto_tree_add_text(tree,
2810                         tvb,
2811                         original_offset,
2812                         offset-original_offset,
2813                         "%s: %" G_GINT64_MODIFIER "u/%d:%s",
2814                         label,
2815                         seq_base,
2816                         num_bits,
2817                         temp_buff);
2818   bitmap_tree = proto_item_add_subtree(ti, ett_rtps_bitmap);
2819   proto_tree_add_text(bitmap_tree,
2820                         tvb,
2821                         original_offset,
2822                         8,
2823                         "bitmapBase: %" G_GINT64_MODIFIER "u",
2824                         seq_base);
2825   proto_tree_add_text(bitmap_tree,
2826                         tvb,
2827                         original_offset + 8,
2828                         4,
2829                         "numBits: %u",
2830                         num_bits);
2831   if (temp_buff[0] != '\0') {
2832     proto_tree_add_text(bitmap_tree,
2833                         tvb,
2834                         original_offset + 12,
2835                         offset - original_offset - 12,
2836                         "bitmap: %s",
2837                         temp_buff);
2838   }
2839   return offset;
2840 }
2841
2842
2843 /* ------------------------------------------------------------------------- */
2844 /* Decode the submessage flags
2845  */
2846 static void rtps_util_decode_flags(proto_tree * tree,
2847                         tvbuff_t *tvb,
2848                         gint      offset,
2849                         guint8 flags,
2850                         const struct Flag_definition * flag_def) {
2851
2852   proto_item * ti;
2853   proto_tree * flags_tree;
2854   int i, j;
2855   char flags_str[MAX_FLAG_SIZE];
2856     
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));
2861   }
2862
2863   ti = proto_tree_add_uint_format(tree, 
2864                         hf_rtps_sm_flags,
2865                         tvb, 
2866                         offset, 
2867                         1, 
2868                         flags,
2869                         "Flags: 0x%02x (%s)", 
2870                         flags,
2871                         flags_str);
2872
2873   flags_tree = proto_item_add_subtree(ti,
2874                         ett_rtps_flags);
2875
2876   for (i = 0; i < 8; ++i) {
2877     int is_set = (flags & (1 << (7-i)));
2878
2879     for (j = 0; j < 8; ++j) {
2880       flags_str[j] = (i == j) ? (is_set ? '1' : '0') : '.';
2881     }
2882     flags_str[8] = '\0';
2883     
2884     proto_tree_add_text(flags_tree,
2885                         tvb,
2886                         offset,
2887                         1,
2888                         "%s = %s: %s",
2889                         flags_str,
2890                         flag_def[i].description,
2891                         is_set ? "Set" : "Not set");
2892   }
2893   
2894 }
2895
2896
2897
2898
2899
2900
2901 /* *********************************************************************** */
2902 /* * Parameter Sequence dissector                                        * */
2903 /* *********************************************************************** */
2904 /*
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
2910  * current packet).
2911  * If no error occurred, the returned value is ALWAYS > than the offset passed.
2912  */
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);        \
2919           break;                                                        \
2920         }
2921
2922 static gint dissect_parameter_sequence(proto_tree *tree,
2923                         tvbuff_t *tvb,
2924                         gint offset,
2925                         int  little_endian,
2926                         int octects_to_next_header,
2927                         const char * label) {
2928   proto_item * ti;
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;
2934   
2935   buffer[0] = '\0';
2936
2937   ti = proto_tree_add_text(tree, 
2938                         tvb, 
2939                         offset, 
2940                         -1,
2941                         "%s:", label);
2942   rtps_parameter_sequence_tree = proto_item_add_subtree(ti,
2943                         ett_rtps_parameter_sequence);
2944  
2945
2946   /* Loop through all the parameters defined until PID_SENTINEL is found */
2947   do {
2948     if (max_param_section-offset < 4) {
2949       proto_tree_add_text(tree,
2950                         tvb,
2951                         offset,
2952                         1,
2953                         "RTPS PROTOCOL ERROR: not enough bytes to read "
2954                                                 " the next parameter");
2955       return 0;
2956     }
2957
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
2960      * be set later...
2961      */
2962     parameter = NEXT_guint16(tvb, offset, little_endian);
2963     ti = proto_tree_add_text(rtps_parameter_sequence_tree, 
2964                         tvb, 
2965                         offset, 
2966                         -1,
2967                         "%s",
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,
2973                         tvb,
2974                         offset,
2975                         2,
2976                         parameter,
2977                         "parameterId: 0x%04x (%s)",
2978                         parameter,
2979                         val_to_str(parameter, parameter_id_vals,
2980                                         "unknown %04x"));
2981                         
2982     offset += 2;
2983
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,
2988                         tvb,
2989                         offset,
2990                         2,
2991                         little_endian);
2992     offset += 2;
2993
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,
2998                         tvb,
2999                         offset,
3000                         1,
3001                         "RTPS PROTOCOL ERROR: not enough bytes to read "
3002                                                 " the parameter value");
3003       return 0;
3004     }
3005
3006     /* Sets the end of this item (now we know it!) */
3007     proto_item_set_len(ti, param_length+4);
3008
3009     switch(parameter) {
3010
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        * +---------------+---------------+---------------+---------------+
3019        */
3020       case PID_PARTICIPANT_LEASE_DURATION:
3021         ENSURE_LENGTH(8);
3022         rtps_util_add_ntp_time(rtps_parameter_tree,
3023                         tvb,
3024                         offset,
3025                         little_endian,
3026                         "duration",
3027                         buffer,
3028                         MAX_PARAM_SIZE);
3029         break;
3030           
3031
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        * +---------------+---------------+---------------+---------------+
3040        */
3041       case PID_TIME_BASED_FILTER:
3042         ENSURE_LENGTH(8);
3043         rtps_util_add_ntp_time(rtps_parameter_tree,
3044                         tvb,
3045                         offset,
3046                         little_endian,
3047                         "minimum_separation",
3048                         buffer,
3049                         MAX_PARAM_SIZE);
3050         break;
3051
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        * +---------------+---------------+---------------+---------------+
3060        * |                              ...                              |
3061        * +---------------+---------------+---------------+---------------+
3062        */
3063       case PID_TOPIC_NAME:
3064         rtps_util_add_string(rtps_parameter_tree,
3065                         tvb,
3066                         offset,
3067                         hf_rtps_param_topic_name,
3068                         little_endian,
3069                         NULL,           /* No label, use hf param */
3070                         buffer,
3071                         MAX_PARAM_SIZE);
3072         break;
3073
3074
3075       /* 0...2...........7...............15.............23...............31
3076        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
3077        * | PID_OWNERSHIP_STRENGTH        |            0x0004             | 
3078        * +---------------+---------------+---------------+---------------+
3079        * |    long              strength                                 |
3080        * +---------------+---------------+---------------+---------------+
3081        */
3082       case PID_OWNERSHIP_STRENGTH:
3083         ENSURE_LENGTH(4);
3084         rtps_util_add_long(rtps_parameter_tree,
3085                         tvb,
3086                         offset,
3087                         hf_rtps_param_strength,
3088                         little_endian,
3089                         FALSE,  /* Is Hex ? */
3090                         TRUE,   /* Is Signed ? */
3091                         NULL,   /* No Label, use the protocol item ID */
3092                         buffer,
3093                         MAX_PARAM_SIZE);  
3094         break;
3095
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        * +---------------+---------------+---------------+---------------+
3104        * |                              ...                              |
3105        * +---------------+---------------+---------------+---------------+
3106        */
3107       case PID_TYPE_NAME:
3108         rtps_util_add_string(rtps_parameter_tree,
3109                         tvb,
3110                         offset,
3111                         hf_rtps_param_type_name,
3112                         little_endian,
3113                         NULL,           /* No label, use hf param */
3114                         buffer,
3115                         MAX_PARAM_SIZE);
3116         break;
3117
3118
3119
3120       /* 0...2...........7...............15.............23...............31
3121        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
3122        * | PID_XXXXXXXXXXX               |            0x0004             | 
3123        * +---------------+---------------+---------------+---------------+
3124        * |    long              port                                     |
3125        * +---------------+---------------+---------------+---------------+
3126        */
3127       case PID_METATRAFFIC_MULTICAST_PORT:
3128       case PID_METATRAFFIC_UNICAST_PORT:
3129       case PID_DEFAULT_UNICAST_PORT:
3130         ENSURE_LENGTH(4);
3131         rtps_util_add_port(rtps_parameter_tree,
3132                         tvb,
3133                         offset,
3134                         little_endian, 
3135                         "port",
3136                         buffer,
3137                         MAX_PARAM_SIZE);
3138         break;
3139         
3140         
3141
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        * +---------------+---------------+---------------+---------------+
3148        */
3149       case PID_DEFAULT_EXPECTS_INLINE_QOS:
3150         ENSURE_LENGTH(1);
3151         rtps_util_add_boolean(rtps_parameter_tree,
3152                         tvb,
3153                         offset,
3154                         "inline_qos",
3155                         buffer,
3156                         MAX_PARAM_SIZE);
3157         break;
3158
3159       /* 0...2...........7...............15.............23...............31
3160        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
3161        * | PID_XXXXXXXXXXX               |            length             | 
3162        * +---------------+---------------+---------------+---------------+
3163        * |    unsigned long     ip_address                               |
3164        * +---------------+---------------+---------------+---------------+
3165        */
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,
3171                         tvb,
3172                         offset,
3173                         little_endian,
3174                         "address",
3175                         buffer,
3176                         MAX_PARAM_SIZE);
3177         break;
3178
3179
3180
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        * +---------------+---------------+---------------+---------------+
3187        */
3188       case PID_PROTOCOL_VERSION: {
3189         guint8 major = 0;
3190         guint8 minor = 0;
3191
3192         ENSURE_LENGTH(2);
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,
3197                         tvb,
3198                         offset,
3199                         param_length,
3200                         "protocolVersion: %s", 
3201                         buffer);
3202         break;
3203       }
3204
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        * +---------------+---------------+---------------+---------------+
3211        */
3212       case PID_VENDOR_ID:
3213         ENSURE_LENGTH(2);
3214         rtps_util_add_vendor_id(NULL,
3215                         tvb,
3216                         offset,
3217                         buffer,
3218                         MAX_PARAM_SIZE);
3219         proto_tree_add_text(rtps_parameter_tree,
3220                         tvb,
3221                         offset,
3222                         2,
3223                         "vendorId: %s", 
3224                         buffer);
3225
3226         break;
3227
3228
3229       /* 0...2...........7...............15.............23...............31
3230        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
3231        * | PID_RELIABILITY               |            0x0004             | 
3232        * +---------------+---------------+---------------+---------------+
3233        * |    unsigned long     kind                                     |
3234        * +---------------+---------------+---------------+---------------+
3235        */
3236       case PID_RELIABILITY_OFFERED: /* Deprecated */
3237       case PID_RELIABILITY:
3238         ENSURE_LENGTH(4);
3239         rtps_util_add_kind_qos(rtps_parameter_tree,
3240                         tvb,
3241                         offset,
3242                         little_endian,
3243                         "kind",
3244                         reliability_qos_vals,
3245                         buffer,
3246                         MAX_PARAM_SIZE);
3247         
3248         /* Older version of the protocol (and for PID_RELIABILITY_OFFERED)
3249          * this parameter was carrying also a NtpTime called
3250          * 'maxBlockingTime'.
3251          */
3252         if (octects_to_next_header == 12) {
3253           rtps_util_add_ntp_time(rtps_parameter_tree,
3254                         tvb,
3255                         offset + 4,
3256                         little_endian,
3257                         "maxBlockingTime",
3258                         NULL,
3259                         0);
3260         }
3261         break;
3262
3263
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.
3275        * 
3276        */
3277       case PID_LIVELINESS_OFFERED: /* Deprecated */
3278       case PID_LIVELINESS:
3279         ENSURE_LENGTH(12);
3280         rtps_util_add_liveliness_qos(rtps_parameter_tree,
3281                         tvb,
3282                         offset,
3283                         little_endian,
3284                         buffer,
3285                         MAX_PARAM_SIZE);
3286         break;
3287
3288
3289       /* 0...2...........7...............15.............23...............31
3290        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
3291        * | PID_DURABILITY                |            0x0004             | 
3292        * +---------------+---------------+---------------+---------------+
3293        * |    unsigned long     kind                                     |
3294        * +---------------+---------------+---------------+---------------+
3295        */
3296       case PID_DURABILITY:
3297         ENSURE_LENGTH(4);
3298         rtps_util_add_kind_qos(rtps_parameter_tree,
3299                         tvb,
3300                         offset,
3301                         little_endian,
3302                         "durability",
3303                         durability_qos_vals,
3304                         buffer,
3305                         MAX_PARAM_SIZE);
3306         break;
3307
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        * +---------------+---------------+---------------+---------------+
3326        */
3327       case PID_DURABILITY_SERVICE:
3328         ENSURE_LENGTH(28);
3329         rtps_util_add_durability_service_qos(rtps_parameter_tree,
3330                         tvb,
3331                         offset,
3332                         little_endian,
3333                         buffer,
3334                         MAX_PARAM_SIZE);
3335         break;
3336
3337
3338       /* 0...2...........7...............15.............23...............31
3339        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
3340        * | PID_OWNERSHIP                 |            0x0004             | 
3341        * +---------------+---------------+---------------+---------------+
3342        * |    unsigned long     kind                                     |
3343        * +---------------+---------------+---------------+---------------+
3344        */
3345       case PID_OWNERSHIP_OFFERED: /* Deprecated */
3346       case PID_OWNERSHIP:
3347         ENSURE_LENGTH(4);
3348         rtps_util_add_kind_qos(rtps_parameter_tree,
3349                         tvb,
3350                         offset,
3351                         little_endian,
3352                         "kind",
3353                         ownership_qos_vals,
3354                         buffer,
3355                         MAX_PARAM_SIZE);
3356         break;
3357
3358
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        * +---------------+---------------+---------------+---------------+
3367        */
3368       case PID_PRESENTATION_OFFERED: /* Deprecated */
3369       case PID_PRESENTATION:
3370         ENSURE_LENGTH(6);
3371         g_strlcpy(buffer, "{ ", MAX_PARAM_SIZE);
3372         rtps_util_add_kind_qos(rtps_parameter_tree,
3373                         tvb,
3374                         offset,
3375                         little_endian,
3376                         "access_scope",
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,
3382                         tvb,
3383                         offset+4,
3384                         "coherent_access",
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,
3389                         tvb,
3390                         offset+4,
3391                         "ordered_access",
3392                         buffer+strlen(buffer),
3393                         MAX_PARAM_SIZE-strlen(buffer));
3394         g_strlcat(buffer, " }", MAX_PARAM_SIZE);
3395         break;
3396
3397
3398       /* 0...2...........7...............15.............23...............31
3399        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
3400        * | PID_DEADLINE                  |            0x0008             | 
3401        * +---------------+---------------+---------------+---------------+
3402        * |    long              NtpTime.seconds                          |
3403        * +---------------+---------------+---------------+---------------+
3404        * |    unsigned long     NtpTime.fraction                         |
3405        * +---------------+---------------+---------------+---------------+
3406        */
3407       case PID_DEADLINE_OFFERED: /* Deprecated */
3408       case PID_DEADLINE:
3409         ENSURE_LENGTH(8);
3410         rtps_util_add_ntp_time(rtps_parameter_tree,
3411                         tvb,
3412                         offset,
3413                         little_endian,
3414                         "period",
3415                         buffer,
3416                         MAX_PARAM_SIZE);
3417         break;
3418
3419       /* 0...2...........7...............15.............23...............31
3420        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
3421        * | PID_DESTINATION_ORDER         |            0x0004             | 
3422        * +---------------+---------------+---------------+---------------+
3423        * |    unsigned long     kind                                     |
3424        * +---------------+---------------+---------------+---------------+
3425        */
3426       case PID_DESTINATION_ORDER_OFFERED: /* Deprecated */
3427       case PID_DESTINATION_ORDER:
3428         ENSURE_LENGTH(4);
3429         rtps_util_add_kind_qos(rtps_parameter_tree,
3430                         tvb,
3431                         offset,
3432                         little_endian,
3433                         "kind",
3434                         destination_order_qos_vals,
3435                         buffer,
3436                         MAX_PARAM_SIZE);
3437         break;
3438
3439
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        * +---------------+---------------+---------------+---------------+
3448        */
3449       case PID_LATENCY_BUDGET_OFFERED:
3450       case PID_LATENCY_BUDGET:
3451         ENSURE_LENGTH(8);
3452         rtps_util_add_ntp_time(rtps_parameter_tree,
3453                         tvb,
3454                         offset,
3455                         little_endian,
3456                         "duration",
3457                         buffer,
3458                         MAX_PARAM_SIZE);
3459         break;
3460
3461
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        * +---------------+---------------+---------------+---------------+
3472        * |                              ...                              |
3473        * +---------------+---------------+---------------+---------------+
3474        * The value is a sequence of strings.
3475        */
3476       case PID_PARTITION_OFFERED:  /* Deprecated */
3477       case PID_PARTITION: 
3478         ENSURE_LENGTH(4);
3479         rtps_util_add_seq_string(rtps_parameter_tree,
3480                         tvb,
3481                         offset,
3482                         little_endian,
3483                         param_length,
3484                         "name",
3485                         buffer,
3486                         MAX_PARAM_SIZE);
3487         break;
3488
3489       /* 0...2...........7...............15.............23...............31
3490        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
3491        * | PID_LIFESPAN                  |            0x0008             | 
3492        * +---------------+---------------+---------------+---------------+
3493        * |    long              NtpTime.seconds                          |
3494        * +---------------+---------------+---------------+---------------+
3495        * |    unsigned long     NtpTime.fraction                         |
3496        * +---------------+---------------+---------------+---------------+
3497        */
3498       case PID_LIFESPAN:
3499         ENSURE_LENGTH(8);
3500         rtps_util_add_ntp_time(rtps_parameter_tree,
3501                         tvb,
3502                         offset,
3503                         little_endian,
3504                         "duration",
3505                         buffer,
3506                         MAX_PARAM_SIZE);
3507
3508         break;
3509
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        * +---------------+---------------+---------------+---------------+
3518        * |                              ...                              |
3519        * +---------------+---------------+---------------+---------------+
3520        */
3521       case PID_USER_DATA:
3522         ENSURE_LENGTH(4); 
3523         rtps_util_add_seq_octets(rtps_parameter_tree,
3524                         tvb,
3525                         offset,
3526                         little_endian,
3527                         param_length,
3528                         hf_rtps_param_user_data,
3529                         buffer,
3530                         MAX_PARAM_SIZE);
3531
3532         break;
3533
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        * +---------------+---------------+---------------+---------------+
3542        * |                              ...                              |
3543        * +---------------+---------------+---------------+---------------+
3544        */
3545       case PID_GROUP_DATA: 
3546         ENSURE_LENGTH(4);
3547         rtps_util_add_seq_octets(rtps_parameter_tree,
3548                         tvb,
3549                         offset,
3550                         little_endian,
3551                         param_length,
3552                         hf_rtps_param_group_data,
3553                         buffer,
3554                         MAX_PARAM_SIZE);
3555         break;
3556
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        * +---------------+---------------+---------------+---------------+
3565        * |                              ...                              |
3566        * +---------------+---------------+---------------+---------------+
3567        */
3568      case PID_TOPIC_DATA: 
3569         ENSURE_LENGTH(4);
3570         rtps_util_add_seq_octets(rtps_parameter_tree,
3571                         tvb,
3572                         offset,
3573                         little_endian,
3574                         param_length,
3575                         hf_rtps_param_topic_data,
3576                         buffer,
3577                         MAX_PARAM_SIZE);
3578         break;
3579
3580       /* 0...2...........7...............15.............23...............31
3581        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
3582        * | PID_UNICAST_LOCATOR           |            0x0018             | 
3583        * +---------------+---------------+---------------+---------------+
3584        * |    long              kind                                     |
3585        * +---------------+---------------+---------------+---------------+
3586        * |    long              port                                     |
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        * +---------------+---------------+---------------+---------------+
3596        */
3597      case PID_UNICAST_LOCATOR: 
3598         ENSURE_LENGTH(24);
3599         rtps_util_add_locator_t(rtps_parameter_tree,
3600                         tvb,
3601                         offset,
3602                         little_endian,
3603                         "locator",
3604                         buffer,
3605                         MAX_PARAM_SIZE);
3606
3607         break;
3608
3609       /* 0...2...........7...............15.............23...............31
3610        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
3611        * | PID_MULTICAST_LOCATOR         |            0x0018             | 
3612        * +---------------+---------------+---------------+---------------+
3613        * |    long              kind                                     |
3614        * +---------------+---------------+---------------+---------------+
3615        * |    long              port                                     |
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        * +---------------+---------------+---------------+---------------+
3625        */
3626      case PID_MULTICAST_LOCATOR: 
3627         ENSURE_LENGTH(24);
3628         rtps_util_add_locator_t(rtps_parameter_tree,
3629                         tvb,
3630                         offset,
3631                         little_endian,
3632                         "locator",
3633                         buffer,
3634                         MAX_PARAM_SIZE);
3635
3636         break;
3637
3638       /* 0...2...........7...............15.............23...............31
3639        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
3640        * | PID_DEFAULT_UNICAST_LOCATOR   |            0x0018             | 
3641        * +---------------+---------------+---------------+---------------+
3642        * |    long              kind                                     |
3643        * +---------------+---------------+---------------+---------------+
3644        * |    long              port                                     |
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        * +---------------+---------------+---------------+---------------+
3654        */
3655      case PID_DEFAULT_UNICAST_LOCATOR: 
3656         ENSURE_LENGTH(24);
3657         rtps_util_add_locator_t(rtps_parameter_tree,
3658                         tvb,
3659                         offset,
3660                         little_endian,
3661                         "locator",
3662                         buffer,
3663                         MAX_PARAM_SIZE);
3664
3665         break;
3666
3667       /* 0...2...........7...............15.............23...............31
3668        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
3669        * | PID_METATRAFFIC_UNICAST_LOC...|            0x0018             | 
3670        * +---------------+---------------+---------------+---------------+
3671        * |    long              kind                                     |
3672        * +---------------+---------------+---------------+---------------+
3673        * |    long              port                                     |
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        * +---------------+---------------+---------------+---------------+
3683        */
3684      case PID_METATRAFFIC_UNICAST_LOCATOR: 
3685         ENSURE_LENGTH(24);
3686         rtps_util_add_locator_t(rtps_parameter_tree,
3687                         tvb,
3688                         offset,
3689                         little_endian,
3690                         "locator",
3691                         buffer,
3692                         MAX_PARAM_SIZE);
3693
3694         break;
3695
3696       /* 0...2...........7...............15.............23...............31
3697        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
3698        * | PID_METATRAFFIC_MULTICAST_L...|            0x0018             | 
3699        * +---------------+---------------+---------------+---------------+
3700        * |    long              kind                                     |
3701        * +---------------+---------------+---------------+---------------+
3702        * |    long              port                                     |
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        * +---------------+---------------+---------------+---------------+
3712        */
3713      case PID_METATRAFFIC_MULTICAST_LOCATOR: 
3714         ENSURE_LENGTH(24);
3715         rtps_util_add_locator_t(rtps_parameter_tree,
3716                         tvb,
3717                         offset,
3718                         little_endian,
3719                         "locator",
3720                         buffer,
3721                         MAX_PARAM_SIZE);
3722
3723         break;
3724
3725       /* 0...2...........7...............15.............23...............31
3726        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
3727        * | PID_PARTICIPANT_MANUAL_LIVE...|            0x0004             | 
3728        * +---------------+---------------+---------------+---------------+
3729        * |    long              livelinessEpoch                          |
3730        * +---------------+---------------+---------------+---------------+
3731        */
3732       case PID_PARTICIPANT_BUILTIN_ENDPOINTS:
3733       case PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT:
3734         ENSURE_LENGTH(4);
3735         rtps_util_add_long(rtps_parameter_tree,
3736                         tvb,
3737                         offset,
3738                         -1,     /* No protocol ID, use label below */
3739                         little_endian,
3740                         TRUE,   /* Is Hex ? */
3741                         FALSE,  /* Is Signed ? */
3742                         "value",
3743                         buffer,
3744                         MAX_PARAM_SIZE);
3745         break;
3746
3747       /* 0...2...........7...............15.............23...............31
3748        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
3749        * | PID_HISTORY                   |            0x0004             | 
3750        * +---------------+---------------+---------------+---------------+
3751        * |    long              kind                                     |
3752        * +---------------+---------------+---------------+---------------+
3753        * |    long              depth                                    |
3754        * +---------------+---------------+---------------+---------------+
3755        */
3756       case PID_HISTORY:
3757         ENSURE_LENGTH(8);
3758         g_strlcpy(buffer, "{ ", MAX_PARAM_SIZE);
3759         rtps_util_add_kind_qos(rtps_parameter_tree,
3760                         tvb,
3761                         offset,
3762                         little_endian,
3763                         "kind",
3764                         history_qos_vals,
3765                         buffer+strlen(buffer),
3766                         MAX_PARAM_SIZE-strlen(buffer));
3767         g_strlcat(buffer, ", ", MAX_PARAM_SIZE);
3768                         
3769         rtps_util_add_long(rtps_parameter_tree,
3770                         tvb,
3771                         offset+4,
3772                         -1,     /* No protocol ID, use label below */
3773                         little_endian,
3774                         FALSE,  /* Is Hex ? */
3775                         TRUE,  /* Is Signed ? */
3776                         "depth",
3777                         buffer + strlen(buffer),
3778                         MAX_PARAM_SIZE-strlen(buffer));
3779         g_strlcat(buffer, " }", MAX_PARAM_SIZE);
3780         break;
3781
3782
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        * +---------------+---------------+---------------+---------------+
3793        */
3794       case PID_RESOURCE_LIMIT:
3795         ENSURE_LENGTH(12);
3796         g_strlcpy(buffer, "{ ", MAX_PARAM_SIZE);
3797         rtps_util_add_long(rtps_parameter_tree,
3798                         tvb,
3799                         offset,
3800                         -1,     /* No protocol ID, use label below */
3801                         little_endian,
3802                         FALSE,  /* Is Hex ? */
3803                         TRUE,  /* Is Signed ? */
3804                         "max_samples",
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,
3809                         tvb,
3810                         offset+4,
3811                         -1,     /* No protocol ID, use label below */
3812                         little_endian,
3813                         FALSE,  /* Is Hex ? */
3814                         TRUE,  /* Is Signed ? */
3815                         "max_instances",
3816                         buffer + strlen(buffer),
3817                         MAX_PARAM_SIZE-strlen(buffer));
3818         g_strlcat(buffer, ", ", MAX_PARAM_SIZE);
3819                         
3820         rtps_util_add_long(rtps_parameter_tree,
3821                         tvb,
3822                         offset+8,
3823                         -1,     /* No protocol ID, use label below */
3824                         little_endian,
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);
3831         break;
3832
3833
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        * +---------------+---------------+---------------+---------------+
3842        * |                              ...                              |
3843        * +---------------+---------------+---------------+---------------+
3844        * |    unsigned long     String2.length                           |
3845        * +---------------+---------------+---------------+---------------+
3846        * |   str2[0]     |   str2[1]     |   str2[2]     |   str2[3]     |
3847        * +---------------+---------------+---------------+---------------+
3848        * |                              ...                              |
3849        * +---------------+---------------+---------------+---------------+
3850        * |    unsigned long     String3.length                           |
3851        * +---------------+---------------+---------------+---------------+
3852        * |   str3[0]     |   str3[1]     |   str3[2]     |   str3[3]     |
3853        * +---------------+---------------+---------------+---------------+
3854        * |                              ...                              |
3855        * +---------------+---------------+---------------+---------------+
3856        * |    unsigned long     String4.length                           |
3857        * +---------------+---------------+---------------+---------------+
3858        * |   str4[0]     |   str4[1]     |   str4[2]     |   str4[3]     |
3859        * +---------------+---------------+---------------+---------------+
3860        * |                              ...                              |
3861        * +---------------+---------------+---------------+---------------+
3862        * |                              ...                              |
3863        * |                      Filter Parameters                        |
3864        * |                              ...                              |
3865        * +---------------+---------------+---------------+---------------+
3866        * 
3867        * String1: ContentFilterName
3868        * String2: RelatedTopicName
3869        * String3: FilterName
3870        * String4: FilterExpression
3871        * FilterParameters: sequence of Strings
3872        *
3873        * Note: those strings starts all to a word-aligned (4 bytes) offset
3874        */
3875       case PID_CONTENT_FILTER_PROPERTY: {
3876         guint32 temp_offset = offset;
3877         ENSURE_LENGTH(20);
3878         temp_offset = rtps_util_add_string(rtps_parameter_tree,
3879                         tvb,
3880                         temp_offset,
3881                         hf_rtps_param_content_filter_name,
3882                         little_endian,
3883                         NULL,           /* No label, use hf param */
3884                         buffer,
3885                         MAX_PARAM_SIZE);
3886         temp_offset = rtps_util_add_string(rtps_parameter_tree,
3887                         tvb,
3888                         temp_offset,
3889                         hf_rtps_param_related_topic_name,
3890                         little_endian,
3891                         NULL,
3892                         NULL,
3893                         0);
3894         temp_offset = rtps_util_add_string(rtps_parameter_tree,
3895                         tvb,
3896                         temp_offset,
3897                         hf_rtps_param_filter_name,
3898                         little_endian,
3899                         NULL,
3900                         NULL,
3901                         0);
3902         temp_offset = rtps_util_add_string(rtps_parameter_tree,
3903                         tvb,
3904                         temp_offset,
3905                         -1,
3906                         little_endian,
3907                         "filterExpression",
3908                         NULL,
3909                         0);
3910         temp_offset = rtps_util_add_seq_string(rtps_parameter_tree,
3911                         tvb,
3912                         temp_offset,
3913                         little_endian,
3914                         param_length,
3915                         "filterParameters",
3916                         NULL,
3917                         0);
3918         break;
3919       }
3920
3921       /* 0...2...........7...............15.............23...............31
3922        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
3923        * | PID_PROPERTY_LIST             |            length             | 
3924        * +---------------+---------------+---------------+---------------+
3925        * |    unsigned long     Seq.Length                               |
3926        * +---------------+---------------+---------------+---------------+
3927        * |                              ...                              |
3928        * |                           Property 1                          |
3929        * |                              ...                              |
3930        * +---------------+---------------+---------------+---------------+
3931        * |                              ...                              |
3932        * |                           Property 2                          |
3933        * |                              ...                              |
3934        * +---------------+---------------+---------------+---------------+
3935        * |                              ...                              |
3936        * |                           Property n                          |
3937        * |                              ...                              |
3938        * +---------------+---------------+---------------+---------------+
3939        * 
3940        * IDL:
3941        *    struct PROPERTY {
3942        *        String Name;
3943        *        String Value;
3944        *    };
3945        *
3946        *    struct PROPERTY_LIST {
3947        *        Sequence<PROPERTY> PropertyList;
3948        *    };
3949        *
3950        */
3951       case PID_PROPERTY_LIST:
3952         ENSURE_LENGTH(4);
3953         {
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);
3960           if (seq_size > 0) {
3961             proto_tree_add_text(rtps_parameter_tree,
3962                         tvb,
3963                         offset,
3964                         0,
3965                      /*  123456789012345678901234567890|123456789012345678901234567890 */
3966                         "        Property Name         |       Property Value");
3967
3968             proto_tree_add_text(rtps_parameter_tree,
3969                         tvb,
3970                         offset,
3971                         0,
3972                      /*  123456789012345678901234567890|123456789012345678901234567890 */
3973                         "------------------------------|------------------------------");
3974
3975             temp_offset = offset+4;
3976             while(seq_size-- > 0) {
3977               prev_offset = temp_offset;
3978               temp_offset = rtps_util_add_string(NULL,
3979                           tvb,
3980                           temp_offset,
3981                           -1,
3982                           little_endian,
3983                           NULL,
3984                           tempName,
3985                           MAX_PARAM_SIZE);
3986               temp_offset = rtps_util_add_string(NULL,
3987                           tvb,
3988                           temp_offset,
3989                           -1,
3990                           little_endian,
3991                           NULL,
3992                           tempValue,
3993                           MAX_PARAM_SIZE);
3994               proto_tree_add_text(rtps_parameter_tree,
3995                           tvb,
3996                           prev_offset,
3997                           temp_offset - prev_offset,
3998                           "%-29s | %-29s", 
3999                           tempName,
4000                           tempValue);
4001             }
4002           }
4003         }
4004         break;
4005
4006       /* 0...2...........7...............15.............23...............31
4007        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
4008        * | PID_FILTER_SIGNATURE          |            length             | 
4009        * +---------------+---------------+---------------+---------------+
4010        * |                              ...                              |
4011        * +---------------+---------------+---------------+---------------+
4012        * 
4013        * IDL:
4014        *     struct CONTENT_FILTER_SIGNATURE {
4015        *         sequence<long>  filterBitmap;
4016        *         sequence<FILTER_SIGNATURE, 4> filterSignature;
4017        *     }
4018        *
4019        * where:
4020        *     struct FILTER_SIGNATURE {
4021        *         long filterSignature[4];
4022        *     }
4023        */
4024       case PID_FILTER_SIGNATURE: {
4025         guint32 temp_offset = offset;
4026         guint32 prev_offset;
4027         guint32 fs_elem;
4028         guint32 fs[4];
4029         ENSURE_LENGTH(8);
4030         
4031         /* Dissect filter bitmap */
4032         temp_offset = rtps_util_add_seq_ulong(rtps_parameter_tree,
4033                         tvb,
4034                         offset,
4035                         little_endian,
4036                         param_length,
4037                         TRUE,           /* is_hex */
4038                         FALSE,          /* filterSignature: is_signed */
4039                         "filterBitmap");
4040         
4041         /* Dissect sequence of FILTER_SIGNATURE */
4042         fs_elem = NEXT_guint32(tvb, temp_offset, little_endian);
4043         temp_offset += 4;
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);
4048             temp_offset += 4;
4049             fs[1] = NEXT_guint32(tvb, temp_offset, little_endian);
4050             temp_offset += 4;
4051             fs[2] = NEXT_guint32(tvb, temp_offset, little_endian);
4052             temp_offset += 4;
4053             fs[3] = NEXT_guint32(tvb, temp_offset, little_endian);
4054             temp_offset += 4;
4055             proto_tree_add_text(rtps_parameter_tree,
4056                           tvb,
4057                           prev_offset,
4058                           temp_offset - prev_offset,
4059                           "filterSignature: %08x %08x %08x %08x",
4060                           fs[0], fs[1], fs[2], fs[3]);
4061         }
4062         
4063         break;
4064       }
4065
4066
4067       /* 0...2...........7...............15.............23...............31
4068        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
4069        * | PID_COHERENT_SET              |            length             | 
4070        * +---------------+---------------+---------------+---------------+
4071        * |                                                               |
4072        * + SequenceNumber seqNumber                                      +
4073        * |                                                               |
4074        * +---------------+---------------+---------------+---------------+
4075        */
4076       case PID_COHERENT_SET:
4077         ENSURE_LENGTH(8);
4078         rtps_util_add_seq_number(rtps_parameter_tree,
4079                         tvb,
4080                         offset,
4081                         little_endian,
4082                         "sequenceNumber");
4083         break;
4084
4085       /* 0...2...........7...............15.............23...............31
4086        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
4087        * | PID_TYPECODE                  |            length             | 
4088        * +---------------+---------------+---------------+---------------+
4089        * |                                                               |
4090        * +                    Type code description                      +
4091        * |                                                               |
4092        * +---------------+---------------+---------------+---------------+
4093        */
4094       case PID_TYPECODE:
4095         rtps_util_add_typecode(rtps_parameter_tree,
4096                         tvb,
4097                         offset,
4098                         little_endian,
4099                         0,      /* indent level */
4100                         0,      /* isPointer */
4101                         -1,     /* bitfield */
4102                         0,      /* isKey */
4103                         offset,
4104                         NULL,   /* name */
4105                         -1,     /* not a seq field */
4106                         NULL,   /* not an array */
4107                         0);     /* ndds 4.0 hack: init to false */
4108         break;
4109
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        * +---------------+---------------+---------------+---------------+
4120        */
4121       case PID_PARTICIPANT_GUID:
4122         ENSURE_LENGTH(12);
4123         rtps_util_add_generic_guid(rtps_parameter_tree,
4124                         tvb,
4125                         offset,
4126                         "Participant GUID",
4127                         buffer,
4128                         MAX_PARAM_SIZE);
4129         
4130         break;
4131
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        * +---------------+---------------+---------------+---------------+
4138        */
4139       case PID_PARTICIPANT_ENTITY_ID:
4140         ENSURE_LENGTH(4);
4141         rtps_util_add_generic_entity_id(rtps_parameter_tree,
4142                         tvb,
4143                         offset,
4144                         "Participant entity ID",
4145                         buffer,
4146                         MAX_PARAM_SIZE);
4147         break;
4148
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        * +---------------+---------------+---------------+---------------+
4159        */
4160       case PID_GROUP_GUID:
4161         ENSURE_LENGTH(12);
4162         rtps_util_add_generic_guid(rtps_parameter_tree,
4163                         tvb,
4164                         offset,
4165                         "Group GUID",
4166                         buffer,
4167                         MAX_PARAM_SIZE);
4168         
4169         break;
4170
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        * +---------------+---------------+---------------+---------------+
4177        */
4178       case PID_GROUP_ENTITY_ID: 
4179         ENSURE_LENGTH(4);
4180
4181         rtps_util_add_generic_entity_id(rtps_parameter_tree,
4182                         tvb,
4183                         offset,
4184                         "Group entity ID",
4185                         buffer,
4186                         MAX_PARAM_SIZE);
4187         
4188         break;
4189
4190
4191       /* ==================================================================
4192        * Here are all the deprecated items.
4193        */
4194
4195       case PID_PERSISTENCE:
4196         ENSURE_LENGTH(8);
4197         rtps_util_add_ntp_time(rtps_parameter_tree,
4198                         tvb,
4199                         offset,
4200                         little_endian,
4201                         "persistence",
4202                         buffer,
4203                         MAX_PARAM_SIZE);
4204         break;
4205
4206       case PID_TYPE_CHECKSUM:
4207         ENSURE_LENGTH(4);
4208         rtps_util_add_long(rtps_parameter_tree,
4209                         tvb,
4210                         offset,
4211                         -1,
4212                         little_endian,
4213                         TRUE,   /* Is Hex? */
4214                         FALSE,  /* Is signed ? */
4215                         "checksum",
4216                         buffer,
4217                         MAX_PARAM_SIZE);
4218         break;
4219
4220       case PID_EXPECTS_ACK:
4221         ENSURE_LENGTH(1);
4222         rtps_util_add_boolean(rtps_parameter_tree,
4223                         tvb,
4224                         offset,
4225                         "expectsAck",
4226                         buffer,
4227                         MAX_PARAM_SIZE);
4228         break;
4229
4230       case PID_MANAGER_KEY: {
4231         int i = 0;
4232         char sep = ':';
4233         guint32 manager_key;
4234
4235         buffer[0] = '\0';
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),
4240                         "%c 0x%08x",
4241                         sep,
4242                         manager_key);
4243           proto_tree_add_text(rtps_parameter_tree, 
4244                         tvb, 
4245                         offset, 
4246                         param_length,
4247                         "Key[%d]: 0x%X", i, manager_key);
4248           ++i;
4249           offset +=4;
4250           sep = ',';
4251           param_length -= 4; /* decrement count */
4252         }
4253         offset += param_length;
4254         break;
4255       }
4256
4257
4258       case PID_RECV_QUEUE_SIZE:
4259       case PID_SEND_QUEUE_SIZE:
4260         ENSURE_LENGTH(4);
4261         rtps_util_add_long(rtps_parameter_tree,
4262                         tvb,
4263                         offset,
4264                         -1,
4265                         little_endian,
4266                         TRUE,   /* Is Hex? */
4267                         FALSE,  /* Is signed ? */
4268                         "queueSize",
4269                         buffer,
4270                         MAX_PARAM_SIZE);
4271         break;
4272
4273
4274       case PID_VARGAPPS_SEQUENCE_NUMBER_LAST:
4275         ENSURE_LENGTH(4);
4276         rtps_util_add_seq_number(rtps_parameter_tree,
4277                         tvb,
4278                         offset,
4279                         little_endian,
4280                         "sequenceNumberLast");
4281         break;
4282
4283       case PID_SENTINEL:
4284       /* PID_SENTINEL should ignore any value of parameter length */
4285         break;
4286
4287
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
4290        * parameters.
4291        */
4292       /* 0...2...........7...............15.............23...............31
4293        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
4294        * | <pid_id>                      |            0x0000             | 
4295        * +---------------+---------------+---------------+---------------+
4296       */
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);
4301
4302       case PID_PAD:
4303       case PID_RELIABILITY_ENABLED:
4304       default:
4305         if (param_length > 0) {
4306           proto_tree_add_text(rtps_parameter_tree,
4307                         tvb,
4308                         offset,
4309                         param_length,
4310                         "parameterData");
4311         }
4312     } /* End switch */
4313
4314     if (buffer[0]) {
4315       proto_item_append_text(ti, ": %s", buffer);
4316       buffer[0] = '\0';
4317     }
4318     offset += param_length;
4319
4320   } while(parameter != PID_SENTINEL); /* for all the parameters */
4321   return offset;
4322 }
4323 #undef ENSURE_LENGTH
4324
4325
4326
4327
4328 /* *********************************************************************** */
4329 /* *                                 P A D                               * */
4330 /* *********************************************************************** */
4331 static void dissect_PAD(tvbuff_t *tvb, 
4332                 gint offset, 
4333                 guint8 flags, 
4334                 gboolean little_endian,
4335                 int octects_to_next_header, 
4336                 proto_tree *tree) {
4337   /* 0...2...........7...............15.............23...............31
4338    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
4339    * |   PAD         |X|X|X|X|X|X|X|E|      octetsToNextHeader       | 
4340    * +---------------+---------------+---------------+---------------+
4341    */
4342   rtps_util_decode_flags(tree, tvb, offset + 1, flags, PAD_FLAGS);
4343
4344   if (octects_to_next_header != 0) {
4345     proto_tree_add_uint_format(tree,
4346                         hf_rtps_sm_octets_to_next_header,
4347                         tvb, 
4348                         offset + 2, 
4349                         2,
4350                         octects_to_next_header,
4351                         "octectsToNextHeader: %u (Error: should be ZERO)",
4352                         octects_to_next_header);
4353     return;
4354   }
4355
4356   proto_tree_add_item(tree, 
4357                         hf_rtps_sm_octets_to_next_header,
4358                         tvb, 
4359                         offset + 2, 
4360                         2, 
4361                         little_endian);
4362 }
4363
4364
4365
4366
4367
4368 /* *********************************************************************** */
4369 /* *                               D A T A                               * */
4370 /* *********************************************************************** */
4371 static void dissect_DATA(tvbuff_t *tvb, 
4372                 gint offset, 
4373                 guint8 flags, 
4374                 gboolean little_endian,
4375                 int octects_to_next_header, 
4376                 proto_tree *tree,
4377                 const char ** sm_data) {        /* May be set to some known values */
4378   /* RTPS 1.0/1.1:
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    * +---------------+---------------+---------------+---------------+
4393    * |                                                               |
4394    * + SequenceNumber writerSeqNumber                                +
4395    * |                                                               |
4396    * +---------------+---------------+---------------+---------------+
4397    * |                                                               |
4398    * ~ ParameterSequence parameters [only if P==1]                   ~
4399    * |                                                               |
4400    * +---------------+---------------+---------------+---------------+
4401    * Note: on RTPS 1.0, flag U is not present
4402    *
4403    * RTPS 1.2:
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    * +---------------+---------------+---------------+---------------+
4412    * |                                                               |
4413    * + KeyHashPrefix  keyHashPrefix [only if H==1]                   +
4414    * |                                                               |
4415    * +---------------+---------------+---------------+---------------+
4416    * | KeyHashSuffix  keyHashSuffix                                  |
4417    * +---------------+---------------+---------------+---------------+
4418    * |                                                               |
4419    * + SequenceNumber writerSeqNum                                   +
4420    * |                                                               |
4421    * +---------------+---------------+---------------+---------------+
4422    * |                                                               |
4423    * ~ ParameterList inlineQos [only if Q==1]                        ~
4424    * |                                                               |
4425    * +---------------+---------------+---------------+---------------+
4426    * |                                                               | 
4427    * ~ SerializedData serializedData [only if D==1]                  ~
4428    * |                                                               |
4429    * +---------------+---------------+---------------+---------------+
4430    * Notes:
4431    *   - inlineQos is NEW
4432    *   - serializedData is equivalent to the old 'parameters'
4433    */
4434   int min_len;
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);
4439
4440
4441   /* Calculates the minimum length for this submessage */
4442   min_len = 20;
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;
4446
4447   if (octects_to_next_header < min_len) {
4448     proto_tree_add_uint_format(tree, 
4449                         hf_rtps_sm_octets_to_next_header,
4450                         tvb, 
4451                         offset+2, 
4452                         2, 
4453                         octects_to_next_header,
4454                         "octectsToNextHeader: %u (Error: should be >= %u)",
4455                         octects_to_next_header, 
4456                         min_len);
4457     return;
4458   }
4459   proto_tree_add_item(tree, 
4460                         hf_rtps_sm_octets_to_next_header,
4461                         tvb, 
4462                         offset + 2, 
4463                         2, 
4464                         little_endian);
4465   offset += 4;
4466
4467
4468   /* readerEntityId */
4469   is_builtin_entity |= rtps_util_add_entity_id(tree,
4470                         tvb,
4471                         offset,
4472                         hf_rtps_sm_rdentity_id,
4473                         hf_rtps_sm_rdentity_id_key,
4474                         hf_rtps_sm_rdentity_id_kind,
4475                         ett_rtps_rdentity,
4476                         "readerEntityId",
4477                         NULL);
4478   offset += 4;
4479
4480   /* writerEntityId */
4481   is_builtin_entity |= rtps_util_add_entity_id(tree,
4482                         tvb,
4483                         offset,
4484                         hf_rtps_sm_wrentity_id,
4485                         hf_rtps_sm_wrentity_id_key,
4486                         hf_rtps_sm_wrentity_id_kind,
4487                         ett_rtps_wrentity,
4488                         "writerEntityId",
4489                         &wid);
4490   offset += 4;
4491
4492   /* Checks for predefined declarations
4493    *
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-   (*)
4504    *
4505    * Note (*): Currently NDDS does not publish those values 
4506    */
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;
4523   }
4524
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,
4528                         tvb,
4529                         offset,
4530                         hf_rtps_sm_guid_prefix,
4531                         hf_rtps_sm_host_id,
4532                         hf_rtps_sm_app_id,
4533                         hf_rtps_sm_instance_id,
4534                         hf_rtps_sm_app_kind,
4535                         "keyHashPrefix",
4536                         NULL,
4537                         0);
4538
4539     offset += 8;
4540   } else {
4541     /* Flag H not set, use hostId, appId from the packet header */
4542   }
4543
4544   /* Complete the GUID by reading the Object ID */
4545   rtps_util_add_entity_id(tree,
4546                         tvb,
4547                         offset,
4548                         hf_rtps_sm_entity_id,
4549                         hf_rtps_sm_entity_id_key,
4550                         hf_rtps_sm_entity_id_kind,
4551                         ett_rtps_entity,
4552                         "keyHashSuffix",
4553                         NULL);
4554   offset += 4;
4555
4556   /* Sequence number */
4557   rtps_util_add_seq_number(tree,
4558                         tvb,
4559                         offset,
4560                         little_endian,
4561                         "writerSeqNumber");
4562   offset += 8;
4563
4564   /* InlineQos */
4565   if ((flags & FLAG_DATA_Q) != 0) {
4566     offset = dissect_parameter_sequence(tree, 
4567                         tvb, 
4568                         offset, 
4569                         little_endian, 
4570                         octects_to_next_header,
4571                         "inlineQos");
4572   }
4573
4574   /* SerializedData */
4575   if ((flags & FLAG_DATA_D) != 0) {
4576     if (is_builtin_entity) {
4577       offset = dissect_parameter_sequence(tree, 
4578                         tvb, 
4579                         offset, 
4580                         little_endian, 
4581                         octects_to_next_header,
4582                         "serializedData");
4583     } else {
4584       proto_tree_add_item(tree,
4585                         hf_rtps_issue_data,
4586                         tvb,
4587                         offset,
4588                         octects_to_next_header - (offset - old_offset) + 4,
4589                         little_endian);
4590     }
4591   }
4592 }
4593
4594 /* *********************************************************************** */
4595 /* *                        N O K E Y _ D A T A                          * */
4596 /* *********************************************************************** */
4597 static void dissect_NOKEY_DATA(tvbuff_t *tvb, 
4598                 gint offset, 
4599                 guint8 flags, 
4600                 gboolean little_endian,
4601                 int octects_to_next_header, 
4602                 proto_tree *tree) {
4603   /* RTPS 1.0/1.1:
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    * +---------------+---------------+---------------+---------------+
4612    * |                                                               |
4613    * + SequenceNumber writerSeqNumber                                +
4614    * |                                                               |
4615    * +---------------+---------------+---------------+---------------+
4616    * |                                                               |
4617    * ~ ParameterSequence parameters [only if P==1]                   ~
4618    * |                                                               |
4619    * +---------------+---------------+---------------+---------------+
4620    * |                                                               |
4621    * ~ UserData issueData                                            ~
4622    * |                                                               |
4623    * +---------------+---------------+---------------+---------------+
4624    *
4625    * RTPS 1.2:
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    * +---------------+---------------+---------------+---------------+
4634    * |                                                               |
4635    * + SequenceNumber writerSeqNum                                   +
4636    * |                                                               |
4637    * +---------------+---------------+---------------+---------------+
4638    * |                                                               |
4639    * ~ ParameterList inlineQos [only if Q==1]                        ~
4640    * |                                                               |
4641    * +---------------+---------------+---------------+---------------+
4642    * |                                                               |
4643    * ~ SerializedData serializedData [only if D==0]                  ~
4644    * |                                                               |
4645    * +---------------+---------------+---------------+---------------+
4646    * Notes:
4647    *   - inlineQos is equivalent to the old 'parameters'
4648    *   - serializedData is equivalent to the old 'issueData'
4649    */
4650
4651   int  min_len;
4652   gint old_offset = offset;
4653   rtps_util_decode_flags(tree, tvb, offset + 1, flags, NOKEY_DATA_FLAGS);
4654
4655
4656   /* Calculates the minimum length for this submessage */
4657   min_len = 16;
4658   if ((flags & FLAG_NOKEY_DATA_Q) != 0) min_len += 4;
4659
4660   if (octects_to_next_header < min_len) {
4661     proto_tree_add_uint_format(tree, 
4662                         hf_rtps_sm_octets_to_next_header,
4663                         tvb, 
4664                         offset+2, 
4665                         2, 
4666                         octects_to_next_header,
4667                         "octectsToNextHeader: %u (Error: should be >= %u)",
4668                         octects_to_next_header, 
4669                         min_len);
4670     return;
4671   }
4672   proto_tree_add_item(tree, 
4673                         hf_rtps_sm_octets_to_next_header,
4674                         tvb, 
4675                         offset + 2, 
4676                         2, 
4677                         little_endian);
4678   offset += 4;
4679
4680   /* readerEntityId */
4681   rtps_util_add_entity_id(tree,
4682                         tvb,
4683                         offset,
4684                         hf_rtps_sm_rdentity_id,
4685                         hf_rtps_sm_rdentity_id_key,
4686                         hf_rtps_sm_rdentity_id_kind,
4687                         ett_rtps_rdentity,
4688                         "readerEntityId",
4689                         NULL);
4690   offset += 4;
4691
4692   /* writerEntityId */
4693   rtps_util_add_entity_id(tree,
4694                         tvb,
4695                         offset,
4696                         hf_rtps_sm_wrentity_id,
4697                         hf_rtps_sm_wrentity_id_key,
4698                         hf_rtps_sm_wrentity_id_kind,
4699                         ett_rtps_wrentity,
4700                         "writerEntityId",
4701                         NULL);
4702   offset += 4;
4703
4704   /* Sequence number */
4705   rtps_util_add_seq_number(tree,
4706                         tvb,
4707                         offset,
4708                         little_endian,
4709                         "writerSeqNumber");
4710   offset += 8;
4711
4712   /* Parameters */
4713   if ((flags & FLAG_NOKEY_DATA_Q) != 0) {
4714     offset = dissect_parameter_sequence(tree, 
4715                         tvb, 
4716                         offset, 
4717                         little_endian, 
4718                         octects_to_next_header,
4719                         "inlineQos");
4720     
4721   }
4722
4723   /* Issue Data */
4724   if ((flags & FLAG_NOKEY_DATA_D) == 0) {
4725     proto_tree_add_item(tree,
4726                         hf_rtps_issue_data,
4727                         tvb,
4728                         offset,
4729                         octects_to_next_header - (offset - old_offset) + 4,
4730                         little_endian);
4731   }
4732 }
4733
4734
4735 /* *********************************************************************** */
4736 /* *                            A C K N A C K                            * */
4737 /* *********************************************************************** */
4738 static void dissect_ACKNACK(tvbuff_t *tvb, 
4739                 gint offset, 
4740                 guint8 flags, 
4741                 gboolean little_endian,
4742                 int octects_to_next_header, 
4743                 proto_tree *tree) {
4744   /* RTPS 1.0/1.1:
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    * +---------------+---------------+---------------+---------------+
4753    * |                                                               |
4754    * + Bitmap bitmap                                                 +
4755    * |                                                               |
4756    * +---------------+---------------+---------------+---------------+
4757    * | Counter count                                                 |
4758    * +---------------+---------------+---------------+---------------+
4759    * 
4760    * RTPS 1.2:
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    * +---------------+---------------+---------------+---------------+
4769    * |                                                               |
4770    * + SequenceNumberSet readerSNState                               +
4771    * |                                                               |
4772    * +---------------+---------------+---------------+---------------+
4773    * | Counter count                                                 |
4774    * +---------------+---------------+---------------+---------------+
4775    */
4776   gint original_offset; /* Offset to the readerEntityId */
4777
4778   rtps_util_decode_flags(tree, tvb, offset + 1, flags, ACKNACK_FLAGS);
4779
4780   if (octects_to_next_header < 20) {
4781     proto_tree_add_uint_format(tree, 
4782                         hf_rtps_sm_octets_to_next_header,
4783                         tvb, 
4784                         offset + 2, 
4785                         2, 
4786                         octects_to_next_header,
4787                         "octectsToNextHeader: %u (Error: should be >= 20)",
4788                         octects_to_next_header);
4789     return;
4790   }
4791   proto_tree_add_item(tree, 
4792                         hf_rtps_sm_octets_to_next_header,
4793                         tvb, 
4794                         offset + 2, 
4795                         2, 
4796                         little_endian);
4797   offset += 4;
4798   original_offset = offset;
4799
4800   /* readerEntityId */
4801   rtps_util_add_entity_id(tree,
4802                         tvb,
4803                         offset,
4804                         hf_rtps_sm_rdentity_id,
4805                         hf_rtps_sm_rdentity_id_key,
4806                         hf_rtps_sm_rdentity_id_kind,
4807                         ett_rtps_rdentity,
4808                         "readerEntityId",
4809                         NULL);
4810   offset += 4;
4811
4812   /* writerEntityId */
4813   rtps_util_add_entity_id(tree,
4814                         tvb,
4815                         offset,
4816                         hf_rtps_sm_wrentity_id,
4817                         hf_rtps_sm_wrentity_id_key,
4818                         hf_rtps_sm_wrentity_id_kind,
4819                         ett_rtps_wrentity,
4820                         "writerEntityId",
4821                         NULL);
4822   offset += 4;
4823
4824   /* Bitmap */
4825   offset = rtps_util_add_bitmap(tree,
4826                         tvb,
4827                         offset,
4828                         little_endian,
4829                         "readerSNState");
4830
4831
4832   /* RTPS 1.0 didn't have count: make sure we don't decode it wrong
4833    * in this case
4834    */
4835   if (offset + 4 == original_offset + octects_to_next_header) {
4836     /* Count is present */
4837     rtps_util_add_long(tree,
4838                   tvb,
4839                   offset,
4840                   -1,
4841                   little_endian,
4842                   FALSE,        /* Is Hex ? */
4843                   TRUE,         /* Is Signed ? */
4844                   "counter",    /* No Label, use the protocol item ID */
4845                   NULL,
4846                   0);  
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
4850      */
4851     proto_tree_add_text(tree, 
4852                         tvb, 
4853                         offset, 
4854                         octects_to_next_header - offset, 
4855                         "Packet malformed: don't know how to decode those "
4856                         "extra bytes: %d", 
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
4861      * submessage.
4862      */
4863     proto_tree_add_text(tree, 
4864                         tvb, 
4865                         original_offset, 
4866                         octects_to_next_header + original_offset,
4867                         "Packet malformed: not enough bytes to decode");
4868   }
4869
4870 }
4871
4872
4873
4874 /* *********************************************************************** */
4875 /* *                           H E A R T B E A T                         * */  
4876 /* *********************************************************************** */
4877 static void dissect_HEARTBEAT(tvbuff_t *tvb, 
4878                 gint offset, 
4879                 guint8 flags, 
4880                 gboolean little_endian,
4881                 int octects_to_next_header, 
4882                 proto_tree *tree) {
4883   /* RTPS 1.0/1.1:
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    * +---------------+---------------+---------------+---------------+
4892    * |                                                               |
4893    * + SequenceNumber firstAvailableSeqNumber                        +
4894    * |                                                               |
4895    * +---------------+---------------+---------------+---------------+
4896    * |                                                               |
4897    * + SequenceNumber lastSeqNumber                                  +
4898    * |                                                               |
4899    * +---------------+---------------+---------------+---------------+
4900    * | long counter                                                  |
4901    * +---------------+---------------+---------------+---------------+
4902    *
4903    * Notes: 
4904    *   - on RTPS 1.0, counter is not present
4905    *   - on RTPS 1.0, L flag is not present
4906    *
4907    * RTPS 1.2:
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    * +---------------+---------------+---------------+---------------+
4916    * |                                                               |
4917    * + SequenceNumber firstAvailableSeqNumber                        +
4918    * |                                                               |
4919    * +---------------+---------------+---------------+---------------+
4920    * |                                                               |
4921    * + SequenceNumber lastSeqNumber                                  +
4922    * |                                                               |
4923    * +---------------+---------------+---------------+---------------+
4924    * | Counter count                                                 |
4925    * +---------------+---------------+---------------+---------------+
4926    */
4927
4928   guint32 counter;
4929   rtps_util_decode_flags(tree, tvb, offset + 1, flags, HEARTBEAT_FLAGS);
4930
4931
4932   if (octects_to_next_header < 24) {
4933     proto_tree_add_uint_format(tree, 
4934                         hf_rtps_sm_octets_to_next_header,
4935                         tvb, 
4936                         offset+2, 
4937                         2, 
4938                         octects_to_next_header,
4939                         "octectsToNextHeader: %u (Error: should be >= 24)",
4940                         octects_to_next_header);
4941     return;
4942   }
4943   proto_tree_add_item(tree, 
4944                         hf_rtps_sm_octets_to_next_header,
4945                         tvb, 
4946                         offset + 2, 
4947                         2, 
4948                         little_endian);
4949   offset += 4;
4950
4951   /* readerEntityId */
4952   rtps_util_add_entity_id(tree,
4953                         tvb,
4954                         offset,
4955                         hf_rtps_sm_rdentity_id,
4956                         hf_rtps_sm_rdentity_id_key,
4957                         hf_rtps_sm_rdentity_id_kind,
4958                         ett_rtps_rdentity,
4959                         "readerEntityId",
4960                         NULL);
4961   offset += 4;
4962
4963   /* writerEntityId */
4964   rtps_util_add_entity_id(tree,
4965                         tvb,
4966                         offset,
4967                         hf_rtps_sm_wrentity_id,
4968                         hf_rtps_sm_wrentity_id_key,
4969                         hf_rtps_sm_wrentity_id_kind,
4970                         ett_rtps_wrentity,
4971                         "writerEntityId",
4972                         NULL);
4973   offset += 4;
4974
4975   /* First available Sequence Number */
4976   rtps_util_add_seq_number(tree,
4977                         tvb,
4978                         offset,
4979                         little_endian,
4980                         "firstAvailableSeqNumber");
4981   offset += 8;
4982
4983   /* Last Sequence Number */
4984   rtps_util_add_seq_number(tree,
4985                         tvb,
4986                         offset,
4987                         little_endian,
4988                         "lastSeqNumber");
4989   offset += 8;
4990
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,
4995                         tvb,
4996                         offset,
4997                         4,
4998                         "count: %u",
4999                         counter);
5000   }
5001 }
5002
5003
5004 /* *********************************************************************** */
5005 /* *                                 G A P                               * */
5006 /* *********************************************************************** */
5007 static void dissect_GAP(tvbuff_t *tvb, 
5008                 gint offset, 
5009                 guint8 flags, 
5010                 gboolean little_endian,
5011                 int octects_to_next_header, 
5012                 proto_tree *tree) {
5013   /* RTPS 1.0/1.1:
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    * +---------------+---------------+---------------+---------------+
5022    * |                                                               |
5023    * + SequenceNumber firstSeqNumber                                 +
5024    * |                                                               |
5025    * +---------------+---------------+---------------+---------------+
5026    * |                                                               |
5027    * + Bitmap bitmap                                                 +
5028    * |                                                               |
5029    * +---------------+---------------+---------------+---------------+
5030    *
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    * +---------------+---------------+---------------+---------------+
5039    * |                                                               |
5040    * + SequenceNumber gapStart                                       +
5041    * |                                                               |
5042    * +---------------+---------------+---------------+---------------+
5043    * |                                                               |
5044    * ~ SequenceNumberSet gapList                                     ~
5045    * |                                                               |
5046    * +---------------+---------------+---------------+---------------+
5047    */
5048
5049   rtps_util_decode_flags(tree, tvb, offset + 1, flags, GAP_FLAGS);
5050
5051   if (octects_to_next_header < 24) {
5052     proto_tree_add_uint_format(tree, 
5053                         hf_rtps_sm_octets_to_next_header,
5054                         tvb, 
5055                         offset + 2, 
5056                         2, 
5057                         octects_to_next_header,
5058                         "octectsToNextHeader: %u (Error: should be >= 24)",
5059                         octects_to_next_header);
5060     return;
5061   }
5062   proto_tree_add_item(tree, 
5063                         hf_rtps_sm_octets_to_next_header,
5064                         tvb, 
5065                         offset + 2, 
5066                         2, 
5067                         little_endian);
5068   offset += 4;
5069
5070   /* readerEntityId */
5071   rtps_util_add_entity_id(tree,
5072                         tvb,
5073                         offset,
5074                         hf_rtps_sm_rdentity_id,
5075                         hf_rtps_sm_rdentity_id_key,
5076                         hf_rtps_sm_rdentity_id_kind,
5077                         ett_rtps_rdentity,
5078                         "readerEntityId",
5079                         NULL);
5080   offset += 4;
5081
5082   /* writerEntityId */
5083   rtps_util_add_entity_id(tree,
5084                         tvb,
5085                         offset,
5086                         hf_rtps_sm_wrentity_id,
5087                         hf_rtps_sm_wrentity_id_key,
5088                         hf_rtps_sm_wrentity_id_kind,
5089                         ett_rtps_wrentity,
5090                         "writerEntityId",
5091                         NULL);
5092   offset += 4;
5093
5094
5095  /* First Sequence Number */
5096   rtps_util_add_seq_number(tree,
5097                         tvb,
5098                         offset,
5099                         little_endian,
5100                         "gapStart");
5101   offset += 8;
5102
5103   /* Bitmap */
5104   rtps_util_add_bitmap(tree,
5105                         tvb,
5106                         offset,
5107                         little_endian,
5108                         "gapList");
5109 }
5110
5111
5112 /* *********************************************************************** */
5113 /* *                           I N F O _ T S                             * */
5114 /* *********************************************************************** */
5115 static void dissect_INFO_TS(tvbuff_t *tvb, 
5116                 gint offset, 
5117                 guint8 flags, 
5118                 gboolean little_endian,
5119                 int octects_to_next_header, 
5120                 proto_tree *tree) {
5121   /* RTPS 1.0/1.1:
5122    * 0...2...........7...............15.............23...............31
5123    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
5124    * |   INFO_TS     |X|X|X|X|X|X|I|E|      octetsToNextHeader       | 
5125    * +---------------+---------------+---------------+---------------+
5126    * |                                                               |
5127    * + NtpTime ntpTimestamp [only if I==0]                           +
5128    * |                                                               |
5129    * +---------------+---------------+---------------+---------------+
5130    *
5131    * RTPS 1.2:
5132    * 0...2...........7...............15.............23...............31
5133    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
5134    * |   INFO_TS     |X|X|X|X|X|X|T|E|      octetsToNextHeader       | 
5135    * +---------------+---------------+---------------+---------------+
5136    * |                                                               |
5137    * + Timestamp timestamp [only if T==1]                            +
5138    * |                                                               |
5139    * +---------------+---------------+---------------+---------------+
5140    */
5141
5142   int min_len;
5143   rtps_util_decode_flags(tree, tvb, offset + 1, flags, INFO_TS_FLAGS);
5144
5145   min_len = 0;
5146   if ((flags & FLAG_INFO_TS_T) == 0) min_len += 8;
5147
5148   if (octects_to_next_header != min_len) {
5149     proto_tree_add_uint_format(tree, 
5150                         hf_rtps_sm_octets_to_next_header,
5151                         tvb, 
5152                         offset+2, 
5153                         2, 
5154                         octects_to_next_header,
5155                         "octectsToNextHeader: %u (Error: should be == %u)",
5156                         octects_to_next_header, 
5157                         min_len);
5158     return;
5159   }
5160
5161   proto_tree_add_item(tree, 
5162                         hf_rtps_sm_octets_to_next_header,
5163                         tvb, 
5164                         offset + 2, 
5165                         2, 
5166                         little_endian);
5167   offset += 4;
5168
5169   if ((flags & FLAG_INFO_TS_T) == 0) {
5170     rtps_util_add_ntp_time(tree,
5171                         tvb,
5172                         offset,
5173                         little_endian,
5174                         "timestamp",
5175                         NULL,
5176                         0);
5177   }
5178 }
5179
5180
5181 /* *********************************************************************** */
5182 /* *                           I N F O _ S R C                           * */
5183 /* *********************************************************************** */
5184 static void dissect_INFO_SRC(tvbuff_t *tvb, 
5185                 gint offset, 
5186                 guint8 flags, 
5187                 gboolean little_endian,
5188                 int octects_to_next_header, 
5189                 proto_tree *tree) {
5190   /* RTPS 1.0/1.1:
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    * +---------------+---------------+---------------+---------------+
5199    * | HostId hostId                                                 |
5200    * +---------------+---------------+---------------+---------------+
5201    * | AppId appId                                                   | 
5202    * +---------------+---------------+---------------+---------------+
5203    *
5204    * RTPS 1.2:
5205    * 0...2...........7...............15.............23...............31
5206    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
5207    * |   INFO_SRC    |X|X|X|X|X|X|X|E|      octetsToNextHeader       | 
5208    * +---------------+---------------+---------------+---------------+
5209    * | long unused                                                   |
5210    * +---------------+---------------+---------------+---------------+
5211    * | ProtocolVersion version       | VendorId vendor               |
5212    * +---------------+---------------+---------------+---------------+
5213    * |                                                               |
5214    * + GuidPrefix guidPrefix                                         +
5215    * |                                                               |
5216    * +---------------+---------------+---------------+---------------+
5217    */
5218
5219   rtps_util_decode_flags(tree, tvb, offset + 1, flags, INFO_SRC_FLAGS);
5220
5221   if (octects_to_next_header != 16) {
5222     proto_tree_add_uint_format(tree, 
5223                         hf_rtps_sm_octets_to_next_header,
5224                         tvb, 
5225                         offset+2, 
5226                         2, 
5227                         octects_to_next_header,
5228                         "octectsToNextHeader: %u (Error: should be == 16)",
5229                         octects_to_next_header);
5230     return;
5231   }
5232
5233   proto_tree_add_item(tree, 
5234                         hf_rtps_sm_octets_to_next_header,
5235                         tvb, 
5236                         offset + 2, 
5237                         2, 
5238                         little_endian);
5239   offset += 4;
5240
5241   /* Ip Address */
5242   {
5243     guint32 ip = NEXT_guint32(tvb, offset, little_endian);
5244     proto_tree_add_text(tree,
5245                         tvb,
5246                         offset,
5247                         4,
5248                         "unused: 0x%08x (appIpAddress: %d.%d.%d.%d)",
5249                         ip,
5250                         (ip >> 24) & 0xff,
5251                         (ip >> 16) & 0xff,
5252                         (ip >> 8) & 0xff,
5253                         ip & 0xff);
5254     offset += 4;
5255   }
5256
5257   /* Version */
5258   {
5259     guint8 major = 0;
5260     guint8 minor = 0;
5261     major = tvb_get_guint8(tvb, offset);
5262     minor = tvb_get_guint8(tvb, offset+1);
5263
5264     proto_tree_add_text(tree,
5265                         tvb,
5266                         offset,
5267                         2,
5268                         "version: %d.%d",
5269                         major, 
5270                         minor);
5271     offset += 2;
5272   }
5273
5274   /* Vendor ID */
5275   {
5276     guint8 vendor[MAX_VENDOR_ID_SIZE];
5277     rtps_util_add_vendor_id(NULL,
5278                         tvb,
5279                         offset, 
5280                         vendor, 
5281                         MAX_VENDOR_ID_SIZE);
5282     proto_tree_add_text(tree,
5283                         tvb,
5284                         offset,
5285                         2,
5286                         "vendor: %s",
5287                         vendor);
5288     offset += 2;
5289   }
5290  
5291   { 
5292     /* guint8 temp_buffer[MAX_GUID_PREFIX_SIZE]; */
5293     rtps_util_add_guid_prefix(tree,
5294                         tvb,
5295                         offset,
5296                         hf_rtps_sm_guid_prefix,
5297                         hf_rtps_sm_host_id,
5298                         hf_rtps_sm_app_id,
5299                         hf_rtps_sm_instance_id,
5300                         hf_rtps_sm_app_kind,
5301                         NULL,   /* Use default 'guidPrefix' */
5302                         NULL,
5303                         0);
5304 /*
5305                         &temp_buffer[0],
5306                         MAX_GUID_PREFIX_SIZE);
5307     proto_tree_add_text(tree,
5308                         tvb,
5309                         offset,
5310                         8,
5311                         temp_buffer);
5312 */
5313   }
5314
5315 }
5316
5317
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, 
5322                 gint offset, 
5323                 guint8 flags, 
5324                 gboolean little_endian,
5325                 int octects_to_next_header, 
5326                 proto_tree *tree) {
5327   /* RTPS 1.0/1.1:
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    * +---------------+---------------+---------------+---------------+
5340    *
5341    * RTPS 1.2:
5342    * 0...2...........7...............15.............23...............31
5343    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
5344    * |INFO_REPLY_IP4 |X|X|X|X|X|X|M|E|      octetsToNextHeader       | 
5345    * +---------------+---------------+---------------+---------------+
5346    * |                                                               |
5347    * + LocatorUDPv4 unicastReplyLocator                              +
5348    * |                                                               |
5349    * +---------------+---------------+---------------+---------------+
5350    * |                                                               |
5351    * + LocatorUDPv4 multicastReplyLocator [only if M==1]             +
5352    * |                                                               |
5353    * +---------------+---------------+---------------+---------------+
5354    */
5355
5356   int min_len;
5357   rtps_util_decode_flags(tree, tvb, offset + 1, flags, INFO_REPLY_IP4_FLAGS);
5358
5359   min_len = 8;
5360   if ((flags & FLAG_INFO_REPLY_IP4_M) == 1) min_len += 8;
5361
5362
5363   if (octects_to_next_header != min_len) {
5364     proto_tree_add_uint_format(tree, 
5365                         hf_rtps_sm_octets_to_next_header,
5366                         tvb, 
5367                         offset+2, 
5368                         2, 
5369                         octects_to_next_header,
5370                         "octectsToNextHeader: %u (Error: should be == %u)",
5371                         octects_to_next_header,
5372                         min_len);
5373     return;
5374   }
5375
5376   proto_tree_add_item(tree, 
5377                         hf_rtps_sm_octets_to_next_header,
5378                         tvb, 
5379                         offset + 2, 
5380                         2, 
5381                         little_endian);
5382   offset += 4;
5383
5384
5385   /* unicastReplyLocator */
5386   rtps_util_add_locator_udp_v4(tree,
5387                         tvb,
5388                         offset,
5389                         "unicastReplyLocator",
5390                         little_endian);
5391
5392   offset += 8;
5393
5394   /* multicastReplyLocator */
5395   if ((flags & FLAG_INFO_REPLY_IP4_M) == 1) {
5396     rtps_util_add_locator_udp_v4(tree,
5397                         tvb,
5398                         offset,
5399                         "multicastReplyLocator",
5400                         little_endian);
5401     offset += 8;
5402   }
5403 }
5404
5405 /* *********************************************************************** */
5406 /* *                           I N F O _ D S T                           * */
5407 /* *********************************************************************** */
5408 static void dissect_INFO_DST(tvbuff_t *tvb, 
5409                 gint offset, 
5410                 guint8 flags, 
5411                 gboolean little_endian,
5412                 int octects_to_next_header, 
5413                 proto_tree *tree) {
5414   /* RTPS 1.0/1.1:
5415    * 0...2...........7...............15.............23...............31
5416    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
5417    * |   INFO_DST    |X|X|X|X|X|X|X|E|      octetsToNextHeader       | 
5418    * +---------------+---------------+---------------+---------------+
5419    * | HostId hostId                                                 |
5420    * +---------------+---------------+---------------+---------------+
5421    * | AppId appId                                                   | 
5422    * +---------------+---------------+---------------+---------------+
5423    *
5424    * RTPS 1.2:
5425    * 0...2...........7...............15.............23...............31
5426    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
5427    * |   INFO_DST    |X|X|X|X|X|X|X|E|      octetsToNextHeader       | 
5428    * +---------------+---------------+---------------+---------------+
5429    * |                                                               |
5430    * + GuidPrefix guidPrefix                                         +
5431    * |                                                               |
5432    * +---------------+---------------+---------------+---------------+
5433    */
5434
5435   rtps_util_decode_flags(tree, tvb, offset + 1, flags, INFO_DST_FLAGS);
5436
5437   if (octects_to_next_header != 8) {
5438     proto_tree_add_uint_format(tree, 
5439                         hf_rtps_sm_octets_to_next_header,
5440                         tvb, 
5441                         offset+2, 
5442                         2, 
5443                         octects_to_next_header,
5444                         "octectsToNextHeader: %u (Error: should be == 8)",
5445                         octects_to_next_header);
5446     return;
5447   }
5448
5449   proto_tree_add_item(tree, 
5450                         hf_rtps_sm_octets_to_next_header,
5451                         tvb, 
5452                         offset + 2, 
5453                         2, 
5454                         little_endian);
5455   offset += 4;
5456
5457   { 
5458     rtps_util_add_guid_prefix(tree,
5459                         tvb,
5460                         offset,
5461                         hf_rtps_sm_guid_prefix,
5462                         hf_rtps_sm_host_id,
5463                         hf_rtps_sm_app_id,
5464                         hf_rtps_sm_instance_id,
5465                         hf_rtps_sm_app_kind,
5466                         NULL,
5467                         NULL,
5468                         0);
5469   }
5470 }
5471
5472
5473
5474 /* *********************************************************************** */
5475 /* *                        I N F O _ R E P L Y                          * */
5476 /* *********************************************************************** */
5477 static void dissect_INFO_REPLY(tvbuff_t *tvb, 
5478                 gint offset, 
5479                 guint8 flags, 
5480                 gboolean little_endian,
5481                 int octects_to_next_header, 
5482                 proto_tree *tree) {
5483   /* RTPS 1.0/1.1:
5484    *   INFO_REPLY is *NOT* the same thing as the old INFO_REPLY.
5485    *
5486    * RTPS 1.2:
5487    * 0...2...........7...............15.............23...............31
5488    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
5489    * |   INFO_REPLY  |X|X|X|X|X|X|M|E|      octetsToNextHeader       | 
5490    * +---------------+---------------+---------------+---------------+
5491    * |                                                               |
5492    * ~ LocatorList unicastReplyLocatorList                           ~
5493    * |                                                               |
5494    * +---------------+---------------+---------------+---------------+
5495    * |                                                               |
5496    * ~ LocatorList multicastReplyLocatorList [only if M==1]          ~
5497    * |                                                               |
5498    * +---------------+---------------+---------------+---------------+
5499    */
5500
5501   int min_len;
5502   rtps_util_decode_flags(tree, tvb, offset + 1, flags, INFO_REPLY_FLAGS);
5503
5504   min_len = 8;
5505   if ((flags & FLAG_INFO_REPLY_M) == 1) min_len += 8;
5506
5507
5508   if (octects_to_next_header != min_len) {
5509     proto_tree_add_uint_format(tree, 
5510                         hf_rtps_sm_octets_to_next_header,
5511                         tvb, 
5512                         offset+2, 
5513                         2, 
5514                         octects_to_next_header,
5515                         "octectsToNextHeader: %u (Error: should be == %u)",
5516                         octects_to_next_header,
5517                         min_len);
5518     return;
5519   }
5520
5521   proto_tree_add_item(tree, 
5522                         hf_rtps_sm_octets_to_next_header,
5523                         tvb, 
5524                         offset + 2, 
5525                         2, 
5526                         little_endian);
5527   offset += 4;
5528
5529
5530   /* unicastReplyLocatorList */
5531   rtps_util_add_locator_list(tree,
5532                         tvb,
5533                         offset,
5534                         "unicastReplyLocatorList",
5535                         little_endian);
5536
5537   offset += 8;
5538
5539   /* multicastReplyLocatorList */
5540   if ((flags & FLAG_INFO_REPLY_M) == 1) {
5541     rtps_util_add_locator_list(tree,
5542                         tvb,
5543                         offset,
5544                         "multicastReplyLocatorList",
5545                         little_endian);
5546     offset += 8;
5547   }
5548 }
5549
5550
5551
5552
5553
5554 /***************************************************************************/
5555 /* The main packet dissector function
5556  */
5557 static gboolean dissect_rtps(tvbuff_t *tvb, 
5558                         packet_info *pinfo, 
5559                         proto_tree *tree) {
5560   proto_item       *ti = NULL;
5561   proto_tree       *rtps_tree=NULL;
5562   gint             offset = 0;
5563   proto_tree       *rtps_submessage_tree;
5564   guint8           submessageId;
5565   guint8           flags;
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;
5573
5574   if (is_tcp) {
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);
5578      */
5579     offset = 4;
5580   }
5581       
5582   /* Check 'RTPS' signature: 
5583    * A header is invalid if it has less than 16 octets 
5584    */
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;
5592
5593   /* --- Make entries in Protocol column ---*/
5594   if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
5595     col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTPS");
5596   }
5597
5598   if (check_col(pinfo->cinfo, COL_INFO)) {
5599     col_clear(pinfo->cinfo, COL_INFO);
5600   }
5601
5602
5603   if (tree) {
5604     guint8 nddsPing[8];
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);
5608
5609     /*  Protocol Version */
5610     rtps_util_add_protocol_version(rtps_tree, tvb, offset+4);
5611
5612     /*  Vendor Id  */
5613     rtps_util_add_vendor_id(rtps_tree, tvb, offset+6, NULL, 0);
5614
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') {
5624       is_ping = TRUE;
5625     }
5626     
5627     if (!is_ping) {
5628       rtps_util_add_guid_prefix(rtps_tree, 
5629                         tvb,
5630                         offset+8,
5631                         hf_rtps_guid_prefix,
5632                         hf_rtps_host_id,
5633                         hf_rtps_app_id,
5634                         hf_rtps_app_id_instance_id,
5635                         hf_rtps_app_id_app_kind,
5636                         NULL,
5637                         NULL,
5638                         0);
5639     }
5640   }
5641
5642   /* Extract the domain id and participant index */
5643   {
5644     int domain_id;
5645     int participant_idx;
5646     int nature;
5647     proto_item *ti;
5648     proto_tree *mapping_tree;
5649
5650     domain_id = ((pinfo->destport - PORT_BASE)/10) % 100;
5651     participant_idx = (pinfo->destport - PORT_BASE) / 1000;
5652     nature    = (pinfo->destport % 10);
5653
5654     ti = proto_tree_add_text(rtps_tree,
5655                         tvb,
5656                         0,
5657                         4,
5658                         "Default port mapping: domainId=%d, "
5659                         "participantIdx=%d, nature=%s",
5660                         domain_id,
5661                         participant_idx,
5662                         val_to_str(nature, nature_type_vals, "%02x"));
5663
5664     mapping_tree = proto_item_add_subtree(ti, ett_rtps_default_mapping);
5665     proto_tree_add_uint(mapping_tree,
5666                         hf_rtps_domain_id,
5667                         tvb,
5668                         0,
5669                         4,
5670                         domain_id);
5671     proto_tree_add_uint(mapping_tree,
5672                         hf_rtps_participant_idx,
5673                         tvb,
5674                         0,
5675                         4,
5676                         participant_idx);
5677     proto_tree_add_uint(mapping_tree,
5678                         hf_rtps_nature_type,
5679                         tvb,
5680                         0,
5681                         4,
5682                         nature);
5683
5684   }
5685
5686   /* offset behind RTPS's Header (need to be set in case tree=NULL)*/
5687   offset=16;
5688
5689   while (tvb_reported_length_remaining(tvb, offset) > 0) {
5690     sm_extra = NULL;
5691     submessageId = tvb_get_guint8(tvb, offset);
5692
5693     /* Creates the subtree 'Submessage: XXXX' */
5694     if (submessageId & 0x80) {
5695       ti = proto_tree_add_text(rtps_tree, 
5696                               tvb, 
5697                               offset, 
5698                               -1, 
5699                               "Submessage: %s",
5700                               val_to_str(submessageId, submessage_id_vals,
5701                                     "Vendor-specific (0x%02x)"));
5702     } else {
5703       ti = proto_tree_add_text(rtps_tree, 
5704                               tvb, 
5705                               offset, 
5706                               -1, 
5707                               "Submessage: %s",
5708                               val_to_str(submessageId, submessage_id_vals,
5709                                         "Unknown (0x%02x)"));
5710     }
5711     rtps_submessage_tree = proto_item_add_subtree(ti, ett_rtps_submessage);
5712
5713     /* Decode the submessage ID */
5714     if (submessageId & 0x80) {
5715       proto_tree_add_uint_format(rtps_submessage_tree, 
5716                               hf_rtps_sm_id,
5717                               tvb, 
5718                               offset, 
5719                               1, 
5720                               submessageId,
5721                               "submessageId: Vendor-specific (0x%02x)",
5722                               submessageId);
5723     } else {
5724       proto_tree_add_uint(rtps_submessage_tree, hf_rtps_sm_id,
5725                         tvb, offset, 1, submessageId);
5726     }
5727
5728     /* Gets the flags */
5729     flags = tvb_get_guint8(tvb, offset + 1);
5730
5731     /* Gets the E (Little endian) flag */
5732     little_endian = ((flags & FLAG_E) != 0);
5733     
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;
5737
5738     /* Set length of this item */
5739     proto_item_set_len(ti, octects_to_next_header + 4); 
5740
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).
5747      */
5748     switch (submessageId)
5749     {
5750       case PAD:
5751         if (tree) {
5752           dissect_PAD(tvb, 
5753                         offset, 
5754                         flags, 
5755                         little_endian, 
5756                         octects_to_next_header,
5757                         rtps_submessage_tree);
5758         }
5759         break;
5760
5761       case DATA:
5762         if (tree) {
5763           dissect_DATA(tvb, 
5764                         offset, 
5765                         flags, 
5766                         little_endian, 
5767                         octects_to_next_header,
5768                         rtps_submessage_tree,
5769                         &sm_extra);
5770         }
5771         break;
5772
5773       case NOKEY_DATA:
5774         if (tree) {
5775           dissect_NOKEY_DATA(tvb, 
5776                         offset, 
5777                         flags, 
5778                         little_endian, 
5779                         octects_to_next_header,
5780                         rtps_submessage_tree);
5781         }
5782         break;
5783
5784       case ACKNACK:
5785         if (tree) {
5786           dissect_ACKNACK(tvb, 
5787                         offset, 
5788                         flags, 
5789                         little_endian, 
5790                         octects_to_next_header,
5791                         rtps_submessage_tree);
5792         }
5793         break;
5794
5795       case HEARTBEAT:
5796         if (tree) {
5797           dissect_HEARTBEAT(tvb, 
5798                         offset, 
5799                         flags, 
5800                         little_endian, 
5801                         octects_to_next_header,
5802                         rtps_submessage_tree);
5803         }
5804         break;
5805
5806       case GAP:
5807         if (tree) {
5808           dissect_GAP(tvb, 
5809                         offset, 
5810                         flags, 
5811                         little_endian, 
5812                         octects_to_next_header,
5813                         rtps_submessage_tree);
5814         }
5815         break;
5816
5817       case INFO_TS:
5818         if (tree) {
5819           dissect_INFO_TS(tvb, 
5820                         offset, 
5821                         flags, 
5822                         little_endian, 
5823                         octects_to_next_header,
5824                         rtps_submessage_tree);
5825         }
5826         break;
5827
5828       case INFO_SRC:
5829         if (tree) {
5830           dissect_INFO_SRC(tvb, 
5831                         offset, 
5832                         flags, 
5833                         little_endian, 
5834                         octects_to_next_header,
5835                         rtps_submessage_tree);
5836         }
5837         break;
5838
5839       case INFO_REPLY_IP4:
5840         if (tree) {
5841           dissect_INFO_REPLY_IP4(tvb, 
5842                         offset, 
5843                         flags, 
5844                         little_endian, 
5845                         octects_to_next_header,
5846                         rtps_submessage_tree);
5847         }
5848         break;
5849
5850       case INFO_DST:
5851         if (tree) {
5852           dissect_INFO_DST(tvb, 
5853                         offset, 
5854                         flags, 
5855                         little_endian, 
5856                         octects_to_next_header,
5857                         rtps_submessage_tree);
5858         }
5859         break;
5860
5861       case INFO_REPLY:
5862         if (tree) {
5863           dissect_INFO_REPLY(tvb, 
5864                         offset, 
5865                         flags, 
5866                         little_endian, 
5867                         octects_to_next_header,
5868                         rtps_submessage_tree);
5869         }
5870         break;
5871
5872       default:
5873         if (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);
5879         }
5880         break;
5881      }
5882
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;
5887     }
5888
5889      /* next submessage's offset */
5890      offset = next_submsg;
5891   }
5892
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;
5898
5899
5900     if (is_ping) {
5901         ep_strbuf_append(info_buf, "PING");
5902     } else {
5903       /* Counts of submessages - for Information Frame */
5904       while (smcr_ptr != NULL) {
5905         if (info_buf->len > 0) {
5906           ep_strbuf_append(info_buf, ", ");
5907         }
5908 /*
5909         if (smcr_ptr->counter > 1) {
5910           ep_strbuf_append_printf(info_buf, "%s(%d)", 
5911                           val_to_str(smcr_ptr->id,
5912                                   submessage_id_vals, 
5913                                   "Unknown[%02x]"),
5914                           smcr_ptr->counter);
5915         } else {
5916 */
5917           ep_strbuf_append_printf(info_buf, "%s%s", 
5918                           val_to_str(smcr_ptr->id,
5919                                   submessage_id_vals, 
5920                                   "Unknown[%02x]"),
5921                           smcr_ptr->extra ? smcr_ptr->extra : "");
5922           /* XXX - Ellipsis code removed when we converted to a strbuf. */
5923 /*
5924         }
5925 */
5926         smcr_ptr = smcr_ptr->next;
5927       }
5928     }
5929     col_add_str(pinfo->cinfo, COL_INFO, info_buf->str);
5930   }
5931   sm_counter_free(smcr_head);
5932
5933   /* If TCP there's an extra OOB byte at the end of the message */
5934   /* TODO: What to do with it? */
5935   return TRUE;
5936
5937 }  /* dissect_rtps(...) */
5938
5939
5940
5941
5942
5943 /***************************************************************************
5944  * Register the protocol with Wireshark 
5945  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5946  */
5947 void proto_register_rtps(void) {
5948
5949   /* Definition of the protocol tree items:
5950    * This section declares all the protocol items that are parsed in the
5951    * dissectors.
5952    * Structure of each element:
5953    *  {   
5954    *    item_id,  {
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
5962    *        HFILL
5963    *    }
5964    *  }
5965    */
5966   static hf_register_info hf[] = {
5967
5968     /* Protocol Version (composed as major.minor) -------------------------- */
5969     { &hf_rtps_protocol_version, {
5970         "version",
5971         "rtps.version",
5972         FT_NONE,
5973         BASE_NONE,
5974         NULL,
5975         0,
5976         "RTPS protocol version number",
5977         HFILL }
5978     },
5979     { &hf_rtps_protocol_version_major, { 
5980         "major",
5981         "rtps.version.major",
5982         FT_INT8,
5983         BASE_DEC,
5984         NULL,
5985         0,
5986         "RTPS major protocol version number",
5987         HFILL }
5988     },
5989     { &hf_rtps_protocol_version_minor, {
5990         "minor",
5991         "rtps.version.minor",
5992         FT_INT8,
5993         BASE_DEC,
5994         NULL,
5995         0,
5996         "RTPS minor protocol version number",
5997         HFILL }
5998     },
5999
6000     /* Domain Participant and Participant Index ---------------------------- */
6001     { &hf_rtps_domain_id, {
6002         "domain_id",
6003         "rtps.domain_id",
6004         FT_UINT32,
6005         BASE_DEC,
6006         NULL,
6007         0,
6008         "Domain ID",
6009         HFILL }
6010     },
6011
6012     { &hf_rtps_participant_idx, {
6013         "participant_idx",
6014         "rtps.participant_idx",
6015         FT_UINT32,
6016         BASE_DEC,
6017         NULL,
6018         0,
6019         "Participant index",
6020         HFILL }
6021     },
6022     { &hf_rtps_nature_type, {
6023         "traffic_nature",
6024         "rtps.traffic_nature",
6025         FT_UINT32,
6026         BASE_DEC,
6027         VALS(nature_type_vals),
6028         0,
6029         "Nature of the traffic (meta/user-traffic uni/multi-cast)",
6030         HFILL }
6031     },
6032
6033     /* Vendor ID ----------------------------------------------------------- */
6034     { &hf_rtps_vendor_id, {
6035         "vendorId",
6036         "rtps.vendorId",
6037         FT_UINT16,
6038         BASE_HEX,
6039         NULL,
6040         0,
6041         "Unique identifier of the DDS vendor that generated this packet",
6042         HFILL }
6043     },
6044
6045     /* Guid Prefix for the Packet ------------------------------------------ */
6046     { &hf_rtps_guid_prefix, { 
6047         "guidPrefix",
6048         "rtps.guidPrefix",
6049         FT_BYTES,
6050         BASE_HEX,
6051         NULL,
6052         0,
6053         "GuidPrefix of the RTPS packet",
6054         HFILL }
6055     },
6056
6057     /* Host ID ------------------------------------------------------------- */
6058     { &hf_rtps_host_id, {               /* HIDDEN */
6059         "hostId",
6060         "rtps.hostId",
6061         FT_UINT32,
6062         BASE_HEX,
6063         NULL,
6064         0,
6065         "Sub-component 'hostId' of the GuidPrefix of the RTPS packet",
6066         HFILL }
6067     },
6068
6069     /* AppID (composed as instanceId, appKind) ----------------------------- */
6070     { &hf_rtps_app_id, {
6071         "appId",
6072         "rtps.appId",
6073         FT_UINT32,
6074         BASE_HEX,
6075         NULL,
6076         0,
6077         "Sub-component 'appId' of the GuidPrefix of the RTPS packet",
6078         HFILL }
6079     },
6080     { &hf_rtps_app_id_instance_id, {
6081         "appId.instanceId",
6082         "rtps.appId.instanceId",
6083         FT_UINT24,
6084         BASE_HEX,
6085         NULL,
6086         0,
6087         "'instanceId' field of the 'AppId' structure",
6088         HFILL }
6089     },
6090     { &hf_rtps_app_id_app_kind, {
6091         "appid.appKind",
6092         "rtps.appId.appKind",
6093         FT_UINT8,
6094         BASE_HEX,
6095         VALS(app_kind_vals),
6096         0,
6097         "'appKind' field of the 'AppId' structure",
6098         HFILL }
6099     },
6100
6101
6102
6103     /* Submessage ID ------------------------------------------------------- */
6104     { &hf_rtps_sm_id, { 
6105         "submessageId", 
6106         "rtps.sm.id",
6107         FT_UINT8, 
6108         BASE_HEX, 
6109         VALS(submessage_id_vals), 
6110         0,
6111         "defines the type of submessage", 
6112         HFILL }
6113     },
6114
6115     /* Submessage flags ---------------------------------------------------- */
6116     { &hf_rtps_sm_flags, { 
6117         "flags", 
6118         "rtps.sm.flags",
6119         FT_UINT8, 
6120         BASE_HEX, 
6121         NULL, 
6122         0,
6123         "bitmask representing the flags associated with a submessage", 
6124         HFILL }
6125     },
6126
6127     /* Octects to next header ---------------------------------------------- */
6128     { &hf_rtps_sm_octets_to_next_header, { 
6129         "octetsToNextHeader", 
6130         "rtps.sm.octetsToNextHeader",
6131         FT_UINT16, 
6132         BASE_DEC, 
6133         NULL, 
6134         0,
6135         "Size of the submessage payload", 
6136         HFILL }
6137     },
6138
6139     /* GUID as {GuidPrefix, EntityId} ------------------------------------ */
6140     { &hf_rtps_sm_guid_prefix, {
6141         "guidPrefix",
6142         "rtps.sm.guidPrefix",
6143         FT_BYTES,
6144         BASE_HEX,
6145         NULL,
6146         0,
6147         "a generic guidPrefix that is transmitted inside the submessage "
6148         "(this is NOT the guidPrefix described in the packet header",
6149         HFILL }
6150     },
6151
6152     { &hf_rtps_sm_host_id, {    
6153         "host_id",
6154         "rtps.sm.guidPrefix.hostId",
6155         FT_UINT32,
6156         BASE_HEX,
6157         NULL,
6158         0,
6159         "The hostId component of the rtps.sm.guidPrefix",
6160         HFILL }
6161     },
6162
6163     { &hf_rtps_sm_app_id, {     
6164         "appId",
6165         "rtps.sm.guidPrefix.appId",
6166         FT_UINT32,
6167         BASE_HEX,
6168         NULL,
6169         0,
6170         "AppId component of the rtps.sm.guidPrefix",
6171         HFILL }
6172     },
6173     { &hf_rtps_sm_instance_id, {
6174         "instanceId",
6175         "rtps.sm.guidPrefix.appId.instanceId",
6176         FT_UINT24,
6177         BASE_HEX,
6178         NULL,
6179         0,
6180         "instanceId component of the AppId of the rtps.sm.guidPrefix",
6181         HFILL }
6182     },
6183     { &hf_rtps_sm_app_kind, { 
6184         "appKind",
6185         "rtps.sm.guidPrefix.appId.appKind",
6186         FT_UINT8,
6187         BASE_HEX,
6188         NULL,
6189         0,
6190         "appKind component of the AppId of the rtps.sm.guidPrefix",
6191         HFILL }
6192     },
6193
6194
6195     /* Entity ID (composed as entityKey, entityKind) ----------------------- */
6196     { &hf_rtps_sm_entity_id, {
6197         "entityId",
6198         "rtps.sm.entityId",
6199         FT_UINT32,
6200         BASE_HEX,
6201         VALS(entity_id_vals),
6202         0,
6203         "Object entity ID as it appears in a DATA submessage (keyHashSuffix)",
6204         HFILL }
6205     },
6206     { &hf_rtps_sm_entity_id_key, {      
6207         "entityKey",
6208         "rtps.sm.entityId.entityKey",
6209         FT_UINT24,
6210         BASE_HEX,
6211         NULL,
6212         0,
6213         "'entityKey' field of the object entity ID",
6214         HFILL }
6215     },
6216     { &hf_rtps_sm_entity_id_kind, {
6217         "entityKind",
6218         "rtps.sm.entityId.entityKind",
6219         FT_UINT8,
6220         BASE_HEX,
6221         VALS(entity_kind_vals),
6222         0,
6223         "'entityKind' field of the object entity ID",
6224         HFILL }
6225     },
6226
6227     { &hf_rtps_sm_rdentity_id, {
6228         "readerEntityId",
6229         "rtps.sm.rdEntityId",
6230         FT_UINT32,
6231         BASE_HEX,
6232         VALS(entity_id_vals),
6233         0,
6234         "Reader entity ID as it appears in a submessage",
6235         HFILL }
6236     },
6237     { &hf_rtps_sm_rdentity_id_key, {
6238         "readerEntityKey",
6239         "rtps.sm.rdEntityId.entityKey",
6240         FT_UINT24,
6241         BASE_HEX,
6242         NULL,
6243         0,
6244         "'entityKey' field of the reader entity ID",
6245         HFILL }
6246     },
6247     { &hf_rtps_sm_rdentity_id_kind, {
6248         "readerEntityKind",
6249         "rtps.sm.rdEntityId.entityKind",
6250         FT_UINT8,
6251         BASE_HEX,
6252         VALS(entity_kind_vals),
6253         0,
6254         "'entityKind' field of the reader entity ID",
6255         HFILL }
6256     },
6257
6258     { &hf_rtps_sm_wrentity_id, {
6259         "writerEntityId",
6260         "rtps.sm.wrEntityId",
6261         FT_UINT32,
6262         BASE_HEX,
6263         VALS(entity_id_vals),
6264         0,
6265         "Writer entity ID as it appears in a submessage",
6266         HFILL }
6267     },
6268     { &hf_rtps_sm_wrentity_id_key, {
6269         "writerEntityKey",
6270         "rtps.sm.wrEntityId.entityKey",
6271         FT_UINT24,
6272         BASE_HEX,
6273         NULL,
6274         0,
6275         "'entityKey' field of the writer entity ID",
6276         HFILL }
6277     },
6278     { &hf_rtps_sm_wrentity_id_kind, {
6279         "writerEntityKind",
6280         "rtps.sm.wrEntityId.entityKind",
6281         FT_UINT8,
6282         BASE_HEX,
6283         VALS(entity_kind_vals),
6284         0,
6285         "'entityKind' field of the writer entity ID",
6286         HFILL }
6287     },
6288
6289
6290
6291     /* Sequence number ----------------------------------------------------- */
6292     { &hf_rtps_sm_seq_number, {
6293         "writerSeqNumber",
6294         "rtps.sm.seqNumber",
6295         FT_INT64,
6296         BASE_DEC,
6297         NULL,
6298         0,
6299         "Writer sequence number",
6300         HFILL }
6301     },
6302
6303     /* Parameter Id -------------------------------------------------------- */
6304     { &hf_rtps_parameter_id, { 
6305         "parameterId", 
6306         "rtps.param.id",
6307         FT_UINT16, 
6308         BASE_HEX, 
6309         VALS(parameter_id_vals), 
6310         0,
6311         "Parameter Id", 
6312         HFILL }
6313     },
6314
6315     /* Parameter Length ---------------------------------------------------- */
6316     { &hf_rtps_parameter_length, { 
6317         "parameterLength", 
6318         "rtps.param.length",
6319         FT_UINT16, 
6320         BASE_DEC, 
6321         NULL, 
6322         0,
6323         "Parameter Length", 
6324         HFILL }
6325     },
6326
6327     /* Parameter / NtpTime ------------------------------------------------- */
6328     { &hf_rtps_param_ntpt, { 
6329         "ntpTime", 
6330         "rtps.param.ntpTime",
6331         FT_NONE, 
6332         BASE_NONE, 
6333         NULL,
6334         0,
6335         "Time using the NTP standard format", 
6336         HFILL }
6337     },
6338     { &hf_rtps_param_ntpt_sec, { 
6339         "seconds", 
6340         "rtps.param.ntpTime.sec",
6341         FT_INT32, 
6342         BASE_DEC, 
6343         NULL,
6344         0,
6345         "The 'second' component of a NTP time", 
6346         HFILL }
6347     },
6348     { &hf_rtps_param_ntpt_fraction, { 
6349         "fraction", 
6350         "rtps.param.ntpTime.fraction",
6351         FT_UINT32, 
6352         BASE_DEC, 
6353         NULL,
6354         0,
6355         "The 'fraction' component of a NTP time",
6356         HFILL }
6357     },
6358
6359
6360     /* Parameter / Topic --------------------------------------------------- */
6361     { &hf_rtps_param_topic_name, { 
6362         "topic", 
6363         "rtps.param.topicName",
6364         FT_STRINGZ, 
6365         BASE_NONE, 
6366         NULL,
6367         0,
6368         "String representing the value value of a PID_TOPIC parameter", 
6369         HFILL }
6370     },
6371
6372     /* Parameter / Strength ------------------------------------------------ */
6373     { &hf_rtps_param_strength, { 
6374         "strength", 
6375         "rtps.param.strength",
6376         FT_INT32, 
6377         BASE_DEC, 
6378         NULL,
6379         0,
6380         "Decimal value representing the value of a PID_OWNERSHIP_STRENGTH "
6381         "parameter", 
6382         HFILL }
6383     },
6384
6385     /* Parameter / Type Name ----------------------------------------------- */
6386     { &hf_rtps_param_type_name, { 
6387         "typeName", 
6388         "rtps.param.typeName",
6389         FT_STRINGZ, 
6390         BASE_NONE, 
6391         NULL,
6392         0,
6393         "String representing the value of a PID_TYPE_NAME parameter", 
6394         HFILL }
6395     },
6396
6397     /* Parameter / User Data ----------------------------------------------- */
6398     { &hf_rtps_param_user_data, { 
6399         "userData", 
6400         "rtps.param.userData",
6401         FT_BYTES, 
6402         BASE_HEX, 
6403         NULL, 
6404         0,
6405         "The user data sent in a PID_USER_DATA parameter", 
6406         HFILL }
6407     },
6408
6409     /* Parameter / Group Data ---------------------------------------------- */
6410     { &hf_rtps_param_group_data, { 
6411         "groupData", 
6412         "rtps.param.groupData",
6413         FT_BYTES, 
6414         BASE_HEX, 
6415         NULL, 
6416         0,
6417         "The user data sent in a PID_GROUP_DATA parameter", 
6418         HFILL }
6419     },
6420
6421     /* Parameter / Topic Data ---------------------------------------------- */
6422     { &hf_rtps_param_topic_data, { 
6423         "topicData", 
6424         "rtps.param.topicData",
6425         FT_BYTES, 
6426         BASE_HEX, 
6427         NULL, 
6428         0,
6429         "The user data sent in a PID_TOPIC_DATA parameter", 
6430         HFILL }
6431     },
6432
6433
6434     /* Parameter / Content Filter Name ------------------------------------- */
6435     { &hf_rtps_param_content_filter_name, { 
6436         "contentFilterName", 
6437         "rtps.param.contentFilterName",
6438         FT_STRINGZ, 
6439         BASE_NONE, 
6440         NULL,
6441         0,
6442         "Value of the content filter name as sent in a PID_CONTENT_FILTER_PROPERTY parameter", 
6443         HFILL }
6444     },
6445     { &hf_rtps_param_related_topic_name, { 
6446         "relatedTopicName", 
6447         "rtps.param.relatedTopicName",
6448         FT_STRINGZ, 
6449         BASE_NONE, 
6450         NULL,
6451         0,
6452         "Value of the related topic name as sent in a PID_CONTENT_FILTER_PROPERTY parameter", 
6453         HFILL }
6454     },
6455     { &hf_rtps_param_filter_name, { 
6456         "filterName", 
6457         "rtps.param.filterName",
6458         FT_STRINGZ, 
6459         BASE_NONE, 
6460         NULL,
6461         0,
6462         "Value of the filter name as sent in a PID_CONTENT_FILTER_PROPERTY parameter", 
6463         HFILL }
6464     },
6465
6466
6467     /* Finally the raw issue data ------------------------------------------ */
6468     { &hf_rtps_issue_data, { 
6469         "serializedData", 
6470         "rtps.issueData",
6471         FT_BYTES, 
6472         BASE_HEX, 
6473         NULL, 
6474         0,
6475         "The user data transferred in a ISSUE submessage", 
6476         HFILL }
6477     },
6478   };
6479
6480   static gint *ett[] = {
6481     &ett_rtps,
6482     &ett_rtps_default_mapping,
6483     &ett_rtps_proto_version,
6484     &ett_rtps_submessage,
6485     &ett_rtps_parameter_sequence,
6486     &ett_rtps_parameter,
6487     &ett_rtps_flags,
6488     &ett_rtps_entity,
6489     &ett_rtps_rdentity,
6490     &ett_rtps_wrentity,
6491     &ett_rtps_guid_prefix,
6492     &ett_rtps_app_id,
6493     &ett_rtps_locator_udp_v4,
6494     &ett_rtps_locator,
6495     &ett_rtps_locator_list,
6496     &ett_rtps_ntp_time,
6497     &ett_rtps_bitmap,
6498     &ett_rtps_seq_string,
6499     &ett_rtps_seq_ulong,
6500   };
6501
6502   proto_rtps = proto_register_protocol(
6503                         "Real-Time Publish-Subscribe Wire Protocol",
6504                         "RTPS", 
6505                         "rtps");
6506   proto_register_field_array(proto_rtps, hf, array_length(hf));
6507   proto_register_subtree_array(ett, array_length(ett));
6508 }
6509
6510
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);
6514 }
6515