wireshark/packet-rtps.c

1990 lines
70 KiB
C

/* packet-rtps.c
* Routines for Real-Time Publish-Subscribe Protocol (RTPS) dissection
*
* Copyright 2003, LUKAS POKORNY <maskis@seznam.cz>
* PETR SMOLIK <petr.smolik@wo.cz>
* ZDENEK SEBEK <sebek@fel.cvut.cz>
*
* Czech Technical University in Prague
* Faculty of Electrical Engineering <www.fel.cvut.cz>
* Department of Control Engineering <dce.felk.cvut.cz>
*
* version: 2004/04/15 9:40:45
* dedication to Kj :]
*
* $Id: packet-rtps.c,v 1.9 2004/04/19 22:41:19 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
*
* Copied from packet-udp.c, packet-tftp.c, packet-x25.c
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* *********************************************************************** */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef NEED_SNPRINTF_H
# include "snprintf.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <epan/packet.h>
#include <epan/resolv.h>
#include <epan/conversation.h>
/* *********************************************************************** *
RTPS protocol was developed by Real Time Innovation, Inc.
Protocol specifikation and documenation you can find on these addresses:
http://www.rti.com/
http://www.rti.com/products/ndds/literature.html
http://www.schneider-electric.com.au/Products/Automation/TF_RealTime/
/technical%20library/specifications/WireProtocolExternal.pdf
* *********************************************************************** */
/* redefine types because of definitions in 'packet-rtps.h' */
/*
#define u_int8_t guint8
#define int8_t gint8
#define u_int16_t guint16
#define int16_t gint16
#define u_int32_t guint32
#define int32_t gint32
*/
#include "packet-rtps.h"
/* number of APP_KIND byte in packet header */
#define APP_KIND_BYTE 15
/* definitions of flags */
#define FLAG_E 0x01
#define FLAG_F 0x02
#define FLAG_I 0x02
#define FLAG_M 0x02
#define FLAG_P 0x02
#define FLAG_A 0x04
#define FLAG_H 0x08
/* submessageId's ranges */
#define SUBMSG_ID_MIN PAD
#define SUBMSG_ID_MAX INFO_DST
/* Vendor specific submessageId's ranges */
#define VENDOR_SUBMSG_ID_MIN 0x80
#define VENDOR_SUBMSG_ID_MAX 0xff
/* *********************************************************************** */
/* initialize the protocol and registered fields */
static int proto_rtps = -1;
static int hf_rtps_submessage_id = -1;
static int hf_rtps_submessage_flags = -1;
static int hf_rtps_octets_to_next_header = -1;
static int hf_rtps_parameter_id = -1;
static int hf_rtps_parameter_length = -1;
static int hf_rtps_issue_data = -1;
/* Initialize the subtree pointers */
static gint ett_rtps = -1;
static gint ett_rtps_submessage = -1;
static gint ett_rtps_bitmap = -1;
static gint ett_rtps_parameter_sequence = -1;
static gint ett_rtps_parameter = -1;
/* Functions declarations */
static void dissect_PAD(tvbuff_t *tvb,gint offset,guint8 flags,
int next_submsg_offset,
proto_tree *rtps_submessage_tree);
static void dissect_VAR(tvbuff_t *tvb,gint offset,guint8 flags,
gboolean little_endian,int next_submsg_offset,
proto_tree *rtps_submessage_tree);
static void dissect_ISSUE(tvbuff_t *tvb,gint offset,guint8 flags,
gboolean little_endian,int next_submsg_offset,
proto_tree *rtps_submessage_tree);
static void dissect_ACK(tvbuff_t *tvb,gint offset,guint8 flags,
gboolean little_endian,int next_submsg_offset,
proto_tree *rtps_submessage_tree);
static void dissect_HEARTBEAT(tvbuff_t *tvb,gint offset,guint8 flags,
gboolean little_endian,int next_submsg_offset,
proto_tree *rtps_submessage_tree);
static void dissect_GAP(tvbuff_t *tvb,gint offset,guint8 flags,
gboolean little_endian,int next_submsg_offset,
proto_tree *rtps_submessage_tree);
static void dissect_INFO_TS(tvbuff_t *tvb,gint offset,guint8 flags,
gboolean little_endian,int next_submsg_offset,
proto_tree *rtps_submessage_tree);
static void dissect_INFO_SRC(tvbuff_t *tvb,gint offset,guint8 flags,
gboolean little_endian,int next_submsg_offset,
proto_tree *rtps_submessage_tree);
static void dissect_INFO_REPLY(tvbuff_t *tvb,gint offset,guint8 flags,
gboolean little_endian,int next_submsg_offset,
proto_tree *rtps_submessage_tree);
static void dissect_INFO_DST(tvbuff_t *tvb,gint offset,guint8 flags,
int next_submsg_offset,
proto_tree *rtps_submessage_tree);
static guint16 get_guint16(tvbuff_t *tvb, gint offset, gboolean little_endian);
static guint32 get_guint32(tvbuff_t *tvb, gint offset, gboolean little_endian);
static char *protocol_version_to_string(gint offset,tvbuff_t *tvb,char *buff);
static char *vendor_id_to_string(gint offset, tvbuff_t *tvb, char *buff);
static char *host_id_to_string(gint offset,tvbuff_t *tvb, char buff[]);
static char *app_id_to_string(gint offset,tvbuff_t *tvb,char buff[]);
static char *object_id_to_string(gint offset, tvbuff_t *tvb, char buff[]);
static char *IP_to_string(gint offset,tvbuff_t *tvb,gboolean little_endian,char buff[]);
static char *port_to_string(gint offset,tvbuff_t *tvb,gboolean little_endian,char buff[]);
static char *get_NtpTime(gint offset,tvbuff_t *tvb,gboolean little_endian,char buff[]);
static void get_bitmap(tvbuff_t *tvb, gint *p_offset, gboolean little_endian,
gint next_submsg, proto_tree *tree);
static void get_parameter_sequence(tvbuff_t *tvb, gint *p_offset,
gboolean little_endian,
gint next_submsg_offset, proto_tree *tree);
static gint seq_nr_to_string( gint offset, gboolean little_endian, tvbuff_t *tvb,
SequenceNumber *p_seqNumber);
static const value_string submessage_id_vals[] = {
{ PAD, "PAD" },
{ VAR, "VAR" },
{ ISSUE, "ISSUE" },
{ ACK, "ACK" },
{ HEARTBEAT, "HEARTBEAT" },
{ GAP, "GAP" },
{ INFO_TS, "INFO_TS" },
{ INFO_SRC, "INFO_SRC" },
{ INFO_REPLY, "INFO_REPLY" },
{ INFO_DST, "INFO_DST" },
{ APP_QUIT, "APP_QUIT" },
{ 0, NULL }
};
static const value_string parameter_id_vals[] = {
{ PID_PAD, "PID_PAD" },
{ PID_SENTINEL, "PID_SENTINEL" },
{ PID_EXPIRATION_TIME, "PID_EXPIRATION_TIME" },
{ PID_PERSISTENCE, "PID_PERSISTENCE" },
{ PID_MINIMUM_SEPARATION, "PID_MINIMUM_SEPARATION" },
{ PID_TOPIC, "PID_TOPIC" },
{ PID_STRENGTH, "PID_STRENGTH" },
{ PID_TYPE_NAME, "PID_TYPE_NAME" },
{ PID_TYPE_CHECKSUM, "PID_TYPE_CHECKSUM" },
{ RTPS_PID_TYPE2_NAME, "RTPS_PID_TYPE2_NAME" },
{ RTPS_PID_TYPE2_CHECKSUM, "RTPS_PID_TYPE2_CHECKSUM" },
{ PID_METATRAFFIC_MULTICAST_IPADDRESS, "PID_METATRAFFIC_MULTICAST_IPADDRESS" },
{ PID_APP_IPADDRESS, "PID_APP_IPADDRESS" },
{ PID_METATRAFFIC_UNICAST_PORT, "PID_METATRAFFIC_UNICAST_PORT" },
{ PID_USERDATA_UNICAST_PORT, "PID_USERDATA_UNICAST_PORT" },
{ PID_IS_RELIABLE, "PID_IS_RELIABLE" },
{ PID_EXPECTS_ACK, "PID_EXPECTS_ACK" },
{ PID_USERDATA_MULTICAST_IPADDRESS, "PID_USERDATA_MULTICAST_IPADDRESS" },
{ PID_MANAGER_KEY, "PID_MANAGER_KEY" },
{ PID_SEND_QUEUE_SIZE, "PID_SEND_QUEUE_SIZE" },
{ PID_RELIABILITY_ENABLED, "PID_RELIABILITY_ENABLED" },
{ PID_PROTOCOL_VERSION, "PID_PROTOCOL_VERSION" },
{ PID_VENDOR_ID, "PID_VENDOR_ID" },
{ PID_VARGAPPS_SEQUENCE_NUMBER_LAST, "PID_VARGAPPS_SEQUENCE_NUMBER_LAST" },
{ PID_RECV_QUEUE_SIZE, "PID_RECV_QUEUE_SIZE" },
{ PID_RELIABILITY_OFFERED, "PID_RELIABILITY_OFFERED" },
{ PID_RELIABILITY_REQUESTED, "PID_RELIABILITY_REQUESTED" },
{ 0, NULL }
};
/* *********************************************************************** */
/* *********************************************************************** *
* *
* Code to actually dissect the packets *
* *
* *********************************************************************** */
static gboolean
dissect_rtps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
proto_item *ti;
proto_tree *rtps_tree=NULL;
gint offset = 0;
gint appKind;
proto_tree *rtps_submessage_tree;
guint8 submessageId;
guint8 flags;
gboolean little_endian;
int next_submsg;
int count_msg_type[11];
char buff[200], buff_tmp[30];/* buffers */
/* offset is the byte offset of 'tvb' at which the new tvbuff
should start. The first byte is the 0th byte. */
/* --- making disition if protocol is RTPS protocol --- */
if (!tvb_bytes_exist(tvb, offset, 4)) return FALSE;
if (tvb_get_guint8(tvb,offset++) != 'R') return FALSE;
if (tvb_get_guint8(tvb,offset++) != 'T') return FALSE;
if (tvb_get_guint8(tvb,offset++) != 'P') return FALSE;
if (tvb_get_guint8(tvb,offset++) != 'S') return FALSE;
/* --- Make entries in Protocol column ---*/
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTPS");
if (check_col(pinfo->cinfo, COL_INFO))
col_clear(pinfo->cinfo, COL_INFO);
memset(count_msg_type, 0, sizeof(count_msg_type));
if (tree) {
/* create display subtree for the protocol */
ti = proto_tree_add_item(tree, proto_rtps, tvb, 0, -1, FALSE);
rtps_tree = proto_item_add_subtree(ti, ett_rtps);
/* Protocol Version */
proto_tree_add_text(rtps_tree, tvb, offset, 2,
"Protocol RTPS, version %s",
protocol_version_to_string(offset, tvb, buff));
offset +=2;
/* Vendor Id */
proto_tree_add_text(rtps_tree, tvb, offset, 2,
"VendorId: %s",
vendor_id_to_string(offset, tvb, buff));
offset +=2;
/* Host Id */
proto_tree_add_text(rtps_tree, tvb, offset, 4,
"HostId: %s",
host_id_to_string(offset,tvb,buff));
offset +=4;
/* App Id */
proto_tree_add_text(rtps_tree, tvb, offset, 4,
"App ID: %s",
app_id_to_string(offset, tvb, buff));
}
/* offset behind RTPS's Header */
offset=16;
while (tvb_reported_length_remaining(tvb, offset) > 0) {
submessageId = tvb_get_guint8(tvb, offset);
if (submessageId & 0x80) {
ti = proto_tree_add_text(tree, tvb, offset, -1, "Submessage: %s",
val_to_str(submessageId, submessage_id_vals,
"Vendor-specific (0x%02X)"));
} else {
ti = proto_tree_add_text(tree, tvb, offset, -1, "Submessage: %s",
val_to_str(submessageId, submessage_id_vals,
"Unknown (0x%02X)"));
}
rtps_submessage_tree = proto_item_add_subtree(ti, ett_rtps_submessage);
if (submessageId & 0x80) {
proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_submessage_id,
tvb, offset, 1, submessageId,
"Submessage Id: Vendor-specific (0x%02x)",
submessageId);
} else {
proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_id,
tvb, offset, 1, submessageId);
}
flags = tvb_get_guint8(tvb, offset + 1);
/* E flag |XXXX|HAPE| => masks with 000000001b = 1 */
if ((flags & FLAG_E) != 0) little_endian = TRUE;
else little_endian = FALSE;
next_submsg = get_guint16(tvb, offset + 2, little_endian);
proto_item_set_len(ti, next_submsg);
switch (submessageId)
{
case PAD:
if (tree)
dissect_PAD(tvb, offset + 1, flags, next_submsg,
rtps_submessage_tree);
count_msg_type[0]++;
break;
case VAR:
if (tree)
dissect_VAR(tvb, offset + 1, flags, little_endian, next_submsg,
rtps_submessage_tree);
count_msg_type[1]++;
break;
case ISSUE:
if (tree)
dissect_ISSUE(tvb, offset + 1, flags, little_endian, next_submsg,
rtps_submessage_tree);
count_msg_type[2]++;
break;
case ACK:
if (tree)
dissect_ACK(tvb, offset + 1, flags, little_endian, next_submsg,
rtps_submessage_tree);
count_msg_type[3]++;
break;
case HEARTBEAT:
if (tree)
dissect_HEARTBEAT(tvb, offset + 1, flags, little_endian, next_submsg,
rtps_submessage_tree);
count_msg_type[4]++;
break;
case GAP:
if (tree)
dissect_GAP(tvb, offset + 1, flags, little_endian, next_submsg,
rtps_submessage_tree);
count_msg_type[5]++;
break;
case INFO_TS:
if (tree)
dissect_INFO_TS(tvb, offset + 1, flags, little_endian, next_submsg,
rtps_submessage_tree);
count_msg_type[6]++;
break;
case INFO_SRC:
if (tree)
dissect_INFO_SRC(tvb, offset + 1, flags, little_endian, next_submsg,
rtps_submessage_tree);
count_msg_type[7]++;
break;
case INFO_REPLY:
if (tree)
dissect_INFO_REPLY(tvb, offset + 1, flags, little_endian, next_submsg,
rtps_submessage_tree);
count_msg_type[8]++;
break;
case INFO_DST:
if (tree)
dissect_INFO_DST(tvb, offset + 1, flags, next_submsg,
rtps_submessage_tree);
count_msg_type[9]++;
break;
default:
if (tree) {
proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
tvb, offset + 1, 1, flags);
proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
tvb, offset + 2, 2, next_submsg);
}
break;
}
/* next submessage's offset */
offset += next_submsg+4;
}
/* --- and Info column on summary display ---*/
if (check_col(pinfo->cinfo, COL_INFO))
{
appKind = tvb_get_guint8(tvb, APP_KIND_BYTE);
if (appKind == MANAGEDAPPLICATION ) {sprintf(buff,"App: ");}
if (appKind == MANAGER) {sprintf(buff,"Man: ");}
if (appKind == AID_UNKNOWN) {sprintf(buff,"Unknown:");}
if (appKind != MANAGEDAPPLICATION && appKind != MANAGER &&
appKind != AID_UNKNOWN) {sprintf(buff,"ERROR in APP type");}
/* -- counts of submessages - for Information Frame */
if (count_msg_type[0]>0) {
sprintf(buff_tmp,"PAD(%d) ",count_msg_type[0]);
strcat(buff,buff_tmp);
}
if (count_msg_type[1]>0) {
sprintf(buff_tmp,"VAR(%d) ",count_msg_type[1]);
strcat(buff,buff_tmp);
}
if (count_msg_type[2]>0) {
sprintf(buff_tmp,"ISSUE(%d) ",count_msg_type[2]);
strcat(buff,buff_tmp);
}
if (count_msg_type[3]>0) {
sprintf(buff_tmp,"ACK(%d) ",count_msg_type[3]);
strcat(buff,buff_tmp);
}
if (count_msg_type[4]>0) {
sprintf(buff_tmp,"HEARTBEAT(%d) ",count_msg_type[4]);
strcat(buff,buff_tmp);
}
if (count_msg_type[5]>0) {
sprintf(buff_tmp,"GAP(%d) ",count_msg_type[5]);
strcat(buff,buff_tmp);
}
if (count_msg_type[6]>0) {
sprintf(buff_tmp,"INFO_TS(%d) ",count_msg_type[6]);
strcat(buff,buff_tmp);
}
if (count_msg_type[7]>0) {
sprintf(buff_tmp, "INFO_SRC(%d) ",count_msg_type[7]);
strcat(buff,buff_tmp);
}
if (count_msg_type[8]>0) {
sprintf(buff_tmp,"INFO_REPLY(%d) ",count_msg_type[8]);
strcat(buff,buff_tmp);
}
if (count_msg_type[9]>0) {
sprintf(buff_tmp,"INFO_DST(%d) ",count_msg_type[9]);
strcat(buff,buff_tmp);
}
if (count_msg_type[10]>0) {
sprintf(buff_tmp,"vendor specific(%d) ",count_msg_type[10]);
strcat(buff,buff_tmp);
}
col_add_fstr(pinfo->cinfo, COL_INFO, buff);
}
return TRUE;
} /* end dissect_rtps(...) */
/* *********************************************************************** */
/* *********************************************************************** *
* *
* get 16 bit from the stream *
* *
* *********************************************************************** */
static guint16 get_guint16(tvbuff_t *tvb, gint offset, gboolean little_endian)
{
guint16 value;
if (little_endian)
value = tvb_get_letohs(tvb, offset);
else
value = tvb_get_ntohs(tvb, offset);
return(value);
}
/* *********************************************************************** */
/* *********************************************************************** *
* *
* get 32 bit from the stream *
* *
* *********************************************************************** */
static guint32 get_guint32(tvbuff_t *tvb, gint offset, gboolean little_endian)
{
guint32 value;
if (little_endian)
value = tvb_get_letohl(tvb, offset);
else
value = tvb_get_ntohl(tvb, offset);
return(value);
}
/* *********************************************************************** */
/* *********************************************************************** *
* *
* get Protocol version *
* *
* *********************************************************************** */
static char *
protocol_version_to_string(gint offset,tvbuff_t *tvb,char *buff)
{
guint8 major, minor;
/* protocol verzion = major.minor */
major = tvb_get_guint8(tvb, offset);
minor = tvb_get_guint8(tvb, (offset+1));
sprintf(buff,"%d.%d", major, minor);
return(buff);
}
/* *********************************************************************** */
/* *********************************************************************** *
* *
* get Vendor Id *
* *
* *********************************************************************** */
static char *
vendor_id_to_string(gint offset, tvbuff_t *tvb, char *buff)
{
guint8 major, minor;
VendorId vendorId_rti;
VENDOR_ID_RTI(vendorId_rti);
major = tvb_get_guint8(tvb, offset);
minor = tvb_get_guint8(tvb, (offset+1));
if (major == vendorId_rti.major &&
minor == vendorId_rti.minor)
{ sprintf(buff,"Real-Time Innovations,Inc.,CA,USA");
return(buff); }
sprintf(buff,"Vendor unknown");
return(buff);
}
/* *********************************************************************** */
/* *********************************************************************** *
* *
* get IP Address *
* *
* *********************************************************************** */
static char *
IP_to_string(gint offset,tvbuff_t *tvb,gboolean little_endian,char buff[])
{
IPAddress ip;
guint8 a = 0, b = 0, c = 0, d = 0; /* IP Adresss = a.b.c.d */
ip = get_guint32(tvb, offset, little_endian);
/* get_guint32() - reads + endian conversion */
a = (ip >> 24);
b = (ip >> 16) & 0xff;
c = (ip >> 8) & 0xff;
d = ip & 0xff;
sprintf(buff,"%d.%d.%d.%d", a, b, c, d);
return(buff);
}
/* *********************************************************************** */
/* *********************************************************************** *
* *
* get Port *
* *
* *********************************************************************** */
static char *
port_to_string(gint offset,tvbuff_t *tvb,gboolean little_endian,char buff[])
{
Port port = get_guint32(tvb, offset, little_endian);
/* get_guint32() - reads + endian conversion */
if (port == PORT_INVALID)
sprintf(buff,"PORT_INVALID");
else
sprintf(buff,"0x%X",port);
return(buff);
}
/* *********************************************************************** */
/* *********************************************************************** *
* *
* get NTP Time *
* *
* *********************************************************************** */
static char *
get_NtpTime(gint offset,tvbuff_t *tvb,gboolean little_endian,char buff[])
{
NtpTime ntpTime;
float time;
/* get_guint32() - reads + endian conversion */
ntpTime.seconds = get_guint32(tvb, offset, little_endian);
ntpTime.fraction = get_guint32(tvb, (offset + 4), little_endian);
time = (float) ntpTime.seconds + (ntpTime.fraction / 2^(32));
sprintf(buff,"%f", time);
return(buff);
}
/* *********************************************************************** */
/* *********************************************************************** *
* *
* get Host Id *
* *
* *********************************************************************** */
static char *
host_id_to_string(gint offset,tvbuff_t *tvb, char buff[])
{
guint32 hostId = tvb_get_ntohl(tvb, offset);
/* get_ntohl() automaticaly convert data to BIG ENDIAN */
sprintf(buff,"0x%X", hostId);
return(buff);
}
/* *********************************************************************** */
/* *********************************************************************** *
* *
* get AppID *
* *
* *********************************************************************** */
static char *
app_id_to_string(gint offset,tvbuff_t *tvb,char buff[])
{
guint32 appId = tvb_get_ntohl(tvb, offset);
/* get_ntohl() automaticaly convert data to BIG ENDIAN */
/* Instance Id */
guint32 instanceId = (appId >> 8);
/* applicatin Kind */
guint8 appKind = (appId & 0xff);
if (appKind == MANAGEDAPPLICATION)
{
sprintf(buff,"Managed App, InstanceId: 0x%X",instanceId);
return(buff);
}
if (appKind == MANAGER)
{
sprintf(buff,"Manager, InstanceId: 0x%X",instanceId);
return(buff);
}
sprintf(buff,"Unknown");
return(buff);
}
/* *********************************************************************** */
/* *********************************************************************** *
* *
* get Object_Id (32 bit) *
* *
* *********************************************************************** */
static char *
object_id_to_string(gint offset, tvbuff_t *tvb, char buff[])
{
guint32 objectId = tvb_get_ntohl(tvb, offset);
/* get_ntohl() automaticaly convert data to BIG ENDIAN */
if (objectId == OID_UNKNOWN) { sprintf(buff,"Unknown ObjectId");
return(buff);}
if (objectId == OID_APP) { sprintf(buff,"applicationSelf");
return(buff);}
if (objectId == OID_WRITE_APPSELF){ sprintf(buff,"writerApplicationSelf");
return(buff);}
if (objectId == OID_WRITE_APP) { sprintf(buff,"writerApplications");
return(buff);}
if (objectId == OID_READ_APP) { sprintf(buff,"readerApplications");
return(buff);}
if (objectId == OID_WRITE_MGR) { sprintf(buff,"writerManagers");
return(buff);}
if (objectId == OID_READ_MGR) { sprintf(buff,"readerManagers ");
return(buff);}
if (objectId == OID_WRITE_PUBL) { sprintf(buff,"writerPublications");
return(buff);}
if (objectId == OID_READ_PUBL) { sprintf(buff,"readerPublications");
return(buff);}
if (objectId == OID_WRITE_SUBS) { sprintf(buff,"writerSubscriptions");
return(buff);}
if (objectId == OID_READ_SUBS) { sprintf(buff,"readerSubscriptions");
return(buff);}
/* nothing from the possibilites above */
sprintf(buff,"instanceId: 0x%X, objKind: 0x%X",
(objectId >> 8),(objectId & 0xff));
return(buff);
/* for the future
//Kind
#define OID_APPLICATION 0x01
#define OID_CSTWRITER 0x02
#define OID_PUBLICATION 0x03
#define OID_SUBSCRIPTION 0x04
#define OID_CSTREADER 0x07
//
#define OID_USEROBJ 0x00
#define OID_RESUSEROBJ 0x40
#define OID_METAOBJ 0x80
#define OID_RESMETAOBJ 0xC0
*/
}
/* *********************************************************************** */
/* *********************************************************************** *
* *
* get Sequence Number (64 bit) *
* *
* *********************************************************************** */
static gint
seq_nr_to_string(gint offset, gboolean little_endian, tvbuff_t *tvb,
SequenceNumber *p_seqNumber)
{
p_seqNumber->high = get_guint32(tvb, offset, little_endian);
p_seqNumber->low = get_guint32(tvb, offset + 4, little_endian);
return(1);
}
/* *********************************************************************** */
/* *********************************************************************** *
* *
* get_Bitmap *
* *
* *********************************************************************** */
static void
get_bitmap(tvbuff_t *tvb, gint *p_offset, gboolean little_endian,
gint next_submsg, proto_tree *tree)
{
proto_item *ti;
proto_tree *rtps_bitmap_tree;
gint i = 0;
gint offset = *p_offset;
SequenceNumber sequenceNumber;
guint32 num_bits;
guint num_longs;
/* making subtree for the bitmap */
ti = proto_tree_add_text(tree,tvb,offset,(next_submsg-offset),"Bitmap");
rtps_bitmap_tree = proto_item_add_subtree(ti, ett_rtps_bitmap);
/* SekvenceNumber bitmapBase */
seq_nr_to_string(offset, little_endian, tvb, &sequenceNumber);
proto_tree_add_text(rtps_bitmap_tree, tvb, offset, 8,
"bitmapBase: 0x%X%X",
sequenceNumber.high, sequenceNumber.low);
offset +=8;
num_bits = get_guint32(tvb, offset, little_endian);
proto_tree_add_text(rtps_bitmap_tree, tvb, offset, 4,
"numBits: %u",
num_bits);
offset += 4;
if (num_bits+31 < num_bits)
num_longs = UINT_MAX; /* overflow */
else
num_longs = (num_bits+31)/32;
while (num_longs != 0)
{
if (next_submsg-offset < 4)
{
proto_tree_add_text(rtps_bitmap_tree, tvb, offset, next_submsg-offset,
"bitmap[%d]: < 4 bytes remain in message", i);
offset = next_submsg;
break;
}
proto_tree_add_text(rtps_bitmap_tree, tvb, offset, 4,
"bitmap[%d]: 0x%08X",
i, get_guint32(tvb, offset, little_endian));
offset +=4;
++i;
--num_longs;
} /* end while */
*p_offset = offset;
}
/* *********************************************************************** */
/* *********************************************************************** *
* *
* dissect submessage: PAD *
* *
* (this submessage has no meaning and it is always valid) *
* *********************************************************************** */
static void
dissect_PAD(tvbuff_t *tvb, gint offset, guint8 flags,
int next_submsg_offset, proto_tree *rtps_submessage_tree)
{
proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
tvb, offset, 1, flags);
offset += 1;
proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
tvb, offset, 2, next_submsg_offset);
offset +=2;
next_submsg_offset += offset;
}
/* *********************************************************************** */
/* *********************************************************************** *
* *
* dissect submessage: VAR *
* *
* *********************************************************************** */
static void
dissect_VAR(tvbuff_t *tvb, gint offset, guint8 flags, gboolean little_endian,
int next_submsg_offset, proto_tree *rtps_submessage_tree)
{
int min_len;
char buff[200];
SequenceNumber writerSeqNumber;
proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
tvb, offset, 1, flags);
offset +=1;
min_len = 20;
if ((flags & FLAG_H) != 0)
min_len += 8;
if ((flags & FLAG_P) != 0)
min_len += 4;
if (next_submsg_offset < min_len)
{
proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
tvb, offset, 2, next_submsg_offset,
"Octets to next header: %u (bogus, must be >= %u)",
next_submsg_offset, min_len);
return;
}
proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
tvb, offset, 2, next_submsg_offset);
offset +=2;
next_submsg_offset += offset;
/* readerObjectId*/
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
"Reader Object ID: %s ",
object_id_to_string(offset, tvb, buff));
offset +=4;
/* writerObjectId*/
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
"Writer Object ID: %s ",
object_id_to_string(offset, tvb, buff));
offset+=4;
/* H flag |XXXX|HAPE| => masks with 00001000b = 8 */
if ((flags & FLAG_H) != 0)
{
/* HostId */
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
"Host ID: %s",
host_id_to_string(offset,tvb,buff));
offset+=4;
/* App Id */
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
"App ID: %s",
app_id_to_string(offset, tvb, buff));
offset +=4;
}
/* Object Id */
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
"Object ID: %s ",
object_id_to_string(offset, tvb, buff));
offset +=4;
/* WriterSequence Number */
seq_nr_to_string(offset, little_endian, tvb, &writerSeqNumber);
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 8,
"WriterSeqNumber: 0x%X%X",
writerSeqNumber.high, writerSeqNumber.low);
offset +=8;
/* P flag |XXXX|HAPE| => masks with 00000010b = 2 */
if ((flags & FLAG_P) != 0)
{
get_parameter_sequence(tvb, &offset, little_endian, next_submsg_offset,
rtps_submessage_tree);
}
}
/* *********************************************************************** */
/* *********************************************************************** *
* *
* get_ParameterSequence *
* *
* *********************************************************************** */
static void
get_parameter_sequence(tvbuff_t *tvb, gint *p_offset, gboolean little_endian,
gint next_submsg_offset, proto_tree *tree)
{
proto_item *ti;
proto_tree *rtps_parameter_sequence_tree;
proto_tree *rtps_parameter_tree;
gint offset = *p_offset;
guint16 parameter, param_length;
gint str_length;
SequenceNumber seqNumber;
char buff_tmp[MAX_PATHNAME];
int i;
char sep;
ti = proto_tree_add_text(tree, tvb, offset, (next_submsg_offset - offset),
"Parameters:");
rtps_parameter_sequence_tree = proto_item_add_subtree(ti,
ett_rtps_parameter_sequence);
for (;;)
{
if (next_submsg_offset-offset < 2)
{
proto_tree_add_text(rtps_parameter_sequence_tree, tvb, offset,
next_submsg_offset-offset,
"Parameter: < 2 bytes remain in message");
offset = next_submsg_offset;
break;
}
parameter = get_guint16(tvb, offset, little_endian);
ti = proto_tree_add_text(rtps_parameter_sequence_tree, tvb, offset, 2,
"%s",
val_to_str(parameter, parameter_id_vals,
"Unknown parameter (0x%04X)"));
rtps_parameter_tree = proto_item_add_subtree(ti, ett_rtps_parameter);
proto_tree_add_uint(rtps_parameter_tree, hf_rtps_parameter_id,
tvb, offset, 2, parameter);
offset +=2;
if (next_submsg_offset-offset < 2)
{
proto_tree_add_text(rtps_parameter_tree, tvb, offset,
next_submsg_offset-offset,
"Parameter length: < 2 bytes remain in message");
offset = next_submsg_offset;
proto_item_set_end(ti, tvb, offset);
break;
}
param_length = get_guint16(tvb, offset, little_endian);
proto_tree_add_uint(rtps_parameter_tree, hf_rtps_parameter_length,
tvb, offset, 2, param_length);
offset +=2;
if (parameter == PID_SENTINEL) {
proto_item_set_end(ti, tvb, offset);
break;
}
if (next_submsg_offset-offset < param_length)
{
proto_tree_add_text(rtps_parameter_tree, tvb, offset,
next_submsg_offset-offset,
"Parameter value: < %u bytes remain in message",
param_length);
offset = next_submsg_offset;
proto_item_set_end(ti, tvb, offset);
break;
}
proto_item_set_end(ti, tvb, offset + param_length);
switch (parameter)
{
case PID_PAD:
proto_item_append_text(ti, ": -");
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Padding");
break;
case PID_EXPIRATION_TIME:
if (param_length < 8)
{
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Bad parameter: length < 8");
}
else
{
char *ntp_time_str;
ntp_time_str = get_NtpTime(offset, tvb, little_endian,buff_tmp);
proto_item_append_text(ti, ": %s", ntp_time_str);
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Expiration time: %s", ntp_time_str);
}
break;
case PID_PERSISTENCE:
if (param_length < 8)
{
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Bad parameter: length < 8");
}
else
{
char *ntp_time_str;
ntp_time_str = get_NtpTime(offset, tvb, little_endian,buff_tmp);
proto_item_append_text(ti, ": %s", ntp_time_str);
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Persistence: %s", ntp_time_str);
}
break;
case PID_MINIMUM_SEPARATION:
if (param_length < 8)
{
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Bad parameter: length < 8");
}
else
{
char *ntp_time_str;
ntp_time_str = get_NtpTime(offset, tvb, little_endian,buff_tmp);
proto_item_append_text(ti, ": %s", ntp_time_str);
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Minimum separation: %s", ntp_time_str);
}
break;
case PID_TOPIC: /* --- ?? funguje spravne ?? */
str_length = tvb_strnlen(tvb, offset, param_length);
if (str_length == -1)
{
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Bad parameter: Terminating zero missing");
}
else
{
char *str;
str = tvb_format_text(tvb, offset, str_length);
proto_item_append_text(ti, ": %s", str);
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Topic: %s", str);
}
break;
case PID_STRENGTH:
if (param_length < 4)
{
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Bad parameter: length < 4");
}
else
{
guint32 strength;
strength = get_guint32(tvb, offset, little_endian);
proto_item_append_text(ti, ": 0x%X", strength);
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Strength: 0x%X", strength);
}
break;
case PID_TYPE_NAME: /* --- ?? funguje spravne ?? */
str_length = tvb_strnlen(tvb, offset, param_length);
if (str_length == -1)
{
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Bad parameter: Terminating zero missing");
}
else
{
char *str;
str = tvb_format_text(tvb, offset, str_length);
proto_item_append_text(ti, ": %s", str);
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Type name: %s", str);
}
break;
case PID_TYPE_CHECKSUM:
/* nacitam jako UNSIGNED - nemuze to byt i zaporne cislo?? */
if (param_length < 4)
{
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Bad parameter: length < 4");
}
else
{
guint32 checksum;
checksum = get_guint32(tvb, offset, little_endian);
proto_item_append_text(ti, ": 0x%X", checksum);
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Checksum: 0x%X", checksum);
}
break;
case RTPS_PID_TYPE2_NAME:
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Parameter data");
break;
case RTPS_PID_TYPE2_CHECKSUM:
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Parameter data");
break;
case PID_METATRAFFIC_MULTICAST_IPADDRESS:
i = 0;
sep = ':';
while (param_length >= 4)
{
char *ip_string;
ip_string = IP_to_string(offset, tvb, little_endian,buff_tmp);
proto_item_append_text(ti, "%c %s", sep, ip_string);
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Address[%d]: %s", i, ip_string);
++i;
offset +=4;
sep = ',';
}
offset += param_length;
break;
case PID_APP_IPADDRESS:
i = 0;
sep = ':';
while (param_length >= 4)
{
char *ip_string;
ip_string = IP_to_string(offset, tvb, little_endian,buff_tmp);
proto_item_append_text(ti, "%c %s", sep, ip_string);
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Address[%d]: %s", i, ip_string);
++i;
offset +=4;
sep = ',';
}
offset += param_length;
break;
case PID_METATRAFFIC_UNICAST_PORT:
if (param_length < 4)
{
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Bad parameter: length < 4");
}
else
{
char *port_str;
port_str = port_to_string(offset, tvb, little_endian,buff_tmp);
proto_item_append_text(ti, ": %s", port_str);
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Port: %s", port_str);
}
break;
case PID_USERDATA_UNICAST_PORT:
if (param_length < 4)
{
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Bad parameter: length < 4");
}
else
{
char *port_str;
port_str = port_to_string(offset, tvb, little_endian,buff_tmp);
proto_item_append_text(ti, ": %s", port_str);
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Port: %s", port_str);
}
break;
case PID_EXPECTS_ACK:
if (param_length < 1)
{
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Bad parameter: length < 1");
}
else
{
if (tvb_get_guint8(tvb, offset) == 0)
{
proto_item_append_text(ti, ": No");
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"ACK expected: No");
}
else
{
proto_item_append_text(ti, ": Yes");
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"ACK expected: Yes");
}
}
break;
case PID_USERDATA_MULTICAST_IPADDRESS:
i = 0;
sep = ':';
while (param_length >= 4)
{
char *ip_string;
ip_string = IP_to_string(offset, tvb, little_endian,buff_tmp);
proto_item_append_text(ti, "%c %s", sep, ip_string);
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Address[%d]: %s", i, ip_string);
++i;
offset +=4;
}
offset += param_length;
break;
case PID_MANAGER_KEY:
i = 0;
sep = ':';
while (param_length >= 4)
{
guint32 manager_key;
manager_key = get_guint32(tvb, offset, little_endian);
proto_item_append_text(ti, "%c 0x%X", sep, manager_key);
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Key[%d]: 0x%X", i, manager_key);
++i;
offset +=4;
sep = ',';
}
offset += param_length;
break;
case PID_SEND_QUEUE_SIZE:
if (param_length < 4)
{
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Bad parameter: length < 4");
}
else
{
guint32 send_queue_size;
send_queue_size = get_guint32(tvb, offset, little_endian);
proto_item_append_text(ti, ": %u", send_queue_size);
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Send queue size: %u", send_queue_size);
}
break;
case PID_PROTOCOL_VERSION:
if (param_length < 2)
{
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Bad parameter: length < 2");
}
else
{
char *protocol_version_str;
protocol_version_str = protocol_version_to_string(offset, tvb, buff_tmp);
proto_item_append_text(ti, ": %s", protocol_version_str);
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Protocol version: %s", protocol_version_str);
}
break;
case PID_VENDOR_ID:
if (param_length < 2)
{
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Bad parameter: length < 2");
}
else
{
char *vendor_id_str;
vendor_id_str = vendor_id_to_string(offset, tvb, buff_tmp);
proto_item_append_text(ti, ": %s", vendor_id_str);
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Vendor ID: %s", vendor_id_str);
}
break;
case PID_VARGAPPS_SEQUENCE_NUMBER_LAST:
if (param_length < 8)
{
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Bad parameter: length < 8");
}
else
{
seq_nr_to_string(offset, little_endian, tvb, &seqNumber);
proto_item_append_text(ti, ": 0x%X%X",
seqNumber.high, seqNumber.low);
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Sequence number: 0x%X%X",
seqNumber.high, seqNumber.low);
}
break;
case PID_RECV_QUEUE_SIZE:
if (param_length < 4)
{
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Bad parameter: length < 4");
}
else
{
guint32 recv_queue_size;
recv_queue_size = get_guint32(tvb, offset, little_endian);
proto_item_append_text(ti, ": %u", recv_queue_size);
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Receive queue size: %u", recv_queue_size);
}
break;
case PID_RELIABILITY_OFFERED:
if (param_length < 4)
{
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Bad parameter: length < 4");
}
else
{
guint32 reliability_offered;
reliability_offered = get_guint32(tvb, offset, little_endian);
proto_item_append_text(ti, ": 0x%X", reliability_offered);
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Reliability offered: 0x%X", reliability_offered);
}
break;
case PID_RELIABILITY_REQUESTED:
if (param_length < 4)
{
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Bad parameter: length < 4");
}
else
{
guint32 reliability_requested;
reliability_requested = get_guint32(tvb, offset, little_endian);
proto_item_append_text(ti, ": 0x%X", reliability_requested);
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Reliability requested: 0x%X", reliability_requested);
}
break;
default:
proto_tree_add_text(rtps_parameter_tree, tvb, offset, param_length,
"Unknown parameter value");
break;
} /* end switch */
offset += param_length;
}
*p_offset = offset;
}
/* *********************************************************************** */
/* *********************************************************************** *
* *
* subdissector for submessage: ISSUE *
* *
* *********************************************************************** */
/* hotovo 12.01.04 - JEN OTESTOVAT :] */
static void
dissect_ISSUE(tvbuff_t *tvb, gint offset, guint8 flags,
gboolean little_endian, int next_submsg_offset,
proto_tree *rtps_submessage_tree)
{
int min_len;
char buff[40];
SequenceNumber sequenceNumber; /* type struct */
proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
tvb, offset, 1, flags);
offset +=1;
min_len = 16;
if ((flags & FLAG_P) != 0)
min_len += 4;
if (next_submsg_offset < min_len)
{
proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
tvb, offset, 2, next_submsg_offset,
"Octets to next header: %u (bogus, must be >= %u)",
next_submsg_offset, min_len);
return;
}
proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
tvb, offset, 2, next_submsg_offset);
offset +=2;
next_submsg_offset += offset;
/* Reader Object ID */
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
"Reader Object ID: %s ",
object_id_to_string(offset, tvb, buff));
offset +=4;
/* Writer Object ID */
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
"Writer Object ID: %s ",
object_id_to_string(offset, tvb, buff));
offset +=4;
/* Sequence Number */
seq_nr_to_string(offset, little_endian, tvb, &sequenceNumber);
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 8,
"firstSeqNumber: 0x%X%X",
sequenceNumber.high, sequenceNumber.low);
offset += 8;
/* Parameters */
/* *********************************************************************** *
* - for future extension of the protocol - in *
* implementation of RTPS 1.0 can ignore the content *
* *********************************************************************** */
/* -- P flag |XXXX|HAPE| => masks with 00000010b = 2 */
if ((flags & FLAG_P) != 0)
{
get_parameter_sequence(tvb, &offset, little_endian, next_submsg_offset,
rtps_submessage_tree);
}
/* Issue Data */
proto_tree_add_item(rtps_submessage_tree, hf_rtps_issue_data, tvb,
offset, (next_submsg_offset - offset), FALSE);
}
/* *********************************************************************** */
/* *********************************************************************** *
* *
* subdissector for submessage: ACK *
* *
* *********************************************************************** */
/* hotovo 12.01.04 - JEN OTESTOVAT :] */
static void
dissect_ACK(tvbuff_t *tvb, gint offset, guint8 flags,
gboolean little_endian, int next_submsg_offset,
proto_tree *rtps_submessage_tree)
{
char buff[40];
proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
tvb, offset, 1, flags);
offset +=1;
if (next_submsg_offset < 20)
{
proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
tvb, offset, 2, next_submsg_offset,
"Octets to next header: %u (bogus, must be >= 20)",
next_submsg_offset);
return;
}
proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
tvb, offset, 2, next_submsg_offset);
offset +=2;
next_submsg_offset += offset;
/* Reader Object ID */
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
"Reader Object ID: %s ",
object_id_to_string(offset, tvb, buff));
offset +=4;
/* Writer Object ID */
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
"Writer Object ID: %s ",
object_id_to_string(offset, tvb, buff));
offset +=4;
get_bitmap(tvb,&offset,little_endian,next_submsg_offset,rtps_submessage_tree);
}
/* *********************************************************************** */
/* *********************************************************************** *
* *
* subdissector for submessage: HEARTBEAT *
* *
* *********************************************************************** */
/* hotovo 12.01.04 - JEN OTESTOVAT :] */
static void
dissect_HEARTBEAT(tvbuff_t *tvb, gint offset, guint8 flags,
gboolean little_endian, int next_submsg_offset,
proto_tree *rtps_submessage_tree)
{
char buff[40];
SequenceNumber sequenceNumber; /* type struct */
proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
tvb, offset, 1, flags);
offset +=1;
if (next_submsg_offset < 24)
{
proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
tvb, offset, 2, next_submsg_offset,
"Octets to next header: %u (bogus, must be >= 24)",
next_submsg_offset);
return;
}
proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
tvb, offset, 2, next_submsg_offset);
offset +=2;
next_submsg_offset += offset;
/* Reader Object ID */
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
"Reader Object ID: %s ",
object_id_to_string(offset, tvb, buff));
offset +=4;
/* Writer Object ID */
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
"Writer Object ID: %s ",
object_id_to_string(offset, tvb, buff));
offset +=4;
/* firstSeqNumber */
seq_nr_to_string(offset, little_endian, tvb, &sequenceNumber);
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 8,
"firstSeqNumber: 0x%X%X",
sequenceNumber.high, sequenceNumber.low);
offset +=8;
/* lastSeqNumber */
seq_nr_to_string(offset, little_endian, tvb, &sequenceNumber);
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 8,
"lastSeqNumber: 0x%X%X",
sequenceNumber.high, sequenceNumber.low);
offset +=8;
}
/* *********************************************************************** */
/* *********************************************************************** *
* *
* subdissector for submessage: GAP *
* *
* *********************************************************************** */
/* hotovo 12.01.04 - JEN OTESTOVAT :] */
static void
dissect_GAP(tvbuff_t *tvb, gint offset, guint8 flags,
gboolean little_endian, int next_submsg_offset,
proto_tree *rtps_submessage_tree)
{
char buff[40];
SequenceNumber sequenceNumber; /* type struct */
proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
tvb, offset, 1, flags);
offset +=1;
if (next_submsg_offset < 28)
{
proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
tvb, offset, 2, next_submsg_offset,
"Octets to next header: %u (bogus, must be >= 28)",
next_submsg_offset);
return;
}
proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
tvb, offset, 2, next_submsg_offset);
offset +=2;
next_submsg_offset += offset;
/* Reader Object ID */
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
"Reader Object ID: %s ",
object_id_to_string(offset, tvb, buff));
offset +=4;
/* Writer Object ID */
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
"Writer Object ID: %s ",
object_id_to_string(offset, tvb, buff));
offset +=4;
/* Sequence Number */
seq_nr_to_string(offset, little_endian, tvb, &sequenceNumber);
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 8,
"firstSeqNumber: 0x%X%X",
sequenceNumber.high, sequenceNumber.low);
offset +=8;
get_bitmap(tvb,&offset,little_endian,next_submsg_offset,rtps_submessage_tree);
}
/* *********************************************************************** */
/* *********************************************************************** *
* *
* subdissector for submessage: INFO_TS *
* *
* *********************************************************************** */
/* hotovo 12.01.04 - JEN OTESTOVAT :] */
static void
dissect_INFO_TS(tvbuff_t *tvb, gint offset, guint8 flags,
gboolean little_endian, int next_submsg_offset,
proto_tree *rtps_submessage_tree)
{
char buff[10];
proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
tvb, offset, 1, flags);
offset +=1;
/* npTimestamp - valid if flag I = 1 *
* |XXXX|XXIE| => masks with 00000010b = 2 */
if ((flags & FLAG_I) != 0)
{
if (next_submsg_offset < 8)
{
proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
tvb, offset, 2, next_submsg_offset,
"Octets to next header: %u (bogus, must be >= 8)",
next_submsg_offset);
return;
}
}
proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
tvb, offset, 2, next_submsg_offset);
offset +=2;
next_submsg_offset += offset;
/* npTimestamp - valid if flag I = 1 *
* |XXXX|XXIE| => masks with 00000010b = 2 */
if ((flags & FLAG_I) != 0)
{
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 8,
"ntpTimestamp: %s (sec)",
get_NtpTime(offset, tvb, little_endian,buff));
offset +=8;
}
}
/* *********************************************************************** */
/* *********************************************************************** *
* *
* subdissector for submessage: INFO_SRC *
* *
* *********************************************************************** */
/* hotovo 12.01.04 JEN OTESTOVAT :] */
static void
dissect_INFO_SRC(tvbuff_t *tvb, gint offset, guint8 flags,
gboolean little_endian, int next_submsg_offset,
proto_tree *rtps_submessage_tree)
{
char buff[200];
proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
tvb, offset, 1, flags);
offset +=1;
if (next_submsg_offset < 16)
{
proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
tvb, offset, 2, next_submsg_offset,
"Octets to next header: %u (bogus, must be >= 16)",
next_submsg_offset);
return;
}
proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
tvb, offset, 2, next_submsg_offset);
offset +=2;
next_submsg_offset += offset;
/* IPAddress */
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
"appIP address: %s",
IP_to_string(offset, tvb, little_endian,buff));
offset +=4;
/* Protocol Version */
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 2,
"Protocol RTPS version %s -new",
protocol_version_to_string(offset, tvb, buff));
offset +=2;
/* Vendor Id */
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 2,
"VendorId: %s -new",
vendor_id_to_string(offset, tvb, buff));
offset +=2;
/* Host Id */
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
"Host ID: %s",
host_id_to_string(offset,tvb,buff));
offset+=4;
/* App Id */
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
"App ID: %s-new",
app_id_to_string(offset, tvb, buff));
offset +=4;
}
/* *********************************************************************** */
/* *********************************************************************** *
* *
* subdissector for submessage: INFO_REPLY *
* *
* *********************************************************************** */
/* hotovo 11.01.04 :] */
static void
dissect_INFO_REPLY(tvbuff_t *tvb, gint offset, guint8 flags,
gboolean little_endian, int next_submsg_offset,
proto_tree *rtps_submessage_tree)
{
int min_len;
char buff_ip[10], buff_port[10];
proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
tvb, offset, 1, flags);
offset +=1;
/* 'multicastReplyAdress' and 'multicastReplyPort' are *
* parts of submessage INFO REPLY which are available *
* only when FLAG M=1 flags: XXXX XXME */
if ((flags & FLAG_M) != 0)
min_len = 16;
else
min_len = 8;
if (next_submsg_offset < min_len)
{
proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
tvb, offset, 2, next_submsg_offset,
"Octets to next header: %u (bogus, must be >= %u)",
next_submsg_offset, min_len);
return;
}
proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
tvb, offset, 2, next_submsg_offset);
offset +=2;
next_submsg_offset += offset;
/* Unicat Reply IPAddress */
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
"Unicast Reply IP Adress: %s",
IP_to_string(offset, tvb, little_endian,buff_ip));
offset +=4;
/* Unicast Reply Port */
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
"Unicast Reply IP Port: %s",
port_to_string(offset, tvb, little_endian,buff_port));
offset +=4;
/* 'multicastReplyAdress' and 'multicastReplyPort' are *
* parts of submessage INFO REPLY which are available *
* only when FLAG M=1 flags: XXXX XXME */
if ((flags & FLAG_M) != 0)
{
/* Multicast Reply IPAddress */
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
"Multicast Reply IP Adress: %s",
IP_to_string(offset, tvb, little_endian,buff_ip));
offset +=4;
/* Multicast Reply Port */
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
"Multicast Reply IP Port: %s",
port_to_string(offset, tvb, little_endian,buff_port));
offset +=4;
}
}
/* *********************************************************************** */
/* *********************************************************************** *
* *
* subdissector for submessage: INFO_DST *
* *
* *********************************************************************** */
/* HOTOVO 12.01.04 - JEN OTESOVAT :]*/
static void
dissect_INFO_DST(tvbuff_t *tvb, gint offset, guint8 flags,
int next_submsg_offset,
proto_tree *rtps_submessage_tree)
{
char buff[200];
proto_tree_add_uint(rtps_submessage_tree, hf_rtps_submessage_flags,
tvb, offset, 1, flags);
offset +=1;
if (next_submsg_offset < 8)
{
proto_tree_add_uint_format(rtps_submessage_tree, hf_rtps_octets_to_next_header,
tvb, offset, 2, next_submsg_offset,
"Octets to next header: %u (bogus, must be >= 8)",
next_submsg_offset);
return;
}
proto_tree_add_uint(rtps_submessage_tree, hf_rtps_octets_to_next_header,
tvb, offset, 2, next_submsg_offset);
offset +=2;
next_submsg_offset += offset;
/* Host Id */
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
"Host ID: %s",
host_id_to_string(offset,tvb,buff));
offset+=4;
/* App Id */
proto_tree_add_text(rtps_submessage_tree, tvb, offset, 4,
"App ID: %s-new",
app_id_to_string(offset, tvb, buff));
offset +=4;
}
/* *********************************************************************** *
* *
* Register the protocol with Ethereal *
* *
* *********************************************************************** */
void proto_register_rtps(void)
{
static hf_register_info hf[] = {
{ &hf_rtps_submessage_id,
{ "Submessage Id", "rtps.submessage_id",
FT_UINT8, BASE_HEX, VALS(submessage_id_vals), 0x0,
"Submessage flags", HFILL }},
{ &hf_rtps_submessage_flags,
{ "Submessage flags", "rtps.submessage_flags",
FT_UINT8, BASE_HEX, NULL, 0x0,
"Submessage flags", HFILL }},
{ &hf_rtps_octets_to_next_header,
{ "Octets to next header", "rtps.octets_to_next_header",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Octets to next header", HFILL }},
{ &hf_rtps_parameter_id,
{ "Parameter Id", "rtps.parameter_id",
FT_UINT16, BASE_HEX, VALS(parameter_id_vals), 0x0,
"Parameter Id", HFILL }},
{ &hf_rtps_parameter_length,
{ "Parameter Length", "rtps.parameter_length",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Parameter Length", HFILL }},
{ &hf_rtps_issue_data,
{ "User Data", "rtps.issue_data",
FT_BYTES, BASE_HEX, NULL, 0x0,
"Issue Data", HFILL }},
};
static gint *ett[] = {
&ett_rtps,
&ett_rtps_submessage,
&ett_rtps_bitmap,
&ett_rtps_parameter_sequence,
&ett_rtps_parameter,
};
proto_rtps = proto_register_protocol("Real-Time Publish-Subscribe Wire Protocol",
"RTPS", "rtps");
proto_register_field_array(proto_rtps, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
}
void
proto_reg_handoff_rtps(void)
{
heur_dissector_add("udp", dissect_rtps, proto_rtps);
}