wireshark/epan/dissectors/packet-xtp.c

1399 lines
39 KiB
C

/* packet-xtp.c
* Routines for Xpress Transport Protocol dissection
* Copyright 2008, Shigeo Nakamura <naka_shigeo@yahoo.co.jp>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*
* Ref: http://www.packeteer.com/resources/prod-sol/XTP.pdf
*/
#include "config.h"
#include <epan/packet.h>
#include <epan/exceptions.h>
#include <epan/expert.h>
#include <epan/ipproto.h>
#include <epan/in_cksum.h>
#define XTP_VERSION_4 0x001
/* XTP type of Service */
#define XTP_TOS_UNSPEC 0
#define XTP_TOS_UNACKED_DGRAM 1
#define XTP_TOS_ACKED_DGRAM 2
#define XTP_TOS_TRANS 3
#define XTP_TOS_UNICAST_STREAM 4
#define XTP_TOS_UNACKED_MULTICAST_STREAM 5
#define XTP_TOS_MULTICAST_STREAM 6
/* Address Format */
#define XTP_ADDR_NULL 0
#define XTP_ADDR_IP 1
#define XTP_ADDR_ISO 2
#define XTP_ADDR_XEROX 3
#define XTP_ADDR_IPX 4
#define XTP_ADDR_LOCAL 5
#define XTP_ADDR_IP6 6
/* packet type */
#define XTP_DATA_PKT 0
#define XTP_CNTL_PKT 1
#define XTP_FIRST_PKT 2
#define XTP_ECNTL_PKT 3
#define XTP_TCNTL_PKT 5
#define XTP_JOIN_PKT 6
#define XTP_JCNTL_PKT 7
#define XTP_DIAG_PKT 8
/* cmd options mask */
#define XTP_CMD_OPTIONS_NOCHECK 0x400000
#define XTP_CMD_OPTIONS_EDGE 0x200000
#define XTP_CMD_OPTIONS_NOERR 0x100000
#define XTP_CMD_OPTIONS_MULTI 0x080000
#define XTP_CMD_OPTIONS_RES 0x040000
#define XTP_CMD_OPTIONS_SORT 0x020000
#define XTP_CMD_OPTIONS_NOFLOW 0x010000
#define XTP_CMD_OPTIONS_FASTNAK 0x008000
#define XTP_CMD_OPTIONS_SREQ 0x004000
#define XTP_CMD_OPTIONS_DREQ 0x002000
#define XTP_CMD_OPTIONS_RCLOSE 0x001000
#define XTP_CMD_OPTIONS_WCLOSE 0x000800
#define XTP_CMD_OPTIONS_EOM 0x000400
#define XTP_CMD_OPTIONS_END 0x000200
#define XTP_CMD_OPTIONS_BTAG 0x000100
#define XTP_KEY_RTN ((guint64)1<<63)
void proto_register_xtp(void);
void proto_reg_handoff_xtp(void);
/** packet structures definition **/
struct xtp_cntl {
guint64 rseq;
guint64 alloc;
guint32 echo;
};
#define XTP_CNTL_PKT_LEN 20
struct xtp_ecntl {
guint64 rseq;
guint64 alloc;
guint32 echo;
guint32 nspan;
};
#define MIN_XTP_ECNTL_PKT_LEN 24
struct xtp_traffic_cntl {
guint64 rseq;
guint64 alloc;
guint32 echo;
guint32 rsvd;
guint64 xkey;
};
#define XTP_TRAFFIC_CNTL_LEN 32
/* tformat = 0x00 */
struct xtp_traffic_spec0 {
guint16 tlen;
guint8 service;
guint8 tformat;
guint32 none;
};
#define XTP_TRAFFIC_SPEC0_LEN 8
/* tformat = 0x01 */
struct xtp_traffic_spec1 {
guint16 tlen;
guint8 service;
guint8 tformat;
guint32 maxdata;
guint32 inrate;
guint32 inburst;
guint32 outrate;
guint32 outburst;
};
#define XTP_TRAFFIC_SPEC1_LEN 24
struct xtp_ip_addr_seg {
guint16 alen;
guint8 adomain;
guint8 aformat;
guint32 dsthost;
guint32 srchost;
guint16 dstport;
guint16 srcport;
};
#define XTP_IP_ADDR_SEG_LEN 16
#define XTP_NULL_ADDR_SEG_LEN 8
struct xtp_diag {
guint32 code;
guint32 val;
gchar *msg;
};
#define XTP_DIAG_PKT_HEADER_LEN 8
struct xtphdr {
guint64 key;
guint32 cmd;
guint32 cmd_options; /* 24 bits */
guint8 cmd_ptype;
guint8 cmd_ptype_ver; /* 3 bits */
guint8 cmd_ptype_pformat; /* 5 bits */
guint32 dlen;
guint16 check;
guint16 sort;
guint32 sync;
guint64 seq;
};
#define XTP_HEADER_LEN 32
static const value_string version_vals[] = {
{ XTP_VERSION_4, "XTP version 4.0" },
{ 0, NULL }
};
static const value_string service_vals[] = {
{ XTP_TOS_UNSPEC, "Unspecified" },
{ XTP_TOS_UNACKED_DGRAM, "Traditional Unacknowledged Datagram Service" },
{ XTP_TOS_ACKED_DGRAM, "Acknowledged Datagram Service" },
{ XTP_TOS_TRANS, "Transaction Service" },
{ XTP_TOS_UNICAST_STREAM, "Traditional Reliable Unicast Stream Service" },
{ XTP_TOS_UNACKED_MULTICAST_STREAM, "Unacknowledged Multicast Stream Service" },
{ XTP_TOS_MULTICAST_STREAM, "Reliable Multicast Stream Service" },
{ 0, NULL }
};
static const value_string aformat_vals[] = {
{ XTP_ADDR_NULL, "Null Address" },
{ XTP_ADDR_IP, "Internet Protocol Address" },
{ XTP_ADDR_ISO, "ISO Connectionless Network Layer Protocol Address" },
{ XTP_ADDR_XEROX, "Xerox Network System Address" },
{ XTP_ADDR_IPX, "IPX Address" },
{ XTP_ADDR_LOCAL, "Local Address" },
{ XTP_ADDR_IP6, "Internet Protocol Version 6 Address" },
{ 0, NULL }
};
static const value_string pformat_vals[] = {
{ XTP_DATA_PKT, "DATA" },
{ XTP_CNTL_PKT, "CNTL" },
{ XTP_FIRST_PKT, "FIRST" },
{ XTP_ECNTL_PKT, "ECNTL" },
{ XTP_TCNTL_PKT, "TCNTL" },
{ XTP_JOIN_PKT, "JOIN<obsolete>" },
{ XTP_JCNTL_PKT, "JCNTL" },
{ XTP_DIAG_PKT, "DIAG" },
{ 0, NULL }
};
static const value_string diag_code_vals[] = {
{ 1, "Context Refused" },
{ 2, "Context Abandoned" },
{ 3, "Invalid Context" },
{ 4, "Request Refused" },
{ 5, "Join Refused" },
{ 6, "Protocol Error" },
{ 7, "Maximum Packet Size Error" },
{ 0, NULL }
};
static const value_string diag_val_vals[] = {
{ 0, "Unspecified" },
{ 1, "No listener" },
{ 2, "Options refused" },
{ 3, "Address format not supported" },
{ 4, "Malformed address format" },
{ 5, "Traffic format not supported" },
{ 6, "Traffic specification refused" },
{ 7, "Malformed traffic format" },
{ 8, "No provider for service" },
{ 9, "No resource" },
{ 10, "Host going down" },
{ 11, "Invalid retransmission request" },
{ 12, "Context in improper state" },
{ 13, "Join request denied" },
{ 0, NULL }
};
/* Initialize the protocol and registered fields */
static int proto_xtp = -1;
/* common header */
static int hf_xtp_key = -1;
static int hf_xtp_cmd = -1;
static int hf_xtp_cmd_options = -1;
static int hf_xtp_cmd_options_nocheck = -1;
static int hf_xtp_cmd_options_edge = -1;
static int hf_xtp_cmd_options_noerr = -1;
static int hf_xtp_cmd_options_multi = -1;
static int hf_xtp_cmd_options_res = -1;
static int hf_xtp_cmd_options_sort = -1;
static int hf_xtp_cmd_options_noflow = -1;
static int hf_xtp_cmd_options_fastnak = -1;
static int hf_xtp_cmd_options_sreq = -1;
static int hf_xtp_cmd_options_dreq = -1;
static int hf_xtp_cmd_options_rclose = -1;
static int hf_xtp_cmd_options_wclose = -1;
static int hf_xtp_cmd_options_eom = -1;
static int hf_xtp_cmd_options_end = -1;
static int hf_xtp_cmd_options_btag = -1;
static int hf_xtp_cmd_ptype = -1;
static int hf_xtp_cmd_ptype_ver = -1;
static int hf_xtp_cmd_ptype_pformat = -1;
static int hf_xtp_dlen = -1;
static int hf_xtp_sort = -1;
static int hf_xtp_sync = -1;
static int hf_xtp_seq = -1;
/* control segment */
static int hf_xtp_cntl_rseq = -1;
static int hf_xtp_cntl_alloc = -1;
static int hf_xtp_cntl_echo = -1;
static int hf_xtp_ecntl_rseq = -1;
static int hf_xtp_ecntl_alloc = -1;
static int hf_xtp_ecntl_echo = -1;
static int hf_xtp_ecntl_nspan = -1;
static int hf_xtp_ecntl_span_left = -1;
static int hf_xtp_ecntl_span_right = -1;
static int hf_xtp_tcntl_rseq = -1;
static int hf_xtp_tcntl_alloc = -1;
static int hf_xtp_tcntl_echo = -1;
static int hf_xtp_tcntl_rsvd = -1;
static int hf_xtp_tcntl_xkey = -1;
/* traffic specifier */
static int hf_xtp_tspec_tlen = -1;
static int hf_xtp_tspec_service = -1;
static int hf_xtp_tspec_tformat = -1;
static int hf_xtp_tspec_traffic = -1;
static int hf_xtp_tspec_maxdata = -1;
static int hf_xtp_tspec_inrate = -1;
static int hf_xtp_tspec_outrate = -1;
static int hf_xtp_tspec_inburst = -1;
static int hf_xtp_tspec_outburst = -1;
/* address segment */
static int hf_xtp_aseg_alen = -1;
static int hf_xtp_aseg_adomain = -1;
static int hf_xtp_aseg_aformat = -1;
static int hf_xtp_aseg_address = -1;
static int hf_xtp_aseg_dsthost = -1;
static int hf_xtp_aseg_srchost = -1;
static int hf_xtp_aseg_dstport = -1;
static int hf_xtp_aseg_srcport = -1;
/* others */
static int hf_xtp_btag = -1;
static int hf_xtp_diag_code = -1;
static int hf_xtp_diag_val = -1;
static int hf_xtp_diag_msg = -1;
static int hf_xtp_checksum = -1;
static int hf_xtp_checksum_status = -1;
static int hf_xtp_data = -1;
/* Initialize the subtree pointers */
static gint ett_xtp = -1;
static gint ett_xtp_cmd = -1;
static gint ett_xtp_cmd_options = -1;
static gint ett_xtp_cmd_ptype = -1;
static gint ett_xtp_cntl = -1;
static gint ett_xtp_ecntl = -1;
static gint ett_xtp_tcntl = -1;
static gint ett_xtp_tspec = -1;
static gint ett_xtp_jcntl = -1;
static gint ett_xtp_first = -1;
static gint ett_xtp_aseg = -1;
static gint ett_xtp_data = -1;
static gint ett_xtp_diag = -1;
static expert_field ei_xtp_spans_bad = EI_INIT;
static expert_field ei_xtp_checksum = EI_INIT;
/* dissector of each payload */
static int
dissect_xtp_aseg(tvbuff_t *tvb, proto_tree *tree, guint32 offset) {
guint32 len = tvb_reported_length_remaining(tvb, offset);
guint32 start = offset;
proto_item *ti, *ti2, *top_ti;
proto_tree *xtp_subtree;
struct xtp_ip_addr_seg aseg[1];
int error = 0;
xtp_subtree = proto_tree_add_subtree(tree, tvb, offset, len, ett_xtp_aseg, &top_ti, "Address Segment");
if (len < XTP_NULL_ADDR_SEG_LEN) {
proto_item_append_text(top_ti, ", bogus length(%u, must be at least %u)",
len, XTP_NULL_ADDR_SEG_LEN);
return 0;
}
/** parse common fields **/
/* alen(2) */
aseg->alen = tvb_get_ntohs(tvb, offset);
offset += 2;
/* adomain(1) */
aseg->adomain = tvb_get_guint8(tvb, offset);
offset++;
/* aformat(1) */
aseg->aformat = tvb_get_guint8(tvb, offset);
/** display common fields **/
offset = start;
/* alen(2) */
ti = proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_alen,
tvb, offset, 2, aseg->alen);
offset += 2;
if (aseg->alen > len) {
proto_item_append_text(ti, ", bogus length(%u, must be at most %u)",
aseg->alen, len);
error = 1;
}
/* adomain(1) */
proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_adomain,
tvb, offset, 1, aseg->adomain);
offset++;
/* aformat(1) */
ti2 = proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_aformat,
tvb, offset, 1, aseg->aformat);
offset++;
switch (aseg->aformat) {
case 0:
if (aseg->alen != XTP_NULL_ADDR_SEG_LEN) {
proto_item_append_text(ti, ", bogus length(%u, must be %u)",
aseg->alen, XTP_NULL_ADDR_SEG_LEN);
error = 1;
}
break;
case 1:
if (aseg->alen != XTP_IP_ADDR_SEG_LEN) {
proto_item_append_text(ti, ", bogus length(%u, must be %u)",
aseg->alen, XTP_IP_ADDR_SEG_LEN);
error = 1;
}
break;
default:
if (aseg->aformat < 128) {
proto_item_append_text(ti2,
", Unsupported aformat(%u)", aseg->aformat);
error = 1;
}
break;
}
if (error)
return (offset - start);
/** parse and display each address fileds */
switch (aseg->aformat) {
case 0:
/* address(4) */
aseg->dsthost = tvb_get_ntohl(tvb, offset);
proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_address,
tvb, offset, 4, aseg->dsthost);
offset += 4;
break;
case 1:
/* dsthost(4) */
aseg->dsthost = tvb_get_ipv4(tvb, offset);
proto_tree_add_ipv4(xtp_subtree, hf_xtp_aseg_dsthost,
tvb, offset, 4, aseg->dsthost);
offset += 4;
/* srchost(4) */
aseg->srchost = tvb_get_ipv4(tvb, offset);
proto_tree_add_ipv4(xtp_subtree, hf_xtp_aseg_srchost,
tvb, offset, 4, aseg->srchost);
offset += 4;
/* dstport(2) */
aseg->dstport = tvb_get_ntohs(tvb, offset);
proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_dstport,
tvb, offset, 2, aseg->dstport);
offset += 2;
/* srcport(2) */
aseg->srcport = tvb_get_ntohs(tvb, offset);
proto_tree_add_uint(xtp_subtree, hf_xtp_aseg_srcport,
tvb, offset, 2, aseg->srcport);
offset += 2;
/** add summary **/
proto_item_append_text(top_ti, ", Dst Port: %u", aseg->dstport);
proto_item_append_text(top_ti, ", Src Port: %u", aseg->srcport);
break;
default:
break;
}
return (offset - start);
}
static int
dissect_xtp_traffic_cntl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
guint32 offset) {
guint32 len = tvb_reported_length_remaining(tvb, offset);
guint32 start = offset;
proto_item *top_ti;
proto_tree *xtp_subtree;
struct xtp_traffic_cntl tcntl[1];
xtp_subtree = proto_tree_add_subtree(tree, tvb, offset, len,
ett_xtp_tcntl, &top_ti, "Traffic Control Segment");
if (len < XTP_TRAFFIC_CNTL_LEN) {
proto_item_append_text(top_ti,
", bogus length(%u, must be at least %u)",
len, XTP_TRAFFIC_CNTL_LEN);
return 0;
}
/** parse **/
/* rseq(8) */
tcntl->rseq = tvb_get_ntohl(tvb, offset);
tcntl->rseq <<= 32;
tcntl->rseq += tvb_get_ntohl(tvb, offset+4);
offset += 8;
/* alloc(8) */
tcntl->alloc = tvb_get_ntohl(tvb, offset);
tcntl->alloc <<= 32;
tcntl->alloc += tvb_get_ntohl(tvb, offset+4);
offset += 8;
/* echo(4) */
tcntl->echo = tvb_get_ntohl(tvb, offset);
offset += 4;
/* rsvd(4) */
tcntl->rsvd = tvb_get_ntohl(tvb, offset);
offset += 4;
/* xkey(8) */
tcntl->xkey = tvb_get_ntohl(tvb, offset);
tcntl->xkey <<= 32;
tcntl->xkey += tvb_get_ntohl(tvb, offset+4);
/** add summary **/
col_append_fstr(pinfo->cinfo, COL_INFO,
" Recv-Seq=%" G_GINT64_MODIFIER "u", tcntl->rseq);
col_append_fstr(pinfo->cinfo, COL_INFO,
" Alloc=%" G_GINT64_MODIFIER "u", tcntl->alloc);
proto_item_append_text(top_ti,
", Recv-Seq: %" G_GINT64_MODIFIER "u", tcntl->rseq);
/** display **/
offset = start;
/* rseq(8) */
proto_tree_add_uint64(xtp_subtree, hf_xtp_tcntl_rseq,
tvb, offset, 8, tcntl->rseq);
offset += 8;
/* alloc(8) */
proto_tree_add_uint64(xtp_subtree, hf_xtp_tcntl_alloc,
tvb, offset, 8, tcntl->alloc);
offset += 4;
/* echo(4) */
proto_tree_add_uint(xtp_subtree, hf_xtp_tcntl_echo,
tvb, offset, 4, tcntl->echo);
offset += 4;
/* rsvd(4) */
proto_tree_add_uint(xtp_subtree, hf_xtp_tcntl_rsvd,
tvb, offset, 4, tcntl->rsvd);
offset += 4;
/* xkey(8) */
proto_tree_add_uint64(xtp_subtree, hf_xtp_tcntl_xkey,
tvb, offset, 8, tcntl->xkey);
offset += 8;
return (offset - start);
}
static int
dissect_xtp_tspec(tvbuff_t *tvb, proto_tree *tree, guint32 offset) {
guint32 len = tvb_reported_length_remaining(tvb, offset);
guint32 start = offset;
proto_item *ti, *ti2;
proto_tree *xtp_subtree;
struct xtp_traffic_spec1 tspec[1];
int error = 0;
xtp_subtree = proto_tree_add_subtree(tree, tvb, offset, len, ett_xtp_tspec, &ti, "Traffic Specifier");
if (len < XTP_TRAFFIC_SPEC0_LEN) {
proto_item_append_text(ti,
", bogus length(%u, must be at least %u)",
len, XTP_TRAFFIC_SPEC0_LEN);
return 0;
}
/** parse common fields **/
/* tlen(2) */
tspec->tlen = tvb_get_ntohs(tvb, offset);
offset += 2;
/* service(1) */
tspec->service = tvb_get_guint8(tvb, offset);
offset++;
/* tformat(1) */
tspec->tformat = tvb_get_guint8(tvb, offset);
/** display common fields */
offset = start;
/* tlen(2) */
ti = proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_tlen,
tvb, offset, 2, tspec->tlen);
offset += 2;
if (tspec->tlen > len) {
proto_item_append_text(ti, ", bogus length(%u, must be at most %u)",
tspec->tlen, len);
error = 1;
}
/* service(1) */
proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_service,
tvb, offset, 1, tspec->service);
offset++;
/* tformat(1) */
ti2 = proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_tformat,
tvb, offset, 1, tspec->tformat);
offset++;
switch (tspec->tformat) {
case 0:
if (tspec->tlen != XTP_TRAFFIC_SPEC0_LEN) {
proto_item_append_text(ti, ", bogus length(%u, must be %u)",
tspec->tlen, XTP_TRAFFIC_SPEC0_LEN);
error = 1;
}
break;
case 1:
if (tspec->tlen != XTP_TRAFFIC_SPEC1_LEN) {
proto_item_append_text(ti, ", bogus length(%u, must be %u)",
tspec->tlen, XTP_TRAFFIC_SPEC1_LEN);
error = 1;
}
break;
default:
proto_item_append_text(ti2, ", Unsupported tformat(%u)",
tspec->tformat);
error = 1;
break;
}
if (error)
return (offset - start);
/** parse and display each traffic fields **/
switch (tspec->tformat) {
case 0:
/* traffic(4) */
tspec->maxdata = tvb_get_ntohl(tvb, offset);
proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_traffic,
tvb, offset, 4, tspec->maxdata);
offset += 4;
break;
case 1:
/* maxdata(4) */
tspec->maxdata = tvb_get_ntohl(tvb, offset);
proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_maxdata,
tvb, offset, 4, tspec->maxdata);
offset += 4;
/* inrate(4) */
tspec->inrate = tvb_get_ntohl(tvb, offset);
proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_inrate,
tvb, offset, 4, tspec->inrate);
offset += 4;
/* inburst(4) */
tspec->inburst = tvb_get_ntohl(tvb, offset);
proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_inburst,
tvb, offset, 4, tspec->inburst);
offset += 4;
/* outrate(4) */
tspec->outrate = tvb_get_ntohl(tvb, offset);
proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_outrate,
tvb, offset, 4, tspec->outrate);
offset += 4;
/* outburst(4) */
tspec->outburst = tvb_get_ntohl(tvb, offset);
proto_tree_add_uint(xtp_subtree, hf_xtp_tspec_outburst,
tvb, offset, 4, tspec->outburst);
offset += 4;
break;
default:
break;
}
return (offset - start);
}
static void
dissect_xtp_data(tvbuff_t *tvb, proto_tree *tree, guint32 offset, gboolean have_btag) {
guint32 len = tvb_reported_length_remaining(tvb, offset);
proto_tree *xtp_subtree;
guint64 btag;
xtp_subtree = proto_tree_add_subtree(tree, tvb, offset, len, ett_xtp_data, NULL, "Data Segment");
if (have_btag) {
btag = tvb_get_ntohl(tvb, offset);
btag <<= 32;
btag += tvb_get_ntohl(tvb, offset+4);
proto_tree_add_uint64(xtp_subtree, hf_xtp_btag, tvb, offset, 8, btag);
offset += 8;
len -= 8;
}
proto_tree_add_item(xtp_subtree, hf_xtp_data, tvb, offset, len, ENC_NA);
return;
}
static void
dissect_xtp_cntl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
guint32 offset) {
guint32 len = tvb_reported_length_remaining(tvb, offset);
guint32 start = offset;
proto_item *top_ti;
proto_tree *xtp_subtree;
struct xtp_cntl cntl[1];
xtp_subtree = proto_tree_add_subtree(tree, tvb, offset, len,
ett_xtp_cntl, &top_ti, "Common Control Segment");
if (len != XTP_CNTL_PKT_LEN) {
proto_item_append_text(top_ti, ", bogus length(%u, must be %u)",
len, XTP_CNTL_PKT_LEN);
return;
}
/** parse **/
/* rseq(8) */
cntl->rseq = tvb_get_ntohl(tvb, offset);
cntl->rseq <<= 32;
cntl->rseq += tvb_get_ntohl(tvb, offset+4);
offset += 8;
/* alloc(8) */
cntl->alloc = tvb_get_ntohl(tvb, offset);
cntl->alloc <<= 32;
cntl->alloc += tvb_get_ntohl(tvb, offset+4);
offset += 8;
/* echo(4) */
cntl->echo = tvb_get_ntohl(tvb, offset);
/** add summary **/
col_append_fstr(pinfo->cinfo, COL_INFO,
" Recv-Seq=%" G_GINT64_MODIFIER "u", cntl->rseq);
col_append_fstr(pinfo->cinfo, COL_INFO,
" Alloc=%" G_GINT64_MODIFIER "u", cntl->alloc);
proto_item_append_text(top_ti,
", Recv-Seq: %" G_GINT64_MODIFIER "u", cntl->rseq);
/** display **/
offset = start;
/* rseq(8) */
proto_tree_add_uint64(xtp_subtree, hf_xtp_cntl_rseq,
tvb, offset, 8, cntl->rseq);
offset += 8;
/* alloc(8) */
proto_tree_add_uint64(xtp_subtree, hf_xtp_cntl_alloc,
tvb, offset, 8, cntl->alloc);
offset += 4;
/* echo(4) */
proto_tree_add_uint(xtp_subtree, hf_xtp_cntl_echo,
tvb, offset, 4, cntl->echo);
return;
}
static void
dissect_xtp_first(tvbuff_t *tvb, proto_tree *tree, guint32 offset) {
if (!dissect_xtp_aseg(tvb, tree, offset))
return;
offset += XTP_IP_ADDR_SEG_LEN;
dissect_xtp_tspec(tvb, tree, offset);
return;
}
#define XTP_MAX_NSPANS 10000 /* Arbitrary. (Documentation link is dead.) */
static void
dissect_xtp_ecntl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
guint32 offset) {
guint32 len = tvb_reported_length_remaining(tvb, offset);
guint32 start = offset;
proto_item *top_ti;
proto_tree *xtp_subtree;
struct xtp_ecntl ecntl[1];
guint spans_len;
guint i;
xtp_subtree = proto_tree_add_subtree(tree, tvb, offset, len,
ett_xtp_ecntl, &top_ti, "Error Control Segment");
if (len < MIN_XTP_ECNTL_PKT_LEN) {
proto_item_append_text(top_ti,
", bogus length (%u, must be at least %u)",
len, MIN_XTP_ECNTL_PKT_LEN);
return;
}
/** parse **/
/* rseq(8) */
ecntl->rseq = tvb_get_ntohl(tvb, offset);
ecntl->rseq <<= 32;
ecntl->rseq += tvb_get_ntohl(tvb, offset+4);
offset += 8;
/* alloc(8) */
ecntl->alloc = tvb_get_ntohl(tvb, offset);
ecntl->alloc <<= 32;
ecntl->alloc += tvb_get_ntohl(tvb, offset+4);
offset += 8;
/* echo(4) */
ecntl->echo = tvb_get_ntohl(tvb, offset);
offset += 4;
/* nspan(4) */
ecntl->nspan = tvb_get_ntohl(tvb, offset);
offset += 4;
len = len + XTP_HEADER_LEN - offset;
spans_len = 16 * ecntl->nspan;
if (len != spans_len) {
expert_add_info_format(pinfo, top_ti, &ei_xtp_spans_bad, "Number of spans (%u) incorrect. Should be %u.", ecntl->nspan, len);
return;
}
if (ecntl->nspan > XTP_MAX_NSPANS) {
expert_add_info_format(pinfo, top_ti, &ei_xtp_spans_bad, "Too many spans: %u", ecntl->nspan);
return;
}
/** add summary **/
col_append_fstr(pinfo->cinfo, COL_INFO,
" Recv-Seq=%" G_GINT64_MODIFIER "u", ecntl->rseq);
col_append_fstr(pinfo->cinfo, COL_INFO,
" Alloc=%" G_GINT64_MODIFIER "u", ecntl->alloc);
proto_item_append_text(top_ti,
", Recv-Seq: %" G_GINT64_MODIFIER "u", ecntl->rseq);
/** display **/
offset = start;
/* rseq(8) */
proto_tree_add_uint64(xtp_subtree, hf_xtp_ecntl_rseq,
tvb, offset, 8, ecntl->rseq);
offset += 8;
/* alloc(8) */
proto_tree_add_uint64(xtp_subtree, hf_xtp_ecntl_alloc,
tvb, offset, 8, ecntl->alloc);
offset += 8;
/* echo(4) */
proto_tree_add_uint(xtp_subtree, hf_xtp_ecntl_echo,
tvb, offset, 4, ecntl->echo);
offset += 4;
/* nspan(4) */
proto_tree_add_uint(xtp_subtree, hf_xtp_ecntl_nspan,
tvb, offset, 4, ecntl->nspan);
offset += 4;
/* spans(16n) */
for (i = 0; i < ecntl->nspan; i++) {
proto_tree_add_item(xtp_subtree, hf_xtp_ecntl_span_left,
tvb, offset, 8, ENC_LITTLE_ENDIAN);
offset += 8;
proto_tree_add_item(xtp_subtree, hf_xtp_ecntl_span_right,
tvb, offset, 8, ENC_LITTLE_ENDIAN);
offset += 8;
}
return;
}
static void
dissect_xtp_tcntl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
guint32 offset) {
if (!dissect_xtp_traffic_cntl(tvb, pinfo, tree, offset))
return;
offset += XTP_TRAFFIC_CNTL_LEN;
dissect_xtp_tspec(tvb, tree, offset);
return;
}
static void
dissect_xtp_jcntl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
guint32 offset) {
if (!dissect_xtp_traffic_cntl(tvb, pinfo, tree, offset))
return;
offset += XTP_TRAFFIC_CNTL_LEN;
if (!dissect_xtp_aseg(tvb, tree, offset))
return;
offset += XTP_IP_ADDR_SEG_LEN;
dissect_xtp_tspec(tvb, tree, offset);
return;
}
static void
dissect_xtp_diag(tvbuff_t *tvb, proto_tree *tree, guint32 offset) {
guint32 len = tvb_reported_length_remaining(tvb, offset);
proto_item *ti;
proto_tree *xtp_subtree;
xtp_subtree = proto_tree_add_subtree(tree, tvb, offset, len, ett_xtp_diag, &ti, "Diagnostic Segment");
if (len < XTP_DIAG_PKT_HEADER_LEN) {
proto_item_append_text(ti,
", bogus length (%u, must be at least %u)",
len, XTP_DIAG_PKT_HEADER_LEN);
return;
}
/* code(4) */
proto_tree_add_item(xtp_subtree, hf_xtp_diag_code,
tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
/* val(4) */
proto_tree_add_item(xtp_subtree, hf_xtp_diag_val,
tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
/* message(n) */
proto_tree_add_item(xtp_subtree, hf_xtp_diag_msg,
tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_ASCII|ENC_NA);
return;
}
/* main dissector */
static int
dissect_xtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
guint32 offset, len;
proto_item *ti;
proto_tree *xtp_tree, *xtp_cmd_tree, *xtp_subtree;
struct xtphdr xtph[1];
int error = 0;
gchar *options;
static const char *fstr[] = { "<None>", "NOCHECK", "EDGE", "NOERR", "MULTI", "RES",
"SORT", "NOFLOW", "FASTNAK", "SREQ", "DREQ",
"RCLOSE", "WCLOSE", "EOM", "END", "BTAG" };
gint fpos = 0, returned_length;
guint i, bpos;
guint cmd_options;
vec_t cksum_vec[1];
gboolean have_btag;
static int * const cmd_options_flags[] = {
&hf_xtp_cmd_options_nocheck,
&hf_xtp_cmd_options_edge,
&hf_xtp_cmd_options_noerr,
&hf_xtp_cmd_options_multi,
&hf_xtp_cmd_options_res,
&hf_xtp_cmd_options_sort,
&hf_xtp_cmd_options_noflow,
&hf_xtp_cmd_options_fastnak,
&hf_xtp_cmd_options_sreq,
&hf_xtp_cmd_options_dreq,
&hf_xtp_cmd_options_rclose,
&hf_xtp_cmd_options_wclose,
&hf_xtp_cmd_options_eom,
&hf_xtp_cmd_options_end,
&hf_xtp_cmd_options_btag,
NULL
};
if ((len = tvb_reported_length(tvb)) < XTP_HEADER_LEN)
return 0;
col_set_str(pinfo->cinfo, COL_PROTOCOL, "XTP");
col_clear(pinfo->cinfo, COL_INFO);
/** parse header **/
offset = 0;
/* key(8) */
xtph->key = tvb_get_ntohl(tvb, offset);
xtph->key <<= 32;
xtph->key += tvb_get_ntohl(tvb, offset+4);
offset += 8;
/* cmd(4) */
xtph->cmd = tvb_get_ntohl(tvb, offset);
xtph->cmd_options = xtph->cmd >> 8;
xtph->cmd_ptype = xtph->cmd & 0xff;
xtph->cmd_ptype_ver = (xtph->cmd_ptype & 0xe0) >> 5;
xtph->cmd_ptype_pformat = xtph->cmd_ptype & 0x1f;
offset += 4;
/* dlen(4) */
xtph->dlen = tvb_get_ntohl(tvb, offset);
offset += 4;
/* check(2) */
xtph->check = tvb_get_ntohs(tvb, offset);
offset += 2;
/* sort(2) */
xtph->sort = tvb_get_ntohs(tvb, offset);
offset += 2;
/* sync(4) */
xtph->sync = tvb_get_ntohl(tvb, offset);
offset += 4;
/* seq(8) */
xtph->seq = tvb_get_ntohl(tvb, offset);
xtph->seq <<= 32;
xtph->seq += tvb_get_ntohl(tvb, offset+4);
#define MAX_OPTIONS_LEN 128
options=(gchar *)wmem_alloc(wmem_packet_scope(), MAX_OPTIONS_LEN);
options[0]=0;
cmd_options = xtph->cmd_options >> 8;
for (i = 0; i < 16; i++) {
bpos = 1 << (15 - i);
if (cmd_options & bpos) {
returned_length = g_snprintf(&options[fpos],
MAX_OPTIONS_LEN-fpos, "%s%s",
fpos?", ":"",
fstr[i]);
fpos += MIN(returned_length, MAX_OPTIONS_LEN-fpos);
}
}
col_add_str(pinfo->cinfo, COL_INFO,
val_to_str(xtph->cmd_ptype_pformat,
pformat_vals, "Unknown pformat (%u)"));
col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", options);
col_append_fstr(pinfo->cinfo, COL_INFO,
" Seq=%" G_GINT64_MODIFIER "u", xtph->seq);
col_append_fstr(pinfo->cinfo, COL_INFO, " Len=%u", xtph->dlen);
/* if (tree) */ {
ti = proto_tree_add_item(tree, proto_xtp, tvb, 0, -1, ENC_NA);
/** add summary **/
proto_item_append_text(ti,
", Key: 0x%016" G_GINT64_MODIFIER "X", xtph->key);
proto_item_append_text(ti,
", Seq: %" G_GINT64_MODIFIER "u", xtph->seq);
proto_item_append_text(ti, ", Len: %u", xtph->dlen);
xtp_tree = proto_item_add_subtree(ti, ett_xtp);
/* key(8) */
offset = 0;
proto_tree_add_uint64(xtp_tree, hf_xtp_key,
tvb, offset, 8, xtph->key);
offset += 8;
/* cmd(4) */
ti = proto_tree_add_uint(xtp_tree, hf_xtp_cmd,
tvb, offset, 4, xtph->cmd);
xtp_cmd_tree = proto_item_add_subtree(ti, ett_xtp_cmd);
proto_tree_add_bitmask(xtp_cmd_tree, tvb, offset, hf_xtp_cmd_options, ett_xtp_cmd_options, cmd_options_flags, ENC_BIG_ENDIAN);
offset += 3;
ti = proto_tree_add_uint(xtp_cmd_tree, hf_xtp_cmd_ptype,
tvb, offset, 1, xtph->cmd_ptype);
xtp_subtree = proto_item_add_subtree(ti, ett_xtp_cmd_ptype);
proto_tree_add_uint(xtp_subtree, hf_xtp_cmd_ptype_ver,
tvb, offset, 1, xtph->cmd_ptype_ver);
if (xtph->cmd_ptype_ver != XTP_VERSION_4) {
proto_item_append_text(ti,
", Unknown XTP version (%03X)", xtph->cmd_ptype_ver);
error = 1;
}
proto_tree_add_uint(xtp_subtree, hf_xtp_cmd_ptype_pformat,
tvb, offset, 1, xtph->cmd_ptype_pformat);
offset++;
/* dlen(4) */
ti = proto_tree_add_uint(xtp_tree, hf_xtp_dlen,
tvb, offset, 4, xtph->dlen);
if (xtph->dlen != len - XTP_HEADER_LEN) {
proto_item_append_text(ti, ", bogus length (%u, must be %u)",
xtph->dlen, len - XTP_HEADER_LEN);
error = 1;
}
offset += 4;
/* check(2) */
if (!pinfo->fragmented) {
guint32 check_len = XTP_HEADER_LEN;
if (!(xtph->cmd_options & XTP_CMD_OPTIONS_NOCHECK))
check_len += xtph->dlen;
SET_CKSUM_VEC_TVB(cksum_vec[0], tvb, 0, check_len);
proto_tree_add_checksum(xtp_tree, tvb, offset, hf_xtp_checksum, hf_xtp_checksum_status, &ei_xtp_checksum,
pinfo, in_cksum(cksum_vec, 1), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_IN_CKSUM);
}
else {
proto_tree_add_checksum(xtp_tree, tvb, offset, hf_xtp_checksum, hf_xtp_checksum_status, &ei_xtp_checksum,
pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
}
offset += 2;
/* sort(2) */
proto_tree_add_uint(xtp_tree, hf_xtp_sort, tvb, offset, 2, xtph->sort);
offset += 2;
/* sync(4) */
proto_tree_add_uint(xtp_tree, hf_xtp_sync, tvb, offset, 4, xtph->sync);
offset += 4;
/* seq(8) */
proto_tree_add_uint64(xtp_tree, hf_xtp_seq, tvb, offset, 8, xtph->seq);
offset += 8;
if (!error) {
switch (xtph->cmd_ptype_pformat) {
case XTP_DATA_PKT:
have_btag = !!(xtph->cmd_options & XTP_CMD_OPTIONS_BTAG);
dissect_xtp_data(tvb, xtp_tree, offset, have_btag);
break;
case XTP_CNTL_PKT:
dissect_xtp_cntl(tvb, pinfo, xtp_tree, offset);
break;
case XTP_FIRST_PKT:
dissect_xtp_first(tvb, xtp_tree, offset);
break;
case XTP_ECNTL_PKT:
dissect_xtp_ecntl(tvb, pinfo, xtp_tree, offset);
break;
case XTP_TCNTL_PKT:
dissect_xtp_tcntl(tvb, pinfo, xtp_tree, offset);
break;
case XTP_JOIN_PKT:
/* obsolete */
break;
case XTP_JCNTL_PKT:
dissect_xtp_jcntl(tvb, pinfo, xtp_tree, offset);
break;
case XTP_DIAG_PKT:
dissect_xtp_diag(tvb, xtp_tree, offset);
break;
default:
/* error */
break;
}
}
}
return tvb_reported_length(tvb);
}
void
proto_register_xtp(void)
{
static hf_register_info hf[] = {
/* command header */
{ &hf_xtp_key,
{ "Key", "xtp.key",
FT_UINT64, BASE_HEX, NULL, 0x0,
NULL, HFILL }
},
{ &hf_xtp_cmd,
{ "Command", "xtp.cmd",
FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_cmd_options,
{ "Options", "xtp.cmd.options",
FT_UINT24, BASE_HEX, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_cmd_options_nocheck,
{ "NOCHECK", "xtp.cmd.options.nocheck",
FT_BOOLEAN, 24, TFS(&tfs_set_notset),
XTP_CMD_OPTIONS_NOCHECK, NULL, HFILL }
},
{ &hf_xtp_cmd_options_edge,
{ "EDGE", "xtp.cmd.options.edge",
FT_BOOLEAN, 24, TFS(&tfs_set_notset),
XTP_CMD_OPTIONS_EDGE, NULL, HFILL }
},
{ &hf_xtp_cmd_options_noerr,
{ "NOERR", "xtp.cmd.options.noerr",
FT_BOOLEAN, 24, TFS(&tfs_set_notset),
XTP_CMD_OPTIONS_NOERR, NULL, HFILL }
},
{ &hf_xtp_cmd_options_multi,
{ "MULTI", "xtp.cmd.options.multi",
FT_BOOLEAN, 24, TFS(&tfs_set_notset),
XTP_CMD_OPTIONS_MULTI, NULL, HFILL }
},
{ &hf_xtp_cmd_options_res,
{ "RES", "xtp.cmd.options.res",
FT_BOOLEAN, 24, TFS(&tfs_set_notset),
XTP_CMD_OPTIONS_RES, NULL, HFILL }
},
{ &hf_xtp_cmd_options_sort,
{ "SORT", "xtp.cmd.options.sort",
FT_BOOLEAN, 24, TFS(&tfs_set_notset),
XTP_CMD_OPTIONS_SORT, NULL, HFILL }
},
{ &hf_xtp_cmd_options_noflow,
{ "NOFLOW", "xtp.cmd.options.noflow",
FT_BOOLEAN, 24, TFS(&tfs_set_notset),
XTP_CMD_OPTIONS_NOFLOW, NULL, HFILL }
},
{ &hf_xtp_cmd_options_fastnak,
{ "FASTNAK", "xtp.cmd.options.fastnak",
FT_BOOLEAN, 24, TFS(&tfs_set_notset),
XTP_CMD_OPTIONS_FASTNAK, NULL, HFILL }
},
{ &hf_xtp_cmd_options_sreq,
{ "SREQ", "xtp.cmd.options.sreq",
FT_BOOLEAN, 24, TFS(&tfs_set_notset),
XTP_CMD_OPTIONS_SREQ, NULL, HFILL }
},
{ &hf_xtp_cmd_options_dreq,
{ "DREQ", "xtp.cmd.options.dreq",
FT_BOOLEAN, 24, TFS(&tfs_set_notset),
XTP_CMD_OPTIONS_DREQ, NULL, HFILL }
},
{ &hf_xtp_cmd_options_rclose,
{ "RCLOSE", "xtp.cmd.options.rclose",
FT_BOOLEAN, 24, TFS(&tfs_set_notset),
XTP_CMD_OPTIONS_RCLOSE, NULL, HFILL }
},
{ &hf_xtp_cmd_options_wclose,
{ "WCLOSE", "xtp.cmd.options.wclose",
FT_BOOLEAN, 24, TFS(&tfs_set_notset),
XTP_CMD_OPTIONS_WCLOSE, NULL, HFILL }
},
{ &hf_xtp_cmd_options_eom,
{ "EOM", "xtp.cmd.options.eom",
FT_BOOLEAN, 24, TFS(&tfs_set_notset),
XTP_CMD_OPTIONS_EOM, NULL, HFILL }
},
{ &hf_xtp_cmd_options_end,
{ "END", "xtp.cmd.options.end",
FT_BOOLEAN, 24, TFS(&tfs_set_notset),
XTP_CMD_OPTIONS_END, NULL, HFILL }
},
{ &hf_xtp_cmd_options_btag,
{ "BTAG", "xtp.cmd.options.btag",
FT_BOOLEAN, 24, TFS(&tfs_set_notset),
XTP_CMD_OPTIONS_BTAG, NULL, HFILL }
},
{ &hf_xtp_cmd_ptype,
{ "Packet type", "xtp.cmd.ptype",
FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_cmd_ptype_ver,
{ "Version", "xtp.cmd.ptype.ver",
FT_UINT8, BASE_DEC, VALS(version_vals), 0x0, NULL, HFILL }
},
{ &hf_xtp_cmd_ptype_pformat,
{ "Format", "xtp.cmd.ptype.pformat",
FT_UINT8, BASE_DEC, VALS(pformat_vals), 0x0, NULL, HFILL }
},
{ &hf_xtp_dlen,
{ "Data length", "xtp.dlen",
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_sort,
{ "Sort", "xtp.sort",
FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_sync,
{ "Synchronizing handshake", "xtp.sync",
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_seq,
{ "Sequence number", "xtp.seq",
FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
/* control segment */
{ &hf_xtp_cntl_rseq,
{ "Received sequence number", "xtp.cntl.rseq",
FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_cntl_alloc,
{ "Allocation", "xtp.cntl.alloc",
FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_cntl_echo,
{ "Synchronizing handshake echo", "xtp.cntl.echo",
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_ecntl_rseq,
{ "Received sequence number", "xtp.ecntl.rseq",
FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_ecntl_alloc,
{ "Allocation", "xtp.ecntl.alloc",
FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_ecntl_echo,
{ "Synchronizing handshake echo", "xtp.ecntl.echo",
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_ecntl_nspan,
{ "Number of spans", "xtp.ecntl.nspan",
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_ecntl_span_left,
{ "Span left edge", "xtp.ecntl.span_le",
FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_ecntl_span_right,
{ "Span right edge", "xtp.ecntl.span_re",
FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_tcntl_rseq,
{ "Received sequence number", "xtp.tcntl.rseq",
FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_tcntl_alloc,
{ "Allocation", "xtp.tcntl.alloc",
FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_tcntl_echo,
{ "Synchronizing handshake echo", "xtp.tcntl.echo",
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_tcntl_rsvd,
{ "Reserved", "xtp.tcntl.rsvd",
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_tcntl_xkey,
{ "Exchange key", "xtp.tcntl.xkey",
FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }
},
/* traffic specifier */
{ &hf_xtp_tspec_tlen,
{ "Length", "xtp.tspec.tlen",
FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_tspec_service,
{ "Service", "xtp.tspec.service",
FT_UINT8, BASE_DEC, VALS(service_vals), 0x0, NULL, HFILL }
},
{ &hf_xtp_tspec_tformat,
{ "Format", "xtp.tspec.format",
FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_tspec_traffic,
{ "Traffic", "xtp.tspec.traffic",
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_tspec_maxdata,
{ "Maxdata", "xtp.tspec.maxdata",
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_tspec_inrate,
{ "Incoming rate", "xtp.tspec.inrate",
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_tspec_inburst,
{ "Incoming burst size", "xtp.tspec.inburst",
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_tspec_outrate,
{ "Outgoing rate", "xtp.tspec.outrate",
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_tspec_outburst,
{ "Outgoing burst size", "xtp.tspec.outburst",
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
/* address segment */
{ &hf_xtp_aseg_alen,
{ "Length", "xtp.aseg.alen",
FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_aseg_adomain,
{ "Domain", "xtp.aseg.adomain",
FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_aseg_aformat,
{ "Format", "xtp.aseg.aformat",
FT_UINT8, BASE_DEC, VALS(aformat_vals), 0x0, NULL, HFILL }
},
{ &hf_xtp_aseg_address,
{ "Traffic", "xtp.aseg.address",
FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_aseg_dsthost,
{ "Destination host", "xtp.aseg.dsthost",
FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_aseg_srchost,
{ "Source host", "xtp.aseg.srchost",
FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_aseg_dstport,
{ "Destination port", "xtp.aseg.dstport",
FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_aseg_srcport,
{ "Source port", "xtp.aseg.srcport",
FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
},
/* others */
{ &hf_xtp_btag,
{ "Beginning tag", "xtp.data.btag",
FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_diag_code,
{ "Diagnostic code", "xtp.diag.code",
FT_UINT32, BASE_DEC, VALS(diag_code_vals), 0x0, NULL, HFILL }
},
{ &hf_xtp_diag_val,
{ "Diagnostic value", "xtp.diag.val",
FT_UINT32, BASE_DEC, VALS(diag_val_vals), 0x0, NULL, HFILL }
},
{ &hf_xtp_diag_msg,
{ "Message", "xtp.diag.msg",
FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_checksum,
{ "Checksum", "xtp.checksum",
FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }
},
{ &hf_xtp_checksum_status,
{ "Checksum Status", "xtp.checksum.status",
FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0, NULL, HFILL }
},
{ &hf_xtp_data,
{ "Data", "xtp.data",
FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
},
};
static gint *ett[] = {
&ett_xtp,
&ett_xtp_cmd,
&ett_xtp_cmd_options,
&ett_xtp_cmd_ptype,
&ett_xtp_cntl,
&ett_xtp_ecntl,
&ett_xtp_tcntl,
&ett_xtp_tspec,
&ett_xtp_jcntl,
&ett_xtp_first,
&ett_xtp_aseg,
&ett_xtp_data,
&ett_xtp_diag,
};
static ei_register_info ei[] = {
{ &ei_xtp_spans_bad,
{ "xtp.spans_bad", PI_MALFORMED, PI_ERROR, "Number of spans incorrect", EXPFILL }},
{ &ei_xtp_checksum,
{ "xtp.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
};
expert_module_t* expert_xtp;
proto_xtp = proto_register_protocol("Xpress Transport Protocol", "XTP", "xtp");
proto_register_field_array(proto_xtp, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
expert_xtp = expert_register_protocol(proto_xtp);
expert_register_field_array(expert_xtp, ei, array_length(ei));
}
void
proto_reg_handoff_xtp(void)
{
dissector_handle_t xtp_handle;
xtp_handle = create_dissector_handle(dissect_xtp, proto_xtp);
dissector_add_uint("ip.proto", IP_PROTO_XTP, xtp_handle);
}
/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 8
* tab-width: 8
* indent-tabs-mode: t
* End:
*
* vi: set shiftwidth=8 tabstop=8 noexpandtab:
* :indentSize=8:tabSize=8:noTabs=false:
*/