Set the svn:eol-style property on all text files to "native", so that
[obnox/wireshark/wip.git] / packet-rtps.c
1 /* packet-rtps.c
2  * Routines for Real-Time Publish-Subscribe Protocol (RTPS) dissection
3  *
4  * Copyright 2003, LUKAS POKORNY <maskis@seznam.cz>
5  *                 PETR SMOLIK   <petr.smolik@wo.cz>
6  *                 ZDENEK SEBEK  <sebek@fel.cvut.cz>
7  * 
8  * Czech Technical University in Prague 
9  *  Faculty of Electrical Engineering <www.fel.cvut.cz>
10  *  Department of Control Engineering <dce.felk.cvut.cz>                
11  *                   
12  * version: 2004/04/15 9:40:45
13  * dedication to Kj :]
14  *
15  * $Id$
16  *
17  * Ethereal - Network traffic analyzer
18  * By Gerald Combs <gerald@ethereal.com>
19  * Copyright 1998 Gerald Combs
20  *
21  * Copied from packet-udp.c, packet-tftp.c, packet-x25.c
22  *
23  * This program is free software; you can redistribute it and/or
24  * modify it under the terms of the GNU General Public License
25  * as published by the Free Software Foundation; either version 2
26  * of the License, or (at your option) any later version.
27  *
28  * This program is distributed in the hope that it will be useful,
29  * but WITHOUT ANY WARRANTY; without even the implied warranty of
30  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
31  * GNU General Public License for more details.
32  *
33  * You should have received a copy of the GNU General Public License
34  * along with this program; if not, write to the Free Software
35  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36  *
37  * *********************************************************************** */
38
39 #ifdef HAVE_CONFIG_H
40 # include "config.h"
41 #endif
42
43 #ifdef NEED_SNPRINTF_H
44 # include "snprintf.h"
45 #endif
46
47 #include  <stdio.h>
48 #include  <stdlib.h>
49 #include  <string.h>
50 #include  <glib.h>
51 #include  <epan/packet.h>
52 #include  <epan/resolv.h>
53 #include  <epan/conversation.h>
54
55
56 /* *********************************************************************** *
57    RTPS protocol was developed by Real Time Innovation, Inc.
58
59    Protocol specifikation and documenation you can find on these addresses:
60
61    http://www.rti.com/
62
63    http://www.rti.com/products/ndds/literature.html
64
65    http://www.schneider-electric.com.au/Products/Automation/TF_RealTime/
66          /technical%20library/specifications/WireProtocolExternal.pdf
67
68
69  * *********************************************************************** */
70
71
72
73 /* redefine types because of definitions in 'packet-rtps.h' */
74 /*
75 #define  u_int8_t           guint8
76 #define  int8_t             gint8
77
78 #define  u_int16_t          guint16
79 #define  int16_t            gint16
80
81 #define  u_int32_t          guint32
82 #define  int32_t            gint32
83 */
84
85 #include "packet-rtps.h"
86
87 /* number of APP_KIND byte in packet header */
88 #define  APP_KIND_BYTE          15
89
90
91 /*  definitions of flags */
92 #define    FLAG_E      0x01
93 #define    FLAG_F      0x02
94 #define    FLAG_I      0x02
95 #define    FLAG_M      0x02
96 #define    FLAG_P      0x02
97 #define    FLAG_A      0x04
98 #define    FLAG_H      0x08
99
100
101 /*  submessageId's ranges  */
102 #define  SUBMSG_ID_MIN     PAD
103 #define  SUBMSG_ID_MAX     INFO_DST
104
105 /*  Vendor specific submessageId's ranges */
106 #define  VENDOR_SUBMSG_ID_MIN      0x80
107 #define  VENDOR_SUBMSG_ID_MAX      0xff
108
109 /* *********************************************************************** */
110
111
112 /*  initialize the protocol and registered fields  */
113 static int proto_rtps                    = -1;
114 static int hf_rtps_submessage_id         = -1;
115 static int hf_rtps_submessage_flags      = -1;
116 static int hf_rtps_octets_to_next_header = -1;
117 static int hf_rtps_parameter_id          = -1;
118 static int hf_rtps_parameter_length      = -1;
119 static int hf_rtps_issue_data            = -1;
120
121 /*  Initialize the subtree pointers */
122 static gint ett_rtps                     = -1;
123 static gint ett_rtps_submessage          = -1;
124 static gint ett_rtps_bitmap              = -1;
125 static gint ett_rtps_parameter_sequence  = -1;
126 static gint ett_rtps_parameter           = -1;
127
128 /*  Functions declarations */
129 static void dissect_PAD(tvbuff_t *tvb,gint offset,guint8 flags,
130                         int next_submsg_offset,
131                         proto_tree *rtps_submessage_tree);
132 static void dissect_VAR(tvbuff_t *tvb,gint offset,guint8 flags,
133                         gboolean little_endian,int next_submsg_offset,
134                         proto_tree *rtps_submessage_tree);
135 static void dissect_ISSUE(tvbuff_t *tvb,gint offset,guint8 flags,
136                         gboolean little_endian,int next_submsg_offset,
137                         proto_tree *rtps_submessage_tree);
138 static void dissect_ACK(tvbuff_t *tvb,gint offset,guint8 flags,
139                         gboolean little_endian,int next_submsg_offset,
140                         proto_tree *rtps_submessage_tree);
141 static void dissect_HEARTBEAT(tvbuff_t *tvb,gint offset,guint8 flags,
142                         gboolean little_endian,int next_submsg_offset,
143                         proto_tree *rtps_submessage_tree);
144 static void dissect_GAP(tvbuff_t *tvb,gint offset,guint8 flags,
145                         gboolean little_endian,int next_submsg_offset,
146                         proto_tree *rtps_submessage_tree);
147 static void dissect_INFO_TS(tvbuff_t *tvb,gint offset,guint8 flags,
148                         gboolean little_endian,int next_submsg_offset,
149                         proto_tree *rtps_submessage_tree);
150 static void dissect_INFO_SRC(tvbuff_t *tvb,gint offset,guint8 flags,
151                         gboolean little_endian,int next_submsg_offset,
152                         proto_tree *rtps_submessage_tree);
153 static void dissect_INFO_REPLY(tvbuff_t *tvb,gint offset,guint8 flags,
154                         gboolean little_endian,int next_submsg_offset,
155                         proto_tree *rtps_submessage_tree);
156 static void dissect_INFO_DST(tvbuff_t *tvb,gint offset,guint8 flags,
157                         int next_submsg_offset,
158                         proto_tree *rtps_submessage_tree);
159
160 static guint16  get_guint16(tvbuff_t *tvb, gint offset, gboolean little_endian);
161 static guint32  get_guint32(tvbuff_t *tvb, gint offset, gboolean little_endian);
162
163 static char *protocol_version_to_string(gint offset,tvbuff_t *tvb,char *buff);
164 static char *vendor_id_to_string(gint offset, tvbuff_t *tvb, char *buff);
165
166 static char *host_id_to_string(gint offset,tvbuff_t *tvb, char buff[]);
167 static char *app_id_to_string(gint offset,tvbuff_t *tvb,char buff[]);
168 static char *object_id_to_string(gint offset, tvbuff_t *tvb, char buff[]);
169
170 static char *IP_to_string(gint offset,tvbuff_t *tvb,gboolean little_endian,char buff[]);
171 static char *port_to_string(gint offset,tvbuff_t *tvb,gboolean little_endian,char buff[]);
172 static char *get_NtpTime(gint offset,tvbuff_t *tvb,gboolean little_endian,char buff[]);
173
174 static void  get_bitmap(tvbuff_t *tvb, gint *p_offset, gboolean little_endian,
175                         gint next_submsg, proto_tree *tree);
176
177 static void  get_parameter_sequence(tvbuff_t *tvb, gint *p_offset,
178                                     gboolean little_endian,
179                                     gint next_submsg_offset, proto_tree *tree);
180
181 static gint  seq_nr_to_string( gint offset, gboolean little_endian, tvbuff_t *tvb,
182                              SequenceNumber *p_seqNumber);
183
184 static const value_string submessage_id_vals[] = {
185   { PAD, "PAD" },
186   { VAR, "VAR" },
187   { ISSUE, "ISSUE" },
188   { ACK, "ACK" },
189   { HEARTBEAT, "HEARTBEAT" },
190   { GAP, "GAP" },
191   { INFO_TS, "INFO_TS" },
192   { INFO_SRC, "INFO_SRC" },
193   { INFO_REPLY, "INFO_REPLY" },
194   { INFO_DST, "INFO_DST" },
195   { APP_QUIT, "APP_QUIT" },
196   { 0, NULL }
197 };
198
199 static const value_string parameter_id_vals[] = {
200   { PID_PAD, "PID_PAD" },
201   { PID_SENTINEL, "PID_SENTINEL" },
202   { PID_EXPIRATION_TIME, "PID_EXPIRATION_TIME" },
203   { PID_PERSISTENCE, "PID_PERSISTENCE" },
204   { PID_MINIMUM_SEPARATION, "PID_MINIMUM_SEPARATION" },
205   { PID_TOPIC, "PID_TOPIC" },
206   { PID_STRENGTH, "PID_STRENGTH" },
207   { PID_TYPE_NAME, "PID_TYPE_NAME" },
208   { PID_TYPE_CHECKSUM, "PID_TYPE_CHECKSUM" },
209   { RTPS_PID_TYPE2_NAME, "RTPS_PID_TYPE2_NAME" },
210   { RTPS_PID_TYPE2_CHECKSUM, "RTPS_PID_TYPE2_CHECKSUM" },
211   { PID_METATRAFFIC_MULTICAST_IPADDRESS, "PID_METATRAFFIC_MULTICAST_IPADDRESS" },
212   { PID_APP_IPADDRESS, "PID_APP_IPADDRESS" },
213   { PID_METATRAFFIC_UNICAST_PORT, "PID_METATRAFFIC_UNICAST_PORT" },
214   { PID_USERDATA_UNICAST_PORT, "PID_USERDATA_UNICAST_PORT" },
215   { PID_IS_RELIABLE, "PID_IS_RELIABLE" },
216   { PID_EXPECTS_ACK, "PID_EXPECTS_ACK" },
217   { PID_USERDATA_MULTICAST_IPADDRESS, "PID_USERDATA_MULTICAST_IPADDRESS" },
218   { PID_MANAGER_KEY, "PID_MANAGER_KEY" },
219   { PID_SEND_QUEUE_SIZE, "PID_SEND_QUEUE_SIZE" },
220   { PID_RELIABILITY_ENABLED, "PID_RELIABILITY_ENABLED" },
221   { PID_PROTOCOL_VERSION, "PID_PROTOCOL_VERSION" },
222   { PID_VENDOR_ID, "PID_VENDOR_ID" },
223   { PID_VARGAPPS_SEQUENCE_NUMBER_LAST, "PID_VARGAPPS_SEQUENCE_NUMBER_LAST" },
224   { PID_RECV_QUEUE_SIZE, "PID_RECV_QUEUE_SIZE" },
225   { PID_RELIABILITY_OFFERED, "PID_RELIABILITY_OFFERED" },
226   { PID_RELIABILITY_REQUESTED, "PID_RELIABILITY_REQUESTED" },
227   { 0, NULL }
228 };
229
230 /* *********************************************************************** */
231
232
233 /* *********************************************************************** *
234  *                                                                         *
235  *                  Code to actually dissect the packets                   *
236  *                                                                         *
237  * *********************************************************************** */
238
239 static gboolean
240 dissect_rtps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
241 {
242   proto_item       *ti;
243   proto_tree       *rtps_tree=NULL;
244   gint             offset = 0;
245   gint             appKind;
246   proto_tree       *rtps_submessage_tree;
247   guint8           submessageId;
248   guint8           flags;
249   gboolean         little_endian;
250   int              next_submsg;
251   int              count_msg_type[11];
252   char             buff[200], buff_tmp[30];/* buffers */
253
254   /*  offset is the byte offset of 'tvb' at which the new tvbuff
255       should start.  The first byte is the 0th byte.             */
256
257   /* --- making disition if protocol is RTPS protocol --- */
258   if (!tvb_bytes_exist(tvb, offset, 4)) return FALSE;
259   if (tvb_get_guint8(tvb,offset++) != 'R') return FALSE;
260   if (tvb_get_guint8(tvb,offset++) != 'T') return FALSE;
261   if (tvb_get_guint8(tvb,offset++) != 'P') return FALSE;
262   if (tvb_get_guint8(tvb,offset++) != 'S') return FALSE;
263
264   /* --- Make entries in Protocol column ---*/
265   if (check_col(pinfo->cinfo, COL_PROTOCOL))
266    col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTPS");
267
268   if (check_col(pinfo->cinfo, COL_INFO))
269    col_clear(pinfo->cinfo, COL_INFO);
270
271   memset(count_msg_type, 0, sizeof(count_msg_type));
272
273   if (tree) {
274
275    /* create display subtree for the protocol */
276    ti = proto_tree_add_item(tree, proto_rtps, tvb, 0, -1, FALSE);
277    rtps_tree = proto_item_add_subtree(ti, ett_rtps);
278
279    /*  Protocol Version */
280    proto_tree_add_text(rtps_tree, tvb, offset, 2,
281                        "Protocol  RTPS, version %s",
282                        protocol_version_to_string(offset, tvb, buff));
283    offset +=2;
284
285    /*  Vendor Id  */
286    proto_tree_add_text(rtps_tree, tvb, offset, 2,
287                        "VendorId: %s",
288                        vendor_id_to_string(offset, tvb, buff));
289    offset +=2;
290
291    /*  Host Id  */
292    proto_tree_add_text(rtps_tree, tvb, offset, 4,
293                        "HostId:   %s",
294                        host_id_to_string(offset,tvb,buff));
295    offset +=4;
296
297    /*  App Id  */
298    proto_tree_add_text(rtps_tree, tvb, offset, 4,
299                        "App ID:   %s",
300                        app_id_to_string(offset, tvb, buff));
301
302   }
303
304   /*  offset behind RTPS's Header */
305   offset=16;
306
307   while (tvb_reported_length_remaining(tvb, offset) > 0) {
308     submessageId = tvb_get_guint8(tvb, offset);
309     if (submessageId & 0x80) {
310       ti = proto_tree_add_text(tree, tvb, offset, -1, "Submessage: %s",
311                                val_to_str(submessageId, submessage_id_vals,
312                                           "Vendor-specific (0x%02X)"));
313     } else {
314       ti = proto_tree_add_text(tree, tvb, offset, -1, "Submessage: %s",
315                                val_to_str(submessageId, submessage_id_vals,
316                                           "Unknown (0x%02X)"));
317     }
318     rtps_submessage_tree = proto_item_add_subtree(ti, ett_rtps_submessage);
319     if (submessageId & 0x80) {
320       proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_submessage_id,
321                                  tvb, offset, 1, submessageId,
322                                  "Submessage Id: Vendor-specific (0x%02x)",
323                                  submessageId);
324     } else {
325       proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_id,
326                           tvb, offset, 1, submessageId);
327     }
328
329     flags = tvb_get_guint8(tvb, offset + 1);
330     /*  E flag |XXXX|HAPE| => masks with 000000001b = 1  */
331     if ((flags & FLAG_E) != 0)      little_endian = TRUE;
332       else                          little_endian = FALSE;
333
334     next_submsg  = get_guint16(tvb, offset + 2, little_endian);
335     proto_item_set_len(ti, next_submsg);
336
337     switch (submessageId)
338     {
339       case PAD:
340         if (tree)
341           dissect_PAD(tvb, offset + 1, flags, next_submsg,
342                       rtps_submessage_tree);
343         count_msg_type[0]++;
344         break;
345       case VAR:
346         if (tree)
347           dissect_VAR(tvb, offset + 1, flags, little_endian, next_submsg,
348                       rtps_submessage_tree);
349         count_msg_type[1]++;
350         break;
351       case ISSUE:
352         if (tree)
353           dissect_ISSUE(tvb, offset + 1, flags, little_endian, next_submsg,
354                         rtps_submessage_tree);
355         count_msg_type[2]++;
356         break;
357       case ACK:
358         if (tree)
359           dissect_ACK(tvb, offset + 1, flags, little_endian, next_submsg,
360                       rtps_submessage_tree);
361         count_msg_type[3]++;
362         break;
363       case HEARTBEAT:
364         if (tree)
365           dissect_HEARTBEAT(tvb, offset + 1, flags, little_endian, next_submsg,
366                             rtps_submessage_tree);
367         count_msg_type[4]++;
368         break;
369       case GAP:
370         if (tree)
371           dissect_GAP(tvb, offset + 1, flags, little_endian, next_submsg,
372                       rtps_submessage_tree);
373         count_msg_type[5]++;
374         break;
375       case INFO_TS:
376         if (tree)
377           dissect_INFO_TS(tvb, offset + 1, flags, little_endian, next_submsg,
378                           rtps_submessage_tree);
379         count_msg_type[6]++;
380         break;
381       case INFO_SRC:
382         if (tree)
383           dissect_INFO_SRC(tvb, offset + 1, flags, little_endian, next_submsg,
384                            rtps_submessage_tree);
385         count_msg_type[7]++;
386         break;
387       case INFO_REPLY:
388         if (tree)
389           dissect_INFO_REPLY(tvb, offset + 1, flags, little_endian, next_submsg,
390                              rtps_submessage_tree);
391         count_msg_type[8]++;
392         break;
393       case INFO_DST:
394         if (tree)
395           dissect_INFO_DST(tvb, offset + 1, flags, next_submsg,
396                            rtps_submessage_tree);
397         count_msg_type[9]++;
398         break;
399       default:
400         if (tree) {
401           proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
402                               tvb, offset + 1, 1, flags);
403           proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
404                               tvb, offset + 2, 2, next_submsg);
405         }
406         break;
407      }
408
409      /* next submessage's offset */
410      offset += next_submsg+4;
411
412   }
413
414   /* --- and Info column on summary display ---*/
415
416   if (check_col(pinfo->cinfo, COL_INFO))
417   {
418     appKind = tvb_get_guint8(tvb, APP_KIND_BYTE);
419
420     if (appKind == MANAGEDAPPLICATION ) {sprintf(buff,"App: ");}
421     if (appKind == MANAGER)             {sprintf(buff,"Man: ");}
422     if (appKind == AID_UNKNOWN)         {sprintf(buff,"Unknown:");}
423
424     if (appKind != MANAGEDAPPLICATION  && appKind != MANAGER &&
425         appKind != AID_UNKNOWN)         {sprintf(buff,"ERROR in APP type");}
426
427    /* -- counts of submessages - for Information Frame */
428    if (count_msg_type[0]>0) {
429        sprintf(buff_tmp,"PAD(%d) ",count_msg_type[0]);
430        strcat(buff,buff_tmp);
431    }
432
433    if (count_msg_type[1]>0) {
434        sprintf(buff_tmp,"VAR(%d) ",count_msg_type[1]);
435        strcat(buff,buff_tmp);
436    }
437
438    if (count_msg_type[2]>0) {
439        sprintf(buff_tmp,"ISSUE(%d) ",count_msg_type[2]);
440        strcat(buff,buff_tmp);
441    }
442
443    if (count_msg_type[3]>0) {
444        sprintf(buff_tmp,"ACK(%d) ",count_msg_type[3]);
445        strcat(buff,buff_tmp);
446    }
447
448    if (count_msg_type[4]>0) {
449        sprintf(buff_tmp,"HEARTBEAT(%d) ",count_msg_type[4]);
450        strcat(buff,buff_tmp);
451    }
452
453    if (count_msg_type[5]>0) {
454        sprintf(buff_tmp,"GAP(%d) ",count_msg_type[5]);
455        strcat(buff,buff_tmp);
456    }
457
458    if (count_msg_type[6]>0) {
459        sprintf(buff_tmp,"INFO_TS(%d) ",count_msg_type[6]);
460        strcat(buff,buff_tmp);
461    }
462
463    if (count_msg_type[7]>0) {
464        sprintf(buff_tmp, "INFO_SRC(%d) ",count_msg_type[7]);
465        strcat(buff,buff_tmp);
466    }
467
468    if (count_msg_type[8]>0) {
469        sprintf(buff_tmp,"INFO_REPLY(%d) ",count_msg_type[8]);
470        strcat(buff,buff_tmp);
471    }
472
473    if (count_msg_type[9]>0) {
474        sprintf(buff_tmp,"INFO_DST(%d) ",count_msg_type[9]);
475        strcat(buff,buff_tmp);
476    }
477
478    if (count_msg_type[10]>0) {
479        sprintf(buff_tmp,"vendor specific(%d) ",count_msg_type[10]);
480        strcat(buff,buff_tmp);
481    }
482
483    col_add_fstr(pinfo->cinfo, COL_INFO, buff);
484
485   }
486
487
488   return TRUE;
489
490 }  /* end dissect_rtps(...) */
491
492 /* *********************************************************************** */
493
494
495 /* *********************************************************************** *
496  *                                                                         *
497  *                        get 16 bit from the stream                       *
498  *                                                                         *
499  * *********************************************************************** */
500
501 static guint16  get_guint16(tvbuff_t *tvb, gint offset, gboolean little_endian)
502 {
503   guint16   value;
504
505   if (little_endian)
506     value = tvb_get_letohs(tvb, offset);
507   else
508     value = tvb_get_ntohs(tvb, offset);
509
510   return(value);
511 }
512
513 /* *********************************************************************** */
514
515
516 /* *********************************************************************** *
517  *                                                                         *
518  *                          get 32 bit from the stream                     *
519  *                                                                         *
520  * *********************************************************************** */
521
522 static guint32  get_guint32(tvbuff_t *tvb, gint offset, gboolean little_endian)
523 {
524   guint32     value;
525
526   if (little_endian)
527     value = tvb_get_letohl(tvb, offset);
528   else
529     value = tvb_get_ntohl(tvb, offset);
530
531   return(value);
532 }
533
534 /* *********************************************************************** */
535
536
537 /* *********************************************************************** *
538  *                                                                         *
539  *                               get Protocol version                      *
540  *                                                                         *
541  * *********************************************************************** */
542
543 static char *
544 protocol_version_to_string(gint offset,tvbuff_t *tvb,char *buff)
545 {
546   guint8            major, minor;
547
548   /* protocol verzion = major.minor */
549    major = tvb_get_guint8(tvb, offset);
550    minor = tvb_get_guint8(tvb, (offset+1));
551
552    sprintf(buff,"%d.%d", major, minor);
553    return(buff);
554
555 }
556
557 /* *********************************************************************** */
558
559
560 /* *********************************************************************** *
561  *                                                                         *
562  *                               get Vendor Id                             *
563  *                                                                         *
564  * *********************************************************************** */
565
566 static char *
567 vendor_id_to_string(gint offset, tvbuff_t *tvb, char *buff)
568 {
569   guint8              major, minor;
570   VendorId            vendorId_rti;
571
572   VENDOR_ID_RTI(vendorId_rti);
573
574   major = tvb_get_guint8(tvb, offset);
575   minor = tvb_get_guint8(tvb, (offset+1));
576
577   if (major == vendorId_rti.major &&
578       minor == vendorId_rti.minor)
579   { sprintf(buff,"Real-Time Innovations,Inc.,CA,USA");
580     return(buff); }
581
582   sprintf(buff,"Vendor unknown");
583   return(buff);
584 }
585
586 /* *********************************************************************** */
587
588
589 /* *********************************************************************** *
590  *                                                                         *
591  *                               get IP Address                            *
592  *                                                                         *
593  * *********************************************************************** */
594
595 static char *
596 IP_to_string(gint offset,tvbuff_t *tvb,gboolean little_endian,char buff[])
597 {
598   IPAddress         ip;
599   guint8  a = 0, b = 0, c = 0, d = 0; /* IP Adresss = a.b.c.d */
600
601   ip = get_guint32(tvb, offset, little_endian);
602      /* get_guint32() - reads + endian conversion */
603   a = (ip >> 24);
604   b = (ip >> 16) & 0xff;
605   c = (ip >>  8) & 0xff;
606   d =  ip & 0xff;
607
608   sprintf(buff,"%d.%d.%d.%d", a, b, c, d);
609   return(buff);
610 }
611
612 /* *********************************************************************** */
613
614
615 /* *********************************************************************** *
616  *                                                                         *
617  *                               get Port                                  *
618  *                                                                         *
619  * *********************************************************************** */
620
621 static char *
622 port_to_string(gint offset,tvbuff_t *tvb,gboolean little_endian,char buff[])
623 {
624   Port port = get_guint32(tvb, offset, little_endian);
625             /* get_guint32() - reads + endian conversion */
626
627   if (port == PORT_INVALID)
628     sprintf(buff,"PORT_INVALID");
629   else
630     sprintf(buff,"0x%X",port);
631
632   return(buff);
633 }
634
635 /* *********************************************************************** */
636
637
638 /* *********************************************************************** *
639  *                                                                         *
640  *                                get NTP Time                             *
641  *                                                                         *
642  * *********************************************************************** */
643
644 static char *
645 get_NtpTime(gint offset,tvbuff_t *tvb,gboolean little_endian,char buff[])
646 {
647   NtpTime         ntpTime;
648   float           time;
649
650   /* get_guint32() - reads + endian conversion */
651   ntpTime.seconds  =  get_guint32(tvb, offset, little_endian);
652   ntpTime.fraction =  get_guint32(tvb, (offset + 4), little_endian);
653   time = (float) ntpTime.seconds + (ntpTime.fraction / 2^(32));
654
655   sprintf(buff,"%f", time);
656   return(buff);
657 }
658
659 /* *********************************************************************** */
660
661
662 /* *********************************************************************** *
663  *                                                                         *
664  *                                get Host Id                              *
665  *                                                                         *
666  * *********************************************************************** */
667
668 static char *
669 host_id_to_string(gint offset,tvbuff_t *tvb, char buff[])
670 {
671   guint32       hostId = tvb_get_ntohl(tvb, offset);
672   /* get_ntohl() automaticaly convert data to BIG ENDIAN */
673
674   sprintf(buff,"0x%X", hostId);
675   return(buff);
676 }
677
678 /* *********************************************************************** */
679
680
681 /* *********************************************************************** *
682  *                                                                         *
683  *                                get AppID                                *
684  *                                                                         *
685  * *********************************************************************** */
686
687 static char *
688 app_id_to_string(gint offset,tvbuff_t *tvb,char buff[])
689 {
690   guint32        appId = tvb_get_ntohl(tvb, offset);
691   /* get_ntohl() automaticaly convert data to BIG ENDIAN */
692
693   /* Instance Id */
694   guint32        instanceId = (appId >> 8);
695   /* applicatin Kind */
696   guint8         appKind    = (appId & 0xff);
697
698   if (appKind == MANAGEDAPPLICATION)
699   {
700     sprintf(buff,"Managed App, InstanceId: 0x%X",instanceId);
701     return(buff);
702   }
703
704   if (appKind == MANAGER)
705   {
706     sprintf(buff,"Manager, InstanceId: 0x%X",instanceId);
707     return(buff);
708   }
709
710   sprintf(buff,"Unknown");
711   return(buff);
712
713 }
714
715 /* *********************************************************************** */
716
717
718 /* *********************************************************************** *
719  *                                                                         *
720  *                         get Object_Id (32 bit)                          *
721  *                                                                         *
722  * *********************************************************************** */
723
724 static char *
725 object_id_to_string(gint offset, tvbuff_t *tvb, char buff[])
726 {
727   guint32        objectId = tvb_get_ntohl(tvb, offset);
728   /* get_ntohl() automaticaly convert data to BIG ENDIAN */
729
730   if (objectId == OID_UNKNOWN)      { sprintf(buff,"Unknown ObjectId");
731                                       return(buff);}
732   if (objectId == OID_APP)          { sprintf(buff,"applicationSelf");
733                                       return(buff);}
734   if (objectId == OID_WRITE_APPSELF){ sprintf(buff,"writerApplicationSelf");
735                                       return(buff);}
736   if (objectId == OID_WRITE_APP)    { sprintf(buff,"writerApplications");
737                                       return(buff);}
738   if (objectId == OID_READ_APP)     { sprintf(buff,"readerApplications");
739                                       return(buff);}
740   if (objectId == OID_WRITE_MGR)    { sprintf(buff,"writerManagers");
741                                       return(buff);}
742   if (objectId == OID_READ_MGR)     { sprintf(buff,"readerManagers ");
743                                       return(buff);}
744   if (objectId == OID_WRITE_PUBL)   { sprintf(buff,"writerPublications");
745                                       return(buff);}
746   if (objectId == OID_READ_PUBL)    { sprintf(buff,"readerPublications");
747                                       return(buff);}
748   if (objectId == OID_WRITE_SUBS)   { sprintf(buff,"writerSubscriptions");
749                                       return(buff);}
750   if (objectId == OID_READ_SUBS)    { sprintf(buff,"readerSubscriptions");
751                                       return(buff);}
752
753   /* nothing from the possibilites above */
754   sprintf(buff,"instanceId: 0x%X, objKind: 0x%X",
755                (objectId >> 8),(objectId & 0xff));
756   return(buff);
757
758 /* for the future
759 //Kind
760 #define OID_APPLICATION      0x01
761 #define OID_CSTWRITER        0x02
762 #define OID_PUBLICATION      0x03
763 #define OID_SUBSCRIPTION     0x04
764 #define OID_CSTREADER        0x07
765 //
766 #define OID_USEROBJ          0x00
767 #define OID_RESUSEROBJ       0x40
768 #define OID_METAOBJ          0x80
769 #define OID_RESMETAOBJ       0xC0
770 */
771 }
772
773 /* *********************************************************************** */
774
775
776 /* *********************************************************************** *
777  *                                                                         *
778  *                      get Sequence Number (64 bit)                       *
779  *                                                                         *
780  * *********************************************************************** */
781
782 static gint
783 seq_nr_to_string(gint offset, gboolean little_endian, tvbuff_t *tvb,
784                  SequenceNumber *p_seqNumber)
785 {
786    p_seqNumber->high = get_guint32(tvb, offset, little_endian);
787    p_seqNumber->low  = get_guint32(tvb, offset + 4, little_endian);
788
789    return(1);
790 }
791
792 /* *********************************************************************** */
793
794
795 /* *********************************************************************** *
796  *                                                                         *
797  *                                get_Bitmap                               *
798  *                                                                         *
799  * *********************************************************************** */
800
801 static void
802 get_bitmap(tvbuff_t *tvb, gint *p_offset, gboolean little_endian,
803            gint next_submsg, proto_tree *tree)
804 {
805   proto_item             *ti;
806   proto_tree             *rtps_bitmap_tree;
807   gint                    i = 0;
808   gint                    offset = *p_offset;
809   SequenceNumber          sequenceNumber;
810   guint32                 num_bits;
811   guint                   num_longs;
812
813   /* making subtree for the bitmap */
814   ti = proto_tree_add_text(tree,tvb,offset,(next_submsg-offset),"Bitmap");
815   rtps_bitmap_tree = proto_item_add_subtree(ti, ett_rtps_bitmap);
816
817   /* SekvenceNumber bitmapBase */
818   seq_nr_to_string(offset, little_endian, tvb, &sequenceNumber);
819   proto_tree_add_text(rtps_bitmap_tree, tvb, offset, 8,
820                       "bitmapBase:  0x%X%X",
821                       sequenceNumber.high, sequenceNumber.low);
822   offset +=8;
823
824   num_bits = get_guint32(tvb, offset, little_endian);
825   proto_tree_add_text(rtps_bitmap_tree, tvb, offset, 4,
826                       "numBits:     %u",
827                       num_bits);
828   offset += 4;
829
830   if (num_bits+31 < num_bits)
831     num_longs = UINT_MAX; /* overflow */
832   else
833     num_longs = (num_bits+31)/32;
834   while (num_longs != 0)
835   {
836     if (next_submsg-offset < 4)
837     {
838       proto_tree_add_text(rtps_bitmap_tree, tvb, offset, next_submsg-offset,
839                           "bitmap[%d]:   < 4 bytes remain in message", i);
840       offset = next_submsg;
841       break;
842     }
843     proto_tree_add_text(rtps_bitmap_tree, tvb, offset, 4,
844                         "bitmap[%d]:   0x%08X",
845                         i, get_guint32(tvb, offset, little_endian));
846     offset +=4;
847     ++i;
848     --num_longs;
849   }  /* end while */
850
851   *p_offset = offset;
852 }
853
854 /* *********************************************************************** */
855
856
857 /* *********************************************************************** *
858  *                                                                         *
859  *                          dissect submessage: PAD                        *
860  *                                                                         *
861  *           (this submessage has no meaning and it is always valid)       *
862  * *********************************************************************** */
863
864 static void
865 dissect_PAD(tvbuff_t *tvb, gint offset, guint8 flags,
866             int next_submsg_offset, proto_tree *rtps_submessage_tree)
867 {
868   proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
869                       tvb, offset, 1, flags);
870   offset += 1;
871
872   proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
873                       tvb, offset, 2, next_submsg_offset);
874   offset +=2;
875   next_submsg_offset += offset;
876 }
877
878 /* *********************************************************************** */
879
880
881 /* *********************************************************************** *
882  *                                                                         *
883  *                          dissect submessage: VAR                        *
884  *                                                                         *
885  * *********************************************************************** */
886
887 static void
888 dissect_VAR(tvbuff_t *tvb, gint offset, guint8 flags, gboolean little_endian,
889             int next_submsg_offset, proto_tree *rtps_submessage_tree)
890 {
891   int                min_len;
892   char               buff[200];
893   SequenceNumber     writerSeqNumber;
894
895   proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
896                       tvb, offset, 1, flags);
897   offset +=1;
898
899   min_len = 20;
900   if ((flags & FLAG_H) != 0)
901     min_len += 8;
902   if ((flags & FLAG_P) != 0)
903     min_len += 4;
904   if (next_submsg_offset < min_len)
905   {
906     proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
907                                tvb, offset, 2, next_submsg_offset,
908                                "Octets to next header: %u (bogus, must be >= %u)",
909                                next_submsg_offset, min_len);
910     return;
911   }
912   proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
913                       tvb, offset, 2, next_submsg_offset);
914   offset +=2;
915   next_submsg_offset += offset;
916
917   /*  readerObjectId*/
918   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
919                       "Reader Object ID:   %s ",
920                        object_id_to_string(offset, tvb, buff));
921   offset +=4;
922
923   /*  writerObjectId*/
924   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
925                       "Writer Object ID:   %s ",
926                       object_id_to_string(offset, tvb, buff));
927   offset+=4;
928
929   /*  H flag |XXXX|HAPE| => masks with 00001000b = 8 */
930   if ((flags & FLAG_H) != 0)
931   {
932     /*  HostId */
933     proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
934                         "Host ID:            %s",
935                         host_id_to_string(offset,tvb,buff));
936     offset+=4;
937
938     /*  App Id  */
939     proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
940                         "App ID:             %s",
941                         app_id_to_string(offset, tvb, buff));
942     offset +=4;
943   }
944
945   /* Object Id */
946   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
947                       "Object ID:          %s ",
948                       object_id_to_string(offset, tvb, buff));
949   offset +=4;
950
951   /*  WriterSequence Number */
952   seq_nr_to_string(offset, little_endian, tvb, &writerSeqNumber);
953   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 8,
954                       "WriterSeqNumber:    0x%X%X",
955                       writerSeqNumber.high, writerSeqNumber.low);
956   offset +=8;
957
958   /*  P flag |XXXX|HAPE| => masks with 00000010b = 2 */
959   if ((flags & FLAG_P) != 0)
960   {
961     get_parameter_sequence(tvb, &offset, little_endian, next_submsg_offset,
962                            rtps_submessage_tree);
963   }
964 }
965
966 /* *********************************************************************** */
967
968 /* *********************************************************************** *
969  *                                                                         *
970  *                            get_ParameterSequence                        *
971  *                                                                         *
972  * *********************************************************************** */
973
974
975 static void
976 get_parameter_sequence(tvbuff_t *tvb, gint *p_offset, gboolean little_endian,
977                        gint next_submsg_offset, proto_tree *tree)
978 {
979   proto_item             *ti;
980   proto_tree             *rtps_parameter_sequence_tree;
981   proto_tree             *rtps_parameter_tree;
982   gint                    offset = *p_offset;
983   guint16                 parameter, param_length;
984   gint                    str_length;
985   SequenceNumber          seqNumber;
986   char                    buff_tmp[MAX_PATHNAME];
987   int                     i;
988   char                    sep;
989
990   ti = proto_tree_add_text(tree, tvb, offset, (next_submsg_offset - offset),
991                       "Parameters:");
992   rtps_parameter_sequence_tree = proto_item_add_subtree(ti,
993                                                         ett_rtps_parameter_sequence);
994   for (;;)
995   {
996     if (next_submsg_offset-offset < 2)
997     {
998       proto_tree_add_text(rtps_parameter_sequence_tree, tvb, offset,
999                           next_submsg_offset-offset,
1000                           "Parameter: < 2 bytes remain in message");
1001       offset = next_submsg_offset;
1002       break;
1003     }
1004     parameter    = get_guint16(tvb, offset, little_endian);
1005     ti = proto_tree_add_text(rtps_parameter_sequence_tree, tvb, offset, 2,
1006                              "%s",
1007                              val_to_str(parameter, parameter_id_vals,
1008                                         "Unknown parameter (0x%04X)"));
1009     rtps_parameter_tree = proto_item_add_subtree(ti, ett_rtps_parameter);
1010     proto_tree_add_uint(rtps_parameter_tree, hf_rtps_parameter_id,
1011                         tvb, offset, 2, parameter);
1012     offset +=2;
1013     if (next_submsg_offset-offset < 2)
1014     {
1015       proto_tree_add_text(rtps_parameter_tree, tvb, offset,
1016                           next_submsg_offset-offset,
1017                           "Parameter length: < 2 bytes remain in message");
1018       offset = next_submsg_offset;
1019       proto_item_set_end(ti, tvb, offset);
1020       break;
1021     }
1022     param_length = get_guint16(tvb, offset, little_endian);
1023     proto_tree_add_uint(rtps_parameter_tree, hf_rtps_parameter_length,
1024                         tvb, offset, 2, param_length);
1025     offset +=2;
1026
1027     if (parameter == PID_SENTINEL) {
1028       proto_item_set_end(ti, tvb, offset);
1029       break;
1030     }
1031
1032     if (next_submsg_offset-offset < param_length)
1033     {
1034       proto_tree_add_text(rtps_parameter_tree, tvb, offset,
1035                           next_submsg_offset-offset,
1036                           "Parameter value: < %u bytes remain in message",
1037                           param_length);
1038       offset = next_submsg_offset;
1039       proto_item_set_end(ti, tvb, offset);
1040       break;
1041     }
1042     proto_item_set_end(ti, tvb, offset + param_length);
1043
1044     switch (parameter)
1045     {
1046       case PID_PAD:
1047         proto_item_append_text(ti, ": -");
1048         proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1049                             "Padding");
1050         break;
1051
1052       case PID_EXPIRATION_TIME:
1053         if (param_length < 8)
1054         {
1055           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1056                               "Bad parameter: length < 8");
1057         }
1058         else
1059         {
1060           char *ntp_time_str;
1061
1062           ntp_time_str = get_NtpTime(offset, tvb, little_endian,buff_tmp);
1063           proto_item_append_text(ti, ": %s", ntp_time_str);
1064           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1065                               "Expiration time: %s", ntp_time_str);
1066         }
1067         break;
1068
1069       case PID_PERSISTENCE:
1070         if (param_length < 8)
1071         {
1072           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1073                               "Bad parameter: length < 8");
1074         }
1075         else
1076         {
1077           char *ntp_time_str;
1078
1079           ntp_time_str = get_NtpTime(offset, tvb, little_endian,buff_tmp);
1080           proto_item_append_text(ti, ": %s", ntp_time_str);
1081           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1082                               "Persistence: %s", ntp_time_str);
1083         }
1084         break;
1085
1086       case PID_MINIMUM_SEPARATION:
1087         if (param_length < 8)
1088         {
1089           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1090                               "Bad parameter: length < 8");
1091         }
1092         else
1093         {
1094           char *ntp_time_str;
1095
1096           ntp_time_str = get_NtpTime(offset, tvb, little_endian,buff_tmp);
1097           proto_item_append_text(ti, ": %s", ntp_time_str);
1098           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1099                               "Minimum separation: %s", ntp_time_str);
1100         }
1101         break;
1102
1103       case PID_TOPIC: /* --- ?? funguje spravne ?? */
1104         str_length = tvb_strnlen(tvb, offset, param_length);
1105         if (str_length == -1)
1106         {
1107           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1108                               "Bad parameter: Terminating zero missing");
1109         }
1110         else
1111         {
1112           char *str;
1113
1114           str = tvb_format_text(tvb, offset, str_length);
1115           proto_item_append_text(ti, ": %s", str);
1116           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1117                               "Topic: %s", str);
1118         }
1119         break;   
1120
1121       case PID_STRENGTH:
1122         if (param_length < 4)
1123         {
1124           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1125                               "Bad parameter: length < 4");
1126         }
1127         else
1128         {
1129           guint32 strength;
1130
1131           strength = get_guint32(tvb, offset, little_endian);
1132           proto_item_append_text(ti, ": 0x%X", strength);
1133           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1134                               "Strength: 0x%X", strength);
1135         }
1136         break;
1137
1138       case PID_TYPE_NAME: /* --- ?? funguje spravne ?? */
1139         str_length = tvb_strnlen(tvb, offset, param_length);
1140         if (str_length == -1)
1141         {
1142           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1143                               "Bad parameter: Terminating zero missing");
1144         }
1145         else
1146         {
1147           char *str;
1148
1149           str = tvb_format_text(tvb, offset, str_length);
1150           proto_item_append_text(ti, ": %s", str);
1151           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1152                               "Type name: %s", str);
1153         }
1154         break;   
1155
1156       case PID_TYPE_CHECKSUM:
1157         /* nacitam jako UNSIGNED - nemuze to byt i zaporne cislo?? */
1158         if (param_length < 4)
1159         {
1160           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1161                               "Bad parameter: length < 4");
1162         }
1163         else
1164         {
1165           guint32 checksum;
1166
1167           checksum = get_guint32(tvb, offset, little_endian);
1168           proto_item_append_text(ti, ": 0x%X", checksum);
1169           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1170                               "Checksum: 0x%X", checksum);
1171         }
1172         break;
1173
1174       case RTPS_PID_TYPE2_NAME:
1175         proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1176                             "Parameter data");
1177         break;
1178                           
1179       case RTPS_PID_TYPE2_CHECKSUM:
1180         proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1181                             "Parameter data");
1182         break;
1183
1184       case PID_METATRAFFIC_MULTICAST_IPADDRESS:
1185         i = 0;
1186         sep = ':';
1187         while (param_length >= 4)
1188         {
1189           char *ip_string;
1190
1191           ip_string = IP_to_string(offset, tvb, little_endian,buff_tmp);
1192           proto_item_append_text(ti, "%c %s", sep, ip_string);
1193           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1194                               "Address[%d]: %s", i, ip_string);
1195           ++i;
1196           offset +=4;
1197           sep = ',';
1198           param_length -= 4; /* decrement count */       
1199         }
1200         offset += param_length;
1201         break;
1202
1203       case PID_APP_IPADDRESS:
1204         i = 0;
1205         sep = ':';
1206         while (param_length >= 4)
1207         {
1208           char *ip_string;
1209
1210           ip_string = IP_to_string(offset, tvb, little_endian,buff_tmp);
1211           proto_item_append_text(ti, "%c %s", sep, ip_string);
1212           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1213                               "Address[%d]: %s", i, ip_string);
1214           ++i;
1215           offset +=4;
1216           sep = ',';
1217           param_length -= 4; /* decrement count */       
1218         }
1219         offset += param_length;
1220         break;
1221
1222       case PID_METATRAFFIC_UNICAST_PORT:
1223         if (param_length < 4)
1224         {
1225           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1226                               "Bad parameter: length < 4");
1227         }
1228         else
1229         {
1230           char *port_str;
1231
1232           port_str = port_to_string(offset, tvb, little_endian,buff_tmp);
1233           proto_item_append_text(ti, ": %s", port_str);
1234           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1235                               "Port: %s", port_str);
1236         }
1237         break;
1238
1239       case PID_USERDATA_UNICAST_PORT:
1240         if (param_length < 4)
1241         {
1242           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1243                               "Bad parameter: length < 4");
1244         }
1245         else
1246         {
1247           char *port_str;
1248
1249           port_str = port_to_string(offset, tvb, little_endian,buff_tmp);
1250           proto_item_append_text(ti, ": %s", port_str);
1251           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1252                               "Port: %s", port_str);
1253         }
1254         break;
1255
1256       case PID_EXPECTS_ACK:
1257         if (param_length < 1)
1258         {
1259           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1260                               "Bad parameter: length < 1");
1261         }
1262         else
1263         {
1264           if (tvb_get_guint8(tvb, offset) == 0)
1265           {
1266             proto_item_append_text(ti, ": No");
1267             proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1268                                 "ACK expected: No");
1269           }
1270           else
1271           {
1272             proto_item_append_text(ti, ": Yes");
1273             proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1274                                 "ACK expected: Yes");
1275           }
1276         }
1277         break;
1278
1279       case PID_USERDATA_MULTICAST_IPADDRESS:
1280         i = 0;
1281         sep = ':';
1282         while (param_length >= 4)
1283         {
1284           char *ip_string;
1285
1286           ip_string = IP_to_string(offset, tvb, little_endian,buff_tmp);
1287           proto_item_append_text(ti, "%c %s", sep, ip_string);
1288           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1289                               "Address[%d]: %s", i, ip_string);
1290           ++i;
1291           offset +=4;
1292           param_length -= 4; /* decrement count */       
1293         }
1294         offset += param_length;
1295         break;
1296
1297       case PID_MANAGER_KEY:
1298         i = 0;
1299         sep = ':';
1300         while (param_length >= 4)
1301         {
1302           guint32 manager_key;
1303
1304           manager_key = get_guint32(tvb, offset, little_endian);
1305           proto_item_append_text(ti, "%c 0x%X", sep, manager_key);
1306           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1307                               "Key[%d]: 0x%X", i, manager_key);
1308           ++i;
1309           offset +=4;
1310           sep = ',';
1311           param_length -= 4; /* decrement count */       
1312         }
1313         offset += param_length;
1314         break;
1315
1316       case PID_SEND_QUEUE_SIZE:
1317         if (param_length < 4)
1318         {
1319           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1320                               "Bad parameter: length < 4");
1321         }
1322         else
1323         {
1324           guint32 send_queue_size;
1325
1326           send_queue_size = get_guint32(tvb, offset, little_endian);
1327           proto_item_append_text(ti, ": %u", send_queue_size);
1328           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1329                               "Send queue size: %u", send_queue_size);
1330         }
1331         break;
1332
1333       case PID_PROTOCOL_VERSION:
1334         if (param_length < 2)
1335         {
1336           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1337                               "Bad parameter: length < 2");
1338         }
1339         else
1340         {
1341           char *protocol_version_str;
1342
1343           protocol_version_str = protocol_version_to_string(offset, tvb, buff_tmp);
1344           proto_item_append_text(ti, ": %s", protocol_version_str);
1345           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1346                               "Protocol version: %s", protocol_version_str);
1347         }
1348         break;
1349
1350       case PID_VENDOR_ID:
1351         if (param_length < 2)
1352         {
1353           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1354                               "Bad parameter: length < 2");
1355         }
1356         else
1357         {
1358           char *vendor_id_str;
1359
1360           vendor_id_str = vendor_id_to_string(offset, tvb, buff_tmp);
1361           proto_item_append_text(ti, ": %s", vendor_id_str);
1362           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1363                               "Vendor ID: %s", vendor_id_str);
1364         }
1365         break;
1366
1367       case PID_VARGAPPS_SEQUENCE_NUMBER_LAST:
1368         if (param_length < 8)
1369         {
1370           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1371                               "Bad parameter: length < 8");
1372         }
1373         else
1374         {
1375           seq_nr_to_string(offset, little_endian, tvb, &seqNumber);
1376           proto_item_append_text(ti, ": 0x%X%X",
1377                                  seqNumber.high, seqNumber.low);
1378           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1379                               "Sequence number: 0x%X%X",
1380                               seqNumber.high, seqNumber.low);
1381         }
1382         break;
1383
1384       case PID_RECV_QUEUE_SIZE:
1385         if (param_length < 4)
1386         {
1387           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1388                               "Bad parameter: length < 4");
1389         }
1390         else
1391         {
1392           guint32 recv_queue_size;
1393
1394           recv_queue_size = get_guint32(tvb, offset, little_endian);
1395           proto_item_append_text(ti, ": %u", recv_queue_size);
1396           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1397                               "Receive queue size: %u", recv_queue_size);
1398         }
1399         break;
1400
1401       case PID_RELIABILITY_OFFERED:
1402         if (param_length < 4)
1403         {
1404           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1405                               "Bad parameter: length < 4");
1406         }
1407         else
1408         {
1409           guint32 reliability_offered;
1410
1411           reliability_offered = get_guint32(tvb, offset, little_endian);
1412           proto_item_append_text(ti, ": 0x%X", reliability_offered);
1413           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1414                               "Reliability offered: 0x%X", reliability_offered);
1415         }
1416         break;
1417
1418       case PID_RELIABILITY_REQUESTED:
1419         if (param_length < 4)
1420         {
1421           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1422                               "Bad parameter: length < 4");
1423         }
1424         else
1425         {
1426           guint32 reliability_requested;
1427
1428           reliability_requested = get_guint32(tvb, offset, little_endian);
1429           proto_item_append_text(ti, ": 0x%X", reliability_requested);
1430           proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1431                               "Reliability requested: 0x%X", reliability_requested);
1432         }
1433         break;
1434
1435       default:
1436         proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
1437                             "Unknown parameter value");
1438         break;
1439     }   /* end switch */
1440
1441     offset += param_length;
1442   }
1443
1444   *p_offset = offset;
1445 }
1446
1447 /* *********************************************************************** */
1448
1449
1450 /* *********************************************************************** *
1451  *                                                                         *
1452  *                  subdissector for submessage: ISSUE                     *
1453  *                                                                         *
1454  * *********************************************************************** */
1455  /* hotovo 12.01.04 - JEN OTESTOVAT :] */
1456 static void
1457 dissect_ISSUE(tvbuff_t *tvb, gint offset, guint8 flags,
1458               gboolean little_endian, int next_submsg_offset,
1459               proto_tree *rtps_submessage_tree)
1460 {
1461   int                       min_len;
1462   char                      buff[40];
1463   SequenceNumber            sequenceNumber;      /*  type struct  */
1464
1465   proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
1466                       tvb, offset, 1, flags);
1467   offset +=1;
1468
1469   min_len = 16;
1470   if ((flags & FLAG_P) != 0)
1471     min_len += 4;
1472   if (next_submsg_offset < min_len)
1473   {
1474     proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
1475                                tvb, offset, 2, next_submsg_offset,
1476                                "Octets to next header: %u (bogus, must be >= %u)",
1477                                next_submsg_offset, min_len);
1478     return;
1479   }
1480   proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
1481                       tvb, offset, 2, next_submsg_offset);
1482   offset +=2;
1483   next_submsg_offset += offset;
1484
1485   /*  Reader Object ID  */
1486   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
1487                       "Reader Object ID: %s ",
1488                       object_id_to_string(offset, tvb, buff));
1489   offset +=4;
1490
1491   /*  Writer Object ID */
1492   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
1493                       "Writer Object ID: %s ",
1494                       object_id_to_string(offset, tvb, buff));
1495   offset +=4;
1496
1497   /*  Sequence Number */
1498   seq_nr_to_string(offset, little_endian, tvb, &sequenceNumber);
1499   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 8,
1500                       "firstSeqNumber:   0x%X%X",
1501                       sequenceNumber.high, sequenceNumber.low);
1502   offset += 8;
1503
1504   /*  Parameters */
1505 /* *********************************************************************** *
1506  *              - for future extension of the protocol - in                *
1507  *                implementation of RTPS 1.0 can ignore the content        *
1508  * *********************************************************************** */
1509
1510   /* -- P flag |XXXX|HAPE| => masks with 00000010b = 2 */
1511   if ((flags & FLAG_P) != 0)
1512   {
1513     get_parameter_sequence(tvb, &offset, little_endian, next_submsg_offset,
1514                            rtps_submessage_tree);
1515   }
1516
1517   /*  Issue Data */
1518   proto_tree_add_item(rtps_submessage_tree, hf_rtps_issue_data, tvb,
1519                       offset, (next_submsg_offset - offset), FALSE);
1520
1521 }
1522
1523 /* *********************************************************************** */
1524
1525
1526 /* *********************************************************************** *
1527  *                                                                         *
1528  *                  subdissector for submessage: ACK                       *
1529  *                                                                         *
1530  * *********************************************************************** */
1531  /* hotovo 12.01.04 - JEN OTESTOVAT :] */
1532 static void
1533 dissect_ACK(tvbuff_t *tvb, gint offset, guint8 flags,
1534             gboolean little_endian, int next_submsg_offset,
1535             proto_tree *rtps_submessage_tree)
1536 {
1537   char                    buff[40];
1538
1539   proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
1540                       tvb, offset, 1, flags);
1541   offset +=1;
1542
1543   if (next_submsg_offset < 20)
1544   {
1545     proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
1546                                tvb, offset, 2, next_submsg_offset,
1547                                "Octets to next header: %u (bogus, must be >= 20)",
1548                                next_submsg_offset);
1549     return;
1550   }
1551   proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
1552                       tvb, offset, 2, next_submsg_offset);
1553   offset +=2;
1554   next_submsg_offset += offset;
1555
1556   /*  Reader Object ID  */
1557   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
1558                       "Reader Object ID:   %s ",
1559                       object_id_to_string(offset, tvb, buff));
1560   offset +=4;
1561
1562   /*  Writer Object ID  */
1563   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
1564                       "Writer Object ID:   %s ",
1565                       object_id_to_string(offset, tvb, buff));
1566   offset +=4;
1567
1568   get_bitmap(tvb,&offset,little_endian,next_submsg_offset,rtps_submessage_tree);
1569
1570 }
1571
1572 /* *********************************************************************** */
1573
1574
1575 /* *********************************************************************** *
1576  *                                                                         *
1577  *                subdissector for submessage: HEARTBEAT                   *
1578  *                                                                         *
1579  * *********************************************************************** */
1580  /* hotovo 12.01.04 - JEN OTESTOVAT :] */
1581 static void
1582 dissect_HEARTBEAT(tvbuff_t *tvb, gint offset, guint8 flags,
1583                   gboolean little_endian, int next_submsg_offset,
1584                   proto_tree *rtps_submessage_tree)
1585 {
1586   char                buff[40];
1587   SequenceNumber     sequenceNumber;      /* type struct  */
1588
1589   proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
1590                       tvb, offset, 1, flags);
1591   offset +=1;
1592
1593   if (next_submsg_offset < 24)
1594   {
1595     proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
1596                                tvb, offset, 2, next_submsg_offset,
1597                                "Octets to next header: %u (bogus, must be >= 24)",
1598                                next_submsg_offset);
1599     return;
1600   }
1601   proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
1602                       tvb, offset, 2, next_submsg_offset);
1603   offset +=2;
1604   next_submsg_offset += offset;
1605
1606   /* Reader Object ID */
1607   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
1608                       "Reader Object ID:   %s ",
1609                       object_id_to_string(offset, tvb, buff));
1610   offset +=4;
1611
1612   /* Writer Object ID */
1613   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
1614                       "Writer Object ID:   %s ",
1615                           object_id_to_string(offset, tvb, buff));
1616   offset +=4;
1617
1618   /*  firstSeqNumber */
1619   seq_nr_to_string(offset, little_endian, tvb, &sequenceNumber);
1620   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 8,
1621                       "firstSeqNumber:     0x%X%X",
1622                       sequenceNumber.high, sequenceNumber.low);
1623   offset +=8;
1624
1625   /* lastSeqNumber */
1626   seq_nr_to_string(offset, little_endian, tvb, &sequenceNumber);
1627   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 8,
1628                       "lastSeqNumber:      0x%X%X",
1629                       sequenceNumber.high, sequenceNumber.low);
1630   offset +=8;
1631
1632 }
1633
1634 /* *********************************************************************** */
1635
1636
1637 /* *********************************************************************** *
1638  *                                                                         *
1639  *                   subdissector for submessage: GAP                      *
1640  *                                                                         *
1641  * *********************************************************************** */
1642  /* hotovo 12.01.04 - JEN OTESTOVAT :] */
1643 static void
1644 dissect_GAP(tvbuff_t *tvb, gint offset, guint8 flags,
1645             gboolean little_endian, int next_submsg_offset,
1646             proto_tree *rtps_submessage_tree)
1647 {
1648   char                    buff[40];
1649   SequenceNumber          sequenceNumber;      /* type struct  */
1650
1651   proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
1652                       tvb, offset, 1, flags);
1653   offset +=1;
1654
1655   if (next_submsg_offset < 28)
1656   {
1657     proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
1658                                tvb, offset, 2, next_submsg_offset,
1659                                "Octets to next header: %u (bogus, must be >= 28)",
1660                                next_submsg_offset);
1661     return;
1662   }
1663   proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
1664                       tvb, offset, 2, next_submsg_offset);
1665   offset +=2;
1666   next_submsg_offset += offset;
1667
1668   /*  Reader Object ID  */
1669   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
1670                       "Reader Object ID:          %s ",
1671                       object_id_to_string(offset, tvb, buff));
1672   offset +=4;
1673
1674   /*  Writer Object ID  */
1675   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
1676                       "Writer Object ID:          %s ",
1677                       object_id_to_string(offset, tvb, buff));
1678   offset +=4;
1679
1680   /*  Sequence Number */
1681   seq_nr_to_string(offset, little_endian, tvb, &sequenceNumber);
1682   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 8,
1683                       "firstSeqNumber:   0x%X%X",
1684                       sequenceNumber.high, sequenceNumber.low);
1685   offset +=8;
1686
1687   get_bitmap(tvb,&offset,little_endian,next_submsg_offset,rtps_submessage_tree);
1688
1689 }
1690
1691 /* *********************************************************************** */
1692
1693
1694 /* *********************************************************************** *
1695  *                                                                         *
1696  *                subdissector for submessage: INFO_TS                     *
1697  *                                                                         *
1698  * *********************************************************************** */
1699  /* hotovo 12.01.04 - JEN OTESTOVAT :] */
1700
1701 static void
1702 dissect_INFO_TS(tvbuff_t *tvb, gint offset, guint8 flags,
1703                 gboolean little_endian, int next_submsg_offset,
1704                 proto_tree *rtps_submessage_tree)
1705 {
1706   char                     buff[10];
1707
1708   proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
1709                       tvb, offset, 1, flags);
1710   offset +=1;
1711
1712   /*   npTimestamp - valid if flag I = 1         *
1713    *   |XXXX|XXIE| => masks with 00000010b = 2   */
1714   if ((flags & FLAG_I) != 0)
1715   {
1716     if (next_submsg_offset < 8)
1717     {
1718       proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
1719                                  tvb, offset, 2, next_submsg_offset,
1720                                  "Octets to next header: %u (bogus, must be >= 8)",
1721                                  next_submsg_offset);
1722       return;
1723     }
1724   }
1725   proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
1726                       tvb, offset, 2, next_submsg_offset);
1727   offset +=2;
1728   next_submsg_offset += offset;
1729
1730   /*   npTimestamp - valid if flag I = 1         *
1731    *   |XXXX|XXIE| => masks with 00000010b = 2   */
1732   if ((flags & FLAG_I) != 0)
1733   {
1734     proto_tree_add_text(rtps_submessage_tree, tvb, offset, 8,
1735                         "ntpTimestamp: %s (sec)",
1736                         get_NtpTime(offset, tvb, little_endian,buff));
1737     offset +=8;
1738   }
1739
1740 }
1741
1742 /* *********************************************************************** */
1743
1744
1745 /* *********************************************************************** *
1746  *                                                                         *
1747  *               subdissector for submessage: INFO_SRC                     *
1748  *                                                                         *
1749  * *********************************************************************** */
1750 /* hotovo 12.01.04 JEN OTESTOVAT :] */
1751 static void
1752 dissect_INFO_SRC(tvbuff_t *tvb, gint offset, guint8 flags,
1753                  gboolean little_endian, int next_submsg_offset,
1754                  proto_tree *rtps_submessage_tree)
1755 {
1756   char                    buff[200];
1757
1758   proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
1759                       tvb, offset, 1, flags);
1760   offset +=1;
1761
1762   if (next_submsg_offset < 16)
1763   {
1764     proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
1765                                tvb, offset, 2, next_submsg_offset,
1766                                "Octets to next header: %u (bogus, must be >= 16)",
1767                                next_submsg_offset);
1768     return;
1769   }
1770   proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
1771                       tvb, offset, 2, next_submsg_offset);
1772   offset +=2;
1773   next_submsg_offset += offset;
1774
1775   /*  IPAddress */
1776   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
1777                       "appIP address: %s",
1778                       IP_to_string(offset, tvb, little_endian,buff));
1779   offset +=4;
1780
1781   /*  Protocol Version */
1782   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 2,
1783                       "Protocol  RTPS  version %s -new",
1784                       protocol_version_to_string(offset, tvb, buff));
1785   offset +=2;
1786
1787   /*  Vendor Id */
1788   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 2,
1789                       "VendorId: %s -new",
1790                       vendor_id_to_string(offset, tvb, buff));
1791   offset +=2;
1792
1793   /*  Host Id */
1794   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
1795                       "Host ID:            %s",
1796                       host_id_to_string(offset,tvb,buff));
1797   offset+=4;
1798
1799   /*  App Id */
1800   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
1801                       "App ID:             %s-new",
1802                       app_id_to_string(offset, tvb, buff));
1803   offset +=4;
1804
1805 }
1806
1807 /* *********************************************************************** */
1808
1809
1810 /* *********************************************************************** *
1811  *                                                                         *
1812  *               subdissector for submessage: INFO_REPLY                   *
1813  *                                                                         *
1814  * *********************************************************************** */
1815  /* hotovo 11.01.04 :] */
1816 static void
1817 dissect_INFO_REPLY(tvbuff_t *tvb, gint offset, guint8 flags,
1818                    gboolean little_endian, int next_submsg_offset,
1819                    proto_tree *rtps_submessage_tree)
1820 {
1821   int                     min_len;
1822   char                    buff_ip[10], buff_port[10];
1823
1824   proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
1825                       tvb, offset, 1, flags);
1826   offset +=1;
1827
1828  /*  'multicastReplyAdress' and 'multicastReplyPort' are    *
1829   *   parts of submessage INFO REPLY which are available    *
1830   *   only when FLAG  M=1  flags: XXXX XXME                 */
1831
1832   if ((flags & FLAG_M) != 0)
1833     min_len = 16;
1834   else
1835     min_len = 8;
1836   if (next_submsg_offset < min_len)
1837   {
1838     proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
1839                                tvb, offset, 2, next_submsg_offset,
1840                                "Octets to next header: %u (bogus, must be >= %u)",
1841                                next_submsg_offset, min_len);
1842     return;
1843   }
1844   proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
1845                       tvb, offset, 2, next_submsg_offset);
1846   offset +=2;
1847   next_submsg_offset += offset;
1848
1849   /* Unicat Reply IPAddress */
1850   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
1851                       "Unicast Reply IP Adress: %s",
1852                       IP_to_string(offset, tvb, little_endian,buff_ip));
1853   offset +=4;
1854
1855
1856   /* Unicast Reply Port */
1857   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
1858                       "Unicast Reply IP Port: %s",
1859                       port_to_string(offset, tvb, little_endian,buff_port));
1860   offset +=4;
1861
1862
1863  /*  'multicastReplyAdress' and 'multicastReplyPort' are    *
1864   *   parts of submessage INFO REPLY which are available    *
1865   *   only when FLAG  M=1  flags: XXXX XXME                 */
1866
1867   if ((flags & FLAG_M) != 0)
1868   {
1869     /* Multicast Reply IPAddress */
1870     proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
1871                         "Multicast Reply IP Adress: %s",
1872                         IP_to_string(offset, tvb, little_endian,buff_ip));
1873     offset +=4;
1874
1875     /* Multicast Reply Port */
1876     proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
1877                         "Multicast Reply IP Port: %s",
1878                         port_to_string(offset, tvb, little_endian,buff_port));
1879     offset +=4;
1880
1881   }
1882 }
1883
1884 /* *********************************************************************** */
1885
1886
1887 /* *********************************************************************** *
1888  *                                                                         *
1889  *                 subdissector for submessage: INFO_DST                   *
1890  *                                                                         *
1891  * *********************************************************************** */
1892  /* HOTOVO 12.01.04 - JEN OTESOVAT :]*/
1893 static void
1894 dissect_INFO_DST(tvbuff_t *tvb, gint offset, guint8 flags,
1895                  int next_submsg_offset,
1896                  proto_tree *rtps_submessage_tree)
1897 {
1898   char                    buff[200];
1899
1900   proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
1901                       tvb, offset, 1, flags);
1902   offset +=1;
1903
1904   if (next_submsg_offset < 8)
1905   {
1906     proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
1907                                tvb, offset, 2, next_submsg_offset,
1908                                "Octets to next header: %u (bogus, must be >= 8)",
1909                                next_submsg_offset);
1910     return;
1911   }
1912   proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
1913                       tvb, offset, 2, next_submsg_offset);
1914   offset +=2;
1915   next_submsg_offset += offset;
1916
1917   /*  Host Id */
1918   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
1919                       "Host ID:            %s",
1920                       host_id_to_string(offset,tvb,buff));
1921   offset+=4;
1922
1923   /*  App Id */
1924   proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
1925                       "App ID:             %s-new",
1926                       app_id_to_string(offset, tvb, buff));
1927   offset +=4;
1928
1929 }
1930
1931 /* *********************************************************************** *
1932  *                                                                         *
1933  *                       Register the protocol with Ethereal               *
1934  *                                                                         *
1935  * *********************************************************************** */
1936
1937 void proto_register_rtps(void)
1938 {
1939   static hf_register_info hf[] = {
1940
1941     { &hf_rtps_submessage_id,
1942       { "Submessage Id", "rtps.submessage_id",
1943          FT_UINT8, BASE_HEX, VALS(submessage_id_vals), 0x0,
1944         "Submessage flags", HFILL }},
1945
1946     { &hf_rtps_submessage_flags,
1947       { "Submessage flags", "rtps.submessage_flags",
1948          FT_UINT8, BASE_HEX, NULL, 0x0,
1949         "Submessage flags", HFILL }},
1950
1951     { &hf_rtps_octets_to_next_header,
1952       { "Octets to next header", "rtps.octets_to_next_header",
1953          FT_UINT16, BASE_DEC, NULL, 0x0,
1954         "Octets to next header", HFILL }},
1955
1956     { &hf_rtps_parameter_id,
1957       { "Parameter Id", "rtps.parameter_id",
1958          FT_UINT16, BASE_HEX, VALS(parameter_id_vals), 0x0,
1959         "Parameter Id", HFILL }},
1960
1961     { &hf_rtps_parameter_length,
1962       { "Parameter Length", "rtps.parameter_length",
1963          FT_UINT16, BASE_DEC, NULL, 0x0,
1964         "Parameter Length", HFILL }},
1965
1966     { &hf_rtps_issue_data,
1967       { "User Data", "rtps.issue_data",
1968          FT_BYTES, BASE_HEX, NULL, 0x0,
1969         "Issue Data", HFILL }},
1970   };
1971
1972   static gint *ett[] = {
1973     &ett_rtps,
1974     &ett_rtps_submessage,
1975     &ett_rtps_bitmap,
1976     &ett_rtps_parameter_sequence,
1977     &ett_rtps_parameter,
1978   };
1979
1980   proto_rtps = proto_register_protocol("Real-Time Publish-Subscribe Wire Protocol",
1981                                        "RTPS", "rtps");
1982   proto_register_field_array(proto_rtps, hf, array_length(hf));
1983   proto_register_subtree_array(ett, array_length(ett));
1984
1985 }
1986
1987
1988 void
1989 proto_reg_handoff_rtps(void)
1990 {
1991  heur_dissector_add("udp", dissect_rtps, proto_rtps);
1992 }
1993