aboutsummaryrefslogtreecommitdiffstats
path: root/epan
diff options
context:
space:
mode:
authorStig Bjørlykke <stig@bjorlykke.org>2007-12-16 14:21:37 +0000
committerStig Bjørlykke <stig@bjorlykke.org>2007-12-16 14:21:37 +0000
commitfa34d4685193d15f856182c73e097702be1453e3 (patch)
treed74c802d7aa125ab811a5e94734c6a25ebb1f456 /epan
parent53f5c9aaf5a15b46c6615e8dfc414c6f08464843 (diff)
From Fulko Hew:
1/ patches to support the libpcap/SITA format 'WTAP_ENCAP_SITA'. 2/ patches to the LAPB dissector to accept MLP (Multi-link protocol) (although MLP dissection has _not_ been added (yet)). 3/ New protocol dissectors for: a) SITA's WAN layer 0 status header, b) An airline protocol ALC, c) An airline (and other industry) protocol UTS. These patches are submitted as a set since the new protocol dissectors are not useful without the libpcap/SITA related changes, and there is no point in having those changes without the additional dissectors. This fixes bug/enhancement 2016. svn path=/trunk/; revision=23885
Diffstat (limited to 'epan')
-rw-r--r--epan/dissectors/Makefile.common3
-rw-r--r--epan/dissectors/packet-ipars.c188
-rw-r--r--epan/dissectors/packet-lapb.c2
-rw-r--r--epan/dissectors/packet-sita.c309
-rw-r--r--epan/dissectors/packet-uts.c338
5 files changed, 839 insertions, 1 deletions
diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common
index 019126d7ba..33b6106f89 100644
--- a/epan/dissectors/Makefile.common
+++ b/epan/dissectors/Makefile.common
@@ -454,6 +454,7 @@ CLEAN_DISSECTOR_SRC = \
packet-image-png.c \
packet-imap.c \
packet-imf.c \
+ packet-ipars.c \
packet-ip.c \
packet-ipdc.c \
packet-ipfc.c \
@@ -664,6 +665,7 @@ CLEAN_DISSECTOR_SRC = \
packet-sip.c \
packet-sigcomp.c \
packet-sipfrag.c \
+ packet-sita.c \
packet-skinny.c \
packet-slimp3.c \
packet-sll.c \
@@ -733,6 +735,7 @@ CLEAN_DISSECTOR_SRC = \
packet-usb.c \
packet-usb-masstorage.c \
packet-umts_fp.c \
+ packet-uts.c \
packet-v120.c \
packet-vines.c \
packet-vj.c \
diff --git a/epan/dissectors/packet-ipars.c b/epan/dissectors/packet-ipars.c
new file mode 100644
index 0000000000..caebbb3f55
--- /dev/null
+++ b/epan/dissectors/packet-ipars.c
@@ -0,0 +1,188 @@
+/* packet-ipars.c
+ * Routines for IPARS/ALC (International Passenger Airline Reservation System/Airline Link Control) WAN protocol dissection
+ * Copyright 2007, Fulko Hew, SITA INC Canada, Inc.
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * 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.
+ */
+
+/* Use tabstops = 4 */
+
+/* NOTE: This should be rewritten to be more in line with how packet-uts.c is
+ * written so that there are filterable fields available for IPARS too.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/emem.h>
+
+static int proto_ipars = -1;
+static guint8 ipars_eomtype = -1;
+static gint ett_ipars = -1;
+
+#define S1 (0x00)
+#define S2 (0x20)
+#define GA (0x03)
+#define EOMpb (0x10)
+#define EOMc (0x11)
+#define EOMu (0x12)
+#define EOMi (0x13)
+
+#define MAX_EOM_MSG_SIZE (16) /* max size of an EOMx indicator string */
+
+static void
+dissect_ipars(tvbuff_t *tvb, packet_info *pinfo _U_ , proto_tree *tree)
+{
+ proto_tree *ipars_tree = NULL;
+ proto_item *ti;
+ int bytes;
+ guint8 ia = 0, ta = 0, cmd = 0, la = 0;
+ tvbuff_t *next_tvb;
+ int offset = 0;
+ gchar *eom_msg;
+
+ eom_msg = ep_alloc(MAX_EOM_MSG_SIZE);
+ eom_msg[0] = 0;
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) /* set the protocol column on summary display */
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPARS");
+
+ if (tvb_length_remaining(tvb, 0) >= 2 ) {
+ ia = tvb_get_guint8(tvb, 0) & 0x3f;
+ ta = tvb_get_guint8(tvb, 1) & 0x3f;
+ if (ia == S1 && ta == S2) { /* if the first two bytes are S1/S2 skip over them */
+ offset = 2;
+ }
+ }
+ if (tvb_length_remaining(tvb, offset) >= 1) ia = tvb_get_guint8(tvb, offset + 0);
+ if (tvb_length_remaining(tvb, offset) >= 2) ta = tvb_get_guint8(tvb, offset + 1);
+
+ if (ia == 0x83 || ia == 0x43 || ia == GA) { /* if its an FPGA or 'corresponsdance code' 'go ahead'... */
+ if (tvb_length_remaining(tvb, offset) > 2) { /* if the msg is long, it must have been a 'poll' */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Poll IA: %2.2X", ta);
+ } else { /* if its short, then it was a 'no traffic' response */
+ if (tvb_length_remaining(tvb, offset) >= 2 ) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "GoAhead NextIA (0x%2.2X)", ta);
+ } else {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, "GoAhead NextIA");
+ }
+ }
+ } else { /* if its not a 'go ahead'... it must be some kind of data message */
+ ia &= 0x3f;
+ ta &= 0x3f;
+ if (ta == 0x20) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Reset IA: %2.2X", ia); /* the TA character was the 'reset' command */
+ }
+ if (tvb_length_remaining(tvb, offset) >= 3) cmd = tvb_get_guint8(tvb, offset + 2) & 0x3f; /* get the first two bytes of the data message */
+ if (tvb_length_remaining(tvb, offset) >= 4) la = tvb_get_guint8(tvb, offset + 3) & 0x3f;
+ if (cmd == 0x1f && la == 0x38) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Please Resend - IA: %2.2X TA: %2.2X", ia, ta); /* light the resend indicator */
+ } else if (cmd == 0x2a && la == 0x05) {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Unsolicited Msg Indicator - IA: %2.2X TA: %2.2X", ia, ta); /* light the unsolicited msg indicator */
+ } else {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Data Msg - IA: %2.2X TA: %2.2X", ia, ta); /* it was a data message (display or printer */
+ }
+ }
+
+ if (tree) {
+ bytes = tvb_length_remaining(tvb, 0);
+ if (bytes > 0) {
+ ia = tvb_get_guint8(tvb, 0) & 0x3f;
+
+ ti = proto_tree_add_protocol_format(tree, proto_ipars, tvb, 0, -1, "Ipars");
+ ipars_tree = proto_item_add_subtree(ti, ett_ipars);
+
+ if (ia == 0x03) {
+ proto_tree_add_protocol_format(ipars_tree, proto_ipars, tvb, 0, 1, "GoAhead Next IA");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_str(pinfo->cinfo, COL_INFO, "GoAhead");
+ return;
+ } else if (ia != S1) {
+ proto_tree_add_protocol_format(ipars_tree, proto_ipars, tvb,
+ 0,
+ bytes, "Unknown format - Data (%d byte%s)", bytes,
+ plurality(bytes, "", "s"));
+ return;
+ }
+ proto_tree_add_protocol_format(ipars_tree, proto_ipars, tvb, 0, 1, "S1");
+ ia = tvb_get_guint8(tvb, 1) & 0x3f;
+ if (ia != S2) {
+ proto_tree_add_protocol_format(ipars_tree, proto_ipars, tvb,
+ 0,
+ bytes, "Unknown format - Data (%d byte%s)", bytes,
+ plurality(bytes, "", "s"));
+ return;
+ }
+ proto_tree_add_protocol_format(ipars_tree, proto_ipars, tvb, 1, 1, "S2");
+ ia = tvb_get_guint8(tvb, 2) & 0x3f;
+ if (ia == GA) {
+ ia = tvb_get_guint8(tvb, 3) & 0x3f;
+ proto_tree_add_protocol_format(ipars_tree, proto_ipars, tvb, 2, 2, "GoAhead IA: %2.2X", ia);
+ ipars_eomtype = tvb_get_guint8(tvb, 4) & 0x3f;
+ switch (ipars_eomtype) {
+ case EOMc: g_snprintf(eom_msg, MAX_EOM_MSG_SIZE, "EOMc"); break;
+ case EOMi: g_snprintf(eom_msg, MAX_EOM_MSG_SIZE, "EOMi"); break;
+ case EOMu: g_snprintf(eom_msg, MAX_EOM_MSG_SIZE, "EOMu"); break;
+ case EOMpb: g_snprintf(eom_msg, MAX_EOM_MSG_SIZE, "EOMpb"); break;
+ default: g_snprintf(eom_msg, MAX_EOM_MSG_SIZE, "Unknown EOM type (0x%2.2X)", ia); break;
+ }
+ proto_tree_add_protocol_format(ipars_tree, proto_ipars, tvb, 4, 1, eom_msg);
+ ia = tvb_get_guint8(tvb, 5) & 0x3f;
+ proto_tree_add_protocol_format(ipars_tree, proto_ipars, tvb, 5, 1, "Good BCC");
+ } else {
+ next_tvb = tvb_new_subset(tvb, 3, -1, -1);
+ proto_tree_add_protocol_format(ipars_tree, proto_ipars, next_tvb,
+ 0,
+ bytes, "Data (%d byte%s)", bytes,
+ plurality(bytes, "", "s"));
+ /* tvb_free(next_tvb); */ /* having this uncommented seems to cause a segfault (Fulko Hew, Nov 6/07) */
+ return;
+
+ }
+ }
+ }
+}
+
+void
+proto_register_ipars(void)
+{
+ static gint *ett[] = {
+ &ett_ipars,
+ };
+
+ proto_ipars = proto_register_protocol("International Passenger Airline Reservation System ", "IPARS", "ipars"); /* name, short name, abbrev */
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("ipars", dissect_ipars, proto_ipars);
+}
diff --git a/epan/dissectors/packet-lapb.c b/epan/dissectors/packet-lapb.c
index 4599aa2095..7747614ec9 100644
--- a/epan/dissectors/packet-lapb.c
+++ b/epan/dissectors/packet-lapb.c
@@ -103,7 +103,7 @@ dissect_lapb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
byte0 = tvb_get_guint8(tvb, 0);
- if (byte0 != 0x01 && byte0 != 0x03) /* invalid LAPB frame */
+ if (byte0 != 0x01 && byte0 != 0x03 && byte0 != 0x07 && byte0 != 0x0f) /* invalid LAPB frame */
{
if (check_col(pinfo->cinfo, COL_INFO))
col_set_str(pinfo->cinfo, COL_INFO, "Invalid LAPB frame");
diff --git a/epan/dissectors/packet-sita.c b/epan/dissectors/packet-sita.c
new file mode 100644
index 0000000000..ffdd3cce07
--- /dev/null
+++ b/epan/dissectors/packet-sita.c
@@ -0,0 +1,309 @@
+/* packet-sita.c
+ * Routines for SITA protocol dissection (ALC, UTS, Frame Relay, X.25)
+ * with a SITA specific link layer information header
+ *
+ * Copyright 2007, Fulko Hew, SITA INC Canada, Inc.
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/* Use tabstops = 4 */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include <epan/packet.h>
+#include <wiretap/wtap.h>
+#include <epan/emem.h>
+
+static dissector_table_t sita_dissector_table;
+static dissector_handle_t data_handle;
+static gint ett_sita = -1;
+static gint ett_sita_flags = -1;
+static gint ett_sita_signals = -1;
+static gint ett_sita_errors1 = -1;
+static gint ett_sita_errors2 = -1;
+static int proto_sita = -1; /* Initialize the protocol and registered fields */
+static int hf_dir = -1;
+static int hf_framing = -1;
+static int hf_parity = -1;
+static int hf_collision = -1;
+static int hf_longframe = -1;
+static int hf_shortframe = -1;
+static int hf_droppedframe = -1;
+static int hf_nonaligned = -1;
+static int hf_abort = -1;
+static int hf_lostcd = -1;
+static int hf_lostcts = -1;
+static int hf_rxdpll = -1;
+static int hf_overrun = -1;
+static int hf_length = -1;
+static int hf_crc = -1;
+static int hf_break = -1;
+static int hf_underrun = -1;
+static int hf_uarterror = -1;
+static int hf_rtxlimit = -1;
+static int hf_proto = -1;
+static int hf_dsr = -1;
+static int hf_dtr = -1;
+static int hf_cts = -1;
+static int hf_rts = -1;
+static int hf_dcd = -1;
+
+#define MAX_FLAGS_LEN 64 /* max size of a 'flags' decoded string */
+#define IOP "Local"
+#define REMOTE "Remote"
+
+gchar *format_flags_string(guchar value, const gchar *array[])
+{
+ int i;
+ guint bpos;
+ size_t fpos = 0, returned_length = 0;
+ gchar *buf;
+
+ buf = ep_alloc(MAX_FLAGS_LEN);
+ buf[0] = 0;
+ for (i = 0; i < 8; i++) {
+ bpos = 1 << i;
+ if (value & bpos) {
+ if (array[i][0]) /* if there is a string to emit... */
+ returned_length = g_snprintf(&buf[fpos], MAX_FLAGS_LEN-fpos, "%s%s", fpos ? ", " : "", array[i]);
+ fpos += MIN(returned_length, MAX_FLAGS_LEN-fpos);
+ }
+ }
+ return buf;
+}
+
+static void
+dissect_sita(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ guchar flags, signals, errors1, errors2, proto;
+ gchar *errors1_string, *errors2_string, *signals_string, *flags_string;
+ proto_tree *sita_tree = NULL;
+ proto_tree *sita_flags_tree = NULL;
+ proto_tree *sita_errors1_tree = NULL;
+ proto_tree *sita_errors2_tree = NULL;
+ proto_tree *sita_signals_tree = NULL;
+ const gchar *rx_errors1_str[] = {"Framing", "Parity", "Collision", "Long-frame", "Short-frame", "", "", "" };
+ const gchar *rx_errors2_str[] = {"Non-Aligned", "Abort", "CD-lost", "DPLL", "Overrun", "Length", "CRC", "Break" };
+ /*const gchar *tx_errors1_str[] = {"", "", "", "", "", "", "", "" }; */
+ const gchar *tx_errors2_str[] = {"Underun", "CTS-lost", "UART", "ReTx-limit", "", "", "", "" };
+ const gchar *signals_str[] = {"DSR", "DTR", "CTS", "RTS", "DCD", "", "", "" };
+ const gchar *flags_str[] = {"", "", "", "", "", "", "", "No-buffers" };
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) col_clear(pinfo->cinfo, COL_PROTOCOL); /* erase the protocol */
+ if (check_col(pinfo->cinfo, COL_INFO)) col_clear(pinfo->cinfo, COL_INFO); /* and info columns so that the next decoder can fill them in */
+
+ flags = pinfo->pseudo_header->sita.flags;
+ signals = pinfo->pseudo_header->sita.signals;
+ errors1 = pinfo->pseudo_header->sita.errors1;
+ errors2 = pinfo->pseudo_header->sita.errors2;
+ proto = pinfo->pseudo_header->sita.proto;
+
+ if (check_col(pinfo->cinfo, COL_DEF_SRC)) {
+ if ((flags & SITA_FRAME_DIR) == SITA_FRAME_DIR_TXED) {
+ col_set_str(pinfo->cinfo, COL_DEF_SRC, IOP); /* set the source (direction) column accordingly */
+ } else {
+ col_set_str(pinfo->cinfo, COL_DEF_SRC, REMOTE);
+ }
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "");
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_sita, tvb, 0, 0, "Link Layer");
+ sita_tree = proto_item_add_subtree(ti, ett_sita);
+
+ proto_tree_add_uint(sita_tree, hf_proto, tvb, 0, 0, proto);
+
+ flags_string = format_flags_string(flags, flags_str);
+ ti = proto_tree_add_text(sita_tree, tvb, 0, 0, "Flags: 0x%02x (From %s)%s%s",
+ flags,
+ ((flags & SITA_FRAME_DIR) == SITA_FRAME_DIR_TXED) ? IOP : REMOTE,
+ strlen(flags_string) ? ", " : "",
+ flags_string);
+ sita_flags_tree = proto_item_add_subtree(ti, ett_sita_flags);
+ proto_tree_add_boolean(sita_flags_tree, hf_droppedframe, tvb, 0, 0, flags);
+ proto_tree_add_boolean(sita_flags_tree, hf_dir, tvb, 0, 0, flags);
+
+ signals_string = format_flags_string(signals, signals_str);
+ ti = proto_tree_add_text(sita_tree, tvb, 0, 0, "Signals: 0x%02x %s", signals, signals_string);
+ sita_signals_tree = proto_item_add_subtree(ti, ett_sita_signals);
+ proto_tree_add_boolean(sita_signals_tree, hf_dcd, tvb, 0, 0, signals);
+ proto_tree_add_boolean(sita_signals_tree, hf_rts, tvb, 0, 0, signals);
+ proto_tree_add_boolean(sita_signals_tree, hf_cts, tvb, 0, 0, signals);
+ proto_tree_add_boolean(sita_signals_tree, hf_dtr, tvb, 0, 0, signals);
+ proto_tree_add_boolean(sita_signals_tree, hf_dsr, tvb, 0, 0, signals);
+
+ if ((flags & SITA_FRAME_DIR) == SITA_FRAME_DIR_RXED) {
+ errors1_string = format_flags_string(errors1, rx_errors1_str);
+ ti = proto_tree_add_text(sita_tree, tvb, 0, 0, "Receive Status: 0x%02x %s", errors1, errors1_string);
+ sita_errors1_tree = proto_item_add_subtree(ti, ett_sita_errors1);
+ proto_tree_add_boolean(sita_errors1_tree, hf_shortframe, tvb, 0, 0, errors1);
+ proto_tree_add_boolean(sita_errors1_tree, hf_longframe, tvb, 0, 0, errors1);
+ proto_tree_add_boolean(sita_errors1_tree, hf_collision, tvb, 0, 0, errors1);
+ proto_tree_add_boolean(sita_errors1_tree, hf_parity, tvb, 0, 0, errors1);
+ proto_tree_add_boolean(sita_errors1_tree, hf_framing, tvb, 0, 0, errors1);
+
+ errors2_string = format_flags_string(errors2, rx_errors2_str);
+ ti = proto_tree_add_text(sita_tree, tvb, 0, 0, "Receive Status: 0x%02x %s", errors2, errors2_string);
+ sita_errors2_tree = proto_item_add_subtree(ti, ett_sita_errors2);
+ proto_tree_add_boolean(sita_errors2_tree, hf_break, tvb, 0, 0, errors2);
+ proto_tree_add_boolean(sita_errors2_tree, hf_crc, tvb, 0, 0, errors2);
+ proto_tree_add_boolean(sita_errors2_tree, hf_length, tvb, 0, 0, errors2);
+ proto_tree_add_boolean(sita_errors2_tree, hf_overrun, tvb, 0, 0, errors2);
+ proto_tree_add_boolean(sita_errors2_tree, hf_rxdpll, tvb, 0, 0, errors2);
+ proto_tree_add_boolean(sita_errors2_tree, hf_lostcd, tvb, 0, 0, errors2);
+ proto_tree_add_boolean(sita_errors2_tree, hf_abort, tvb, 0, 0, errors2);
+ proto_tree_add_boolean(sita_errors2_tree, hf_nonaligned, tvb, 0, 0, errors2);
+ } else {
+ errors2_string = format_flags_string(errors2, tx_errors2_str);
+ ti = proto_tree_add_text(sita_tree, tvb, 0, 0, "Transmit Status: 0x%02x %s", errors2, errors2_string);
+ sita_errors1_tree = proto_item_add_subtree(ti, ett_sita_errors1);
+ proto_tree_add_boolean(sita_errors1_tree, hf_rtxlimit, tvb, 0, 0, errors2);
+ proto_tree_add_boolean(sita_errors1_tree, hf_uarterror, tvb, 0, 0, errors2);
+ proto_tree_add_boolean(sita_errors1_tree, hf_lostcts, tvb, 0, 0, errors2);
+ proto_tree_add_boolean(sita_errors1_tree, hf_underrun, tvb, 0, 0, errors2);
+ }
+ }
+
+ if (!dissector_try_port(sita_dissector_table, pinfo->pseudo_header->sita.proto, tvb, pinfo, tree)) { /* try to find and run an applicable dissector */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) /* if one can't be found... tell them we don't */
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "UKNOWN"); /* know how to decode this protocol */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "IOP protocol number: %u", pinfo->pseudo_header->sita.proto); /* and give them the details then */
+ call_dissector(data_handle, tvb, pinfo, tree); /* call the generic (hex display) decoder instead */
+ }
+}
+
+static const true_false_string tfs_sita_flags = { "From Remote", "From Local" };
+static const true_false_string tfs_sita_error = { "Error", "" };
+static const true_false_string tfs_sita_violation = { "Violation", "" };
+static const true_false_string tfs_sita_received = { "Received", "" };
+static const true_false_string tfs_sita_lost = { "Lost", "" };
+static const true_false_string tfs_sita_exceeded = { "Exceeded", "" };
+static const true_false_string tfs_sita_on_off = { "On", "Off" };
+
+static const value_string tfs_sita_proto[] = {
+ { SITA_PROTO_UNUSED, "Unused" },
+ { SITA_PROTO_BOP_LAPB, "LAPB" },
+ { SITA_PROTO_ETHERNET, "Ethernet" },
+ { SITA_PROTO_ASYNC_INTIO, "Async (Interrupt I/O)" },
+ { SITA_PROTO_ASYNC_BLKIO, "Async (Block I/O)" },
+ { SITA_PROTO_ALC, "IPARS" },
+ { SITA_PROTO_UTS, "UTS" },
+ { SITA_PROTO_PPP_HDLC, "PPP/HDLC" },
+ { SITA_PROTO_SDLC, "SDLC" },
+ { SITA_PROTO_TOKENRING, "Token Ring" },
+ { SITA_PROTO_I2C, "I2C" },
+ { SITA_PROTO_DPM_LINK, "DPM Link" },
+ { SITA_PROTO_BOP_FRL, "Frame Relay" },
+ { 0, NULL }
+};
+
+void
+proto_register_sita(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_proto, { "Protocol", "sita.errors.protocol", FT_UINT8, BASE_HEX, VALS(&tfs_sita_proto), 0, "Protocol value", HFILL }},
+
+ { &hf_dir, { "Direction", "sita.flags.flags", FT_BOOLEAN, 8, TFS(&tfs_sita_flags), SITA_FRAME_DIR, "TRUE 'from Remote', FALSE 'from Local'", HFILL }},
+ { &hf_droppedframe, { "No Buffers", "sita.flags.droppedframe", FT_BOOLEAN, 8, TFS(&tfs_sita_error), SITA_ERROR_NO_BUFFER, "TRUE if Buffer Failure", HFILL }},
+
+ { &hf_framing, { "Framing", "sita.errors.framing", FT_BOOLEAN, 8, TFS(&tfs_sita_error), SITA_ERROR_RX_FRAMING, "TRUE if Framing Error", HFILL }},
+ { &hf_parity, { "Parity", "sita.errors.parity", FT_BOOLEAN, 8, TFS(&tfs_sita_error), SITA_ERROR_RX_PARITY, "TRUE if Parity Error", HFILL }},
+ { &hf_collision, { "Collision", "sita.errors.collision", FT_BOOLEAN, 8, TFS(&tfs_sita_error), SITA_ERROR_RX_COLLISION, "TRUE if Collision", HFILL }},
+ { &hf_longframe, { "Long Frame", "sita.errors.longfame", FT_BOOLEAN, 8, TFS(&tfs_sita_error), SITA_ERROR_RX_FRAME_LONG, "TRUE if Long Frame Received", HFILL }},
+ { &hf_shortframe, { "Short Frame", "sita.errors.shortframe", FT_BOOLEAN, 8, TFS(&tfs_sita_error), SITA_ERROR_RX_FRAME_SHORT, "TRUE if Short Frame", HFILL }},
+ { &hf_nonaligned, { "NonAligned", "sita.errors.nonaligned", FT_BOOLEAN, 8, TFS(&tfs_sita_error), SITA_ERROR_RX_NONOCTET_ALIGNED, "TRUE if NonAligned Frame", HFILL }},
+ { &hf_abort, { "Abort", "sita.errors.abort", FT_BOOLEAN, 8, TFS(&tfs_sita_received), SITA_ERROR_RX_ABORT, "TRUE if Abort Received", HFILL }},
+ { &hf_lostcd, { "Carrier", "sita.errors.lostcd", FT_BOOLEAN, 8, TFS(&tfs_sita_lost), SITA_ERROR_RX_CD_LOST, "TRUE if Carrier Lost", HFILL }},
+ { &hf_rxdpll, { "DPLL", "sita.errors.rxdpll", FT_BOOLEAN, 8, TFS(&tfs_sita_error), SITA_ERROR_RX_DPLL, "TRUE if DPLL Error", HFILL }},
+ { &hf_overrun, { "Overrun", "sita.errors.overrun", FT_BOOLEAN, 8, TFS(&tfs_sita_error), SITA_ERROR_RX_OVERRUN, "TRUE if Overrun Error", HFILL }},
+ { &hf_length, { "Length", "sita.errors.length", FT_BOOLEAN, 8, TFS(&tfs_sita_violation),SITA_ERROR_RX_FRAME_LEN_VIOL, "TRUE if Length Violation", HFILL }},
+ { &hf_crc, { "CRC", "sita.errors.crc", FT_BOOLEAN, 8, TFS(&tfs_sita_error), SITA_ERROR_RX_CRC, "TRUE if CRC Error", HFILL }},
+ { &hf_break, { "Break", "sita.errors.break", FT_BOOLEAN, 8, TFS(&tfs_sita_received), SITA_ERROR_RX_BREAK, "TRUE if Break Received", HFILL }},
+
+ { &hf_underrun, { "Underrun", "sita.errors.underrun", FT_BOOLEAN, 8, TFS(&tfs_sita_error), SITA_ERROR_TX_UNDERRUN, "TRUE if Tx Underrun", HFILL }},
+ { &hf_lostcts, { "Clear To Send", "sita.errors.lostcts", FT_BOOLEAN, 8, TFS(&tfs_sita_lost), SITA_ERROR_TX_CTS_LOST, "TRUE if Clear To Send Lost", HFILL }},
+ { &hf_uarterror, { "UART", "sita.errors.uarterror", FT_BOOLEAN, 8, TFS(&tfs_sita_error), SITA_ERROR_TX_UART_ERROR, "TRUE if UART Error", HFILL }},
+ { &hf_rtxlimit, { "Retx Limit", "sita.errors.rtxlimit", FT_BOOLEAN, 8, TFS(&tfs_sita_exceeded), SITA_ERROR_TX_RETX_LIMIT, "TRUE if Retransmit Limit reached", HFILL }},
+
+ { &hf_dsr, { "DSR", "sita.signals.dsr", FT_BOOLEAN, 8, TFS(&tfs_sita_on_off), SITA_SIG_DSR, "TRUE if Data Set Ready", HFILL }},
+ { &hf_dtr, { "DTR", "sita.signals.dtr", FT_BOOLEAN, 8, TFS(&tfs_sita_on_off), SITA_SIG_DTR, "TRUE if Data Terminal Ready", HFILL }},
+ { &hf_cts, { "CTS", "sita.signals.cts", FT_BOOLEAN, 8, TFS(&tfs_sita_on_off), SITA_SIG_CTS, "TRUE if Clear To Send", HFILL }},
+ { &hf_rts, { "RTS", "sita.signals.rts", FT_BOOLEAN, 8, TFS(&tfs_sita_on_off), SITA_SIG_RTS, "TRUE if Request To Send", HFILL }},
+ { &hf_dcd, { "DCD", "sita.signals.dcd", FT_BOOLEAN, 8, TFS(&tfs_sita_on_off), SITA_SIG_DCD, "TRUE if Data Carrier Detect", HFILL }},
+
+ };
+
+ static gint *ett[] = {
+ &ett_sita,
+ &ett_sita_flags,
+ &ett_sita_signals,
+ &ett_sita_errors1,
+ &ett_sita_errors2,
+ };
+
+ proto_sita = proto_register_protocol("Société Internationale de Télécommunications Aéronautiques", "SITA", "sita"); /* name, short name,abbreviation */
+ sita_dissector_table = register_dissector_table("sita.proto", "SITA protocol number", FT_UINT8, BASE_HEX);
+ proto_register_field_array(proto_sita, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_dissector("sita", dissect_sita, proto_sita);
+}
+
+void
+proto_reg_handoff_sita(void)
+{
+ static gboolean inited = FALSE;
+ static dissector_handle_t lapb_handle;
+ static dissector_handle_t frame_relay_handle;
+ static dissector_handle_t uts_handle;
+ static dissector_handle_t ipars_handle;
+
+ if (!inited) {
+ dissector_handle_t sita_handle;
+
+ lapb_handle = find_dissector("lapb");
+ frame_relay_handle = find_dissector("fr");
+ uts_handle = find_dissector("uts");
+ ipars_handle = find_dissector("ipars");
+ data_handle = find_dissector("data");
+
+ sita_handle = create_dissector_handle(dissect_sita, proto_sita);
+ dissector_add("wtap_encap", WTAP_ENCAP_SITA, sita_handle);
+
+ dissector_add("sita.proto", SITA_PROTO_ALC, ipars_handle);
+ dissector_add("sita.proto", SITA_PROTO_UTS, uts_handle);
+ dissector_add("sita.proto", SITA_PROTO_BOP_LAPB, lapb_handle);
+ dissector_add("sita.proto", SITA_PROTO_BOP_FRL, frame_relay_handle);
+
+ inited = TRUE;
+ }
+}
+
diff --git a/epan/dissectors/packet-uts.c b/epan/dissectors/packet-uts.c
new file mode 100644
index 0000000000..23b89d7e0c
--- /dev/null
+++ b/epan/dissectors/packet-uts.c
@@ -0,0 +1,338 @@
+/* packet-uts.c
+ * Routines for UTS WAN protocol dissection
+ * Copyright 2007, Fulko Hew, SITA INC Canada, Inc.
+ *
+ * $Id$
+ *
+ * Copied from packet-ipars.c
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * 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.
+ */
+
+/* Use tabstops = 4 */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <string.h>
+#include <epan/packet.h>
+#include <epan/emem.h>
+
+#define SOH (0x01)
+#define STX (0x02)
+#define ETX (0x03)
+#define EOT (0x04)
+#define ENQ (0x05)
+#define BEL (0x07)
+#define NAK (0x15)
+#define DLE (0x10)
+
+#define GRID (0x20)
+#define GSID (0x50)
+#define GDID (0x70)
+
+#define MAX_POLL_TYPE_MSG_SIZE (50)
+
+static int proto_uts = -1;
+static gint ett_uts = -1;
+static gint ett_header_uts = -1;
+static gint ett_trailer_uts = -1;
+static int hf_rid = -1;
+static int hf_sid = -1;
+static int hf_did = -1;
+static int hf_retxrequest = -1;
+static int hf_ack = -1;
+static int hf_replyrequest = -1;
+static int hf_busy = -1;
+static int hf_notbusy = -1;
+static int hf_msgwaiting = -1;
+static int hf_function = -1;
+static int hf_data = -1;
+
+#define MATCH (1)
+#define FETCH (2)
+
+#define SRC (1)
+#define DST (2)
+
+static int testchar(tvbuff_t *tvb, packet_info *pinfo _U_, int offset, int op, gchar match, gchar *storage)
+{
+ gchar temp;
+
+ if (tvb_length_remaining(tvb, offset)) {
+ temp = tvb_get_guint8(tvb, offset) & 0x7f;
+ if (op == FETCH || (op == MATCH && temp == match)) {
+ if (storage != NULL) *storage = temp;
+ return 1;
+ } else {
+ return 0;
+ }
+ } else {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown Message Format");
+ return 0;
+ }
+}
+
+static void
+set_addr(packet_info *pinfo _U_ , int field, gchar rid, gchar sid, gchar did)
+{
+ if (field == SRC) {
+ if (check_col(pinfo->cinfo, COL_DEF_SRC)) col_append_fstr(pinfo->cinfo, COL_DEF_SRC, " %2.2X:%2.2X:%2.2X", rid, sid, did);
+ } else {
+ if (check_col(pinfo->cinfo, COL_DEF_DST)) col_append_fstr(pinfo->cinfo, COL_DEF_DST, " %2.2X:%2.2X:%2.2X", rid, sid, did);
+ }
+}
+
+static void
+dissect_uts(tvbuff_t *tvb, packet_info *pinfo _U_ , proto_tree *tree)
+{
+ proto_tree *uts_tree = NULL;
+ proto_tree *uts_header_tree = NULL;
+ proto_tree *uts_trailer_tree = NULL;
+ proto_item *ti;
+ int length;
+ gchar rid, sid, did;
+ gchar *msg_msg;
+ int offset = 0;
+ int header_length = -1;
+ int ack_start = 0;
+ int busy_start = 0;
+ int notbusy_start = 0;
+ int replyrequest_start = 0;
+ int function_start = 0;
+ int msgwaiting_start = 0;
+ int nak_start = 0;
+ int etx_start = 0;
+ int bcc_start = 0;
+ int stx_start = 0;
+ gchar function_code;
+ guint8 *data_ptr;
+
+ enum { NOTRAFFIC, OTHER } msg_type = OTHER;
+
+ msg_msg = ep_alloc(MAX_POLL_TYPE_MSG_SIZE);
+ msg_msg[0] = 0;
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) /* set the protocol column on summary display */
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "UTS");
+
+ if (testchar(tvb, pinfo, 0, MATCH, EOT, NULL) &&
+ testchar(tvb, pinfo, 1, MATCH, EOT, NULL) &&
+ testchar(tvb, pinfo, 2, MATCH, ETX, NULL)) {
+ msg_type = NOTRAFFIC;
+ g_snprintf(msg_msg, MAX_POLL_TYPE_MSG_SIZE, "No Traffic");
+ } else {
+ if (testchar(tvb, pinfo, 0, MATCH, SOH, NULL) &&
+ testchar(tvb, pinfo, 1, FETCH, 0, (gchar *)&rid) &&
+ testchar(tvb, pinfo, 2, FETCH, 0, (gchar *)&sid) &&
+ testchar(tvb, pinfo, 3, FETCH, 0, (gchar *)&did)) {
+ offset = 4;
+ if (testchar(tvb, pinfo, offset, MATCH, ETX, NULL)) {
+ g_snprintf(msg_msg, MAX_POLL_TYPE_MSG_SIZE, "General Poll");
+ set_addr(pinfo, DST, rid, sid, did);
+ } else if (testchar(tvb, pinfo, offset, MATCH, DLE, NULL) &&
+ testchar(tvb, pinfo, offset+1, MATCH, '1', NULL) &&
+ testchar(tvb, pinfo, offset+2, MATCH, ETX, NULL)) {
+ ack_start = offset;
+ if (sid == GSID && did == GDID) {
+ g_snprintf(msg_msg, MAX_POLL_TYPE_MSG_SIZE, "General Poll + ACK");
+ set_addr(pinfo, DST, rid, sid, did);
+ } else if (sid != GSID && did == GDID) {
+ g_snprintf(msg_msg, MAX_POLL_TYPE_MSG_SIZE, "Specific Poll + ACK");
+ set_addr(pinfo, DST, rid, sid, did);
+ } else if (sid != GSID && did != GDID) {
+ g_snprintf(msg_msg, MAX_POLL_TYPE_MSG_SIZE, "No Traffic + ACK");
+ set_addr(pinfo, SRC, rid, sid, did);
+ } else {
+ g_snprintf(msg_msg, MAX_POLL_TYPE_MSG_SIZE, "Unknown Message Format");
+ if ((pinfo->pseudo_header->sita.flags & SITA_FRAME_DIR) == SITA_FRAME_DIR_TXED) {
+ set_addr(pinfo, DST, rid, sid, did); /* if the ACN sent it, the address is of the destination... the terminal */
+ } else {
+ set_addr(pinfo, SRC, rid, sid, did); /* if the ACN received it, the address if of the source... the terminal */
+ }
+ }
+ } else if (testchar(tvb, pinfo, offset, MATCH, DLE, NULL) &&
+ testchar(tvb, pinfo, offset+1, MATCH, NAK, NULL) &&
+ testchar(tvb, pinfo, offset+2, MATCH, ETX, NULL) &&
+ sid != GSID && did == GDID) {
+ nak_start = offset;
+ g_snprintf(msg_msg, MAX_POLL_TYPE_MSG_SIZE, "Retransmit Request");
+ set_addr(pinfo, DST, rid, sid, did);
+ } else if (testchar(tvb, pinfo, offset, MATCH, BEL, NULL) &&
+ testchar(tvb, pinfo, offset+1, MATCH, STX, NULL) &&
+ testchar(tvb, pinfo, offset+2, MATCH, ETX, NULL)) {
+ header_length = offset+2;
+ msgwaiting_start = offset;
+ g_snprintf(msg_msg, MAX_POLL_TYPE_MSG_SIZE, "Message Waiting");
+ set_addr(pinfo, DST, rid, sid, did);
+ } else if (testchar(tvb, pinfo, offset, MATCH, DLE, NULL) &&
+ testchar(tvb, pinfo, offset+1, MATCH, '1', NULL) &&
+ testchar(tvb, pinfo, offset+2, MATCH, STX, NULL)) {
+ ack_start = offset;
+ header_length = offset+3;
+ stx_start = offset+2;
+ g_snprintf(msg_msg, MAX_POLL_TYPE_MSG_SIZE, "Text + ACK");
+ set_addr(pinfo, SRC, rid, sid, did);
+ } else if (testchar(tvb, pinfo, offset, MATCH, STX, NULL)) {
+ header_length = offset+1;
+ stx_start = offset;
+ g_snprintf(msg_msg, MAX_POLL_TYPE_MSG_SIZE, "Text");
+ if ((pinfo->pseudo_header->sita.flags & SITA_FRAME_DIR) == SITA_FRAME_DIR_TXED) {
+ set_addr(pinfo, DST, rid, sid, did); /* if the ACN sent it, the address is of the destination... the terminal */
+ } else {
+ set_addr(pinfo, SRC, rid, sid, did); /* if the ACN received it, the address if of the source... the terminal */
+ }
+ } else if (testchar(tvb, pinfo, offset, MATCH, DLE, NULL) &&
+ testchar(tvb, pinfo, offset+1, MATCH, ENQ, NULL) &&
+ testchar(tvb, pinfo, offset+2, MATCH, ETX, NULL)) {
+ replyrequest_start = offset;
+ g_snprintf(msg_msg, MAX_POLL_TYPE_MSG_SIZE, "Reply Request");
+ set_addr(pinfo, SRC, rid, sid, did);
+ } else if (testchar(tvb, pinfo, offset, MATCH, DLE, NULL) &&
+ testchar(tvb, pinfo, offset+1, MATCH, '?', NULL) &&
+ testchar(tvb, pinfo, offset+2, MATCH, ETX, NULL)) {
+ busy_start = offset;
+ g_snprintf(msg_msg, MAX_POLL_TYPE_MSG_SIZE, "Busy");
+ set_addr(pinfo, SRC, rid, sid, did);
+ } else if (testchar(tvb, pinfo, offset, MATCH, DLE, NULL) &&
+ testchar(tvb, pinfo, offset+1, MATCH, ';', NULL) &&
+ testchar(tvb, pinfo, offset+2, MATCH, ETX, NULL)) {
+ notbusy_start = offset;
+ g_snprintf(msg_msg, MAX_POLL_TYPE_MSG_SIZE, "Not Busy");
+ set_addr(pinfo, SRC, rid, sid, did);
+ } else if (testchar(tvb, pinfo, offset, MATCH, DLE, NULL) &&
+ testchar(tvb, pinfo, offset+1, MATCH, '1', NULL) &&
+ testchar(tvb, pinfo, offset+2, MATCH, DLE, NULL) &&
+ testchar(tvb, pinfo, offset+3, MATCH, ';', NULL) &&
+ testchar(tvb, pinfo, offset+4, MATCH, ETX, NULL)) {
+ notbusy_start = offset+2;
+ ack_start = offset;
+ g_snprintf(msg_msg, MAX_POLL_TYPE_MSG_SIZE, "Not Busy + ACK");
+ set_addr(pinfo, SRC, rid, sid, did);
+ } else if (testchar(tvb, pinfo, offset, MATCH, DLE, NULL) &&
+ testchar(tvb, pinfo, offset+1, MATCH, '1', NULL) &&
+ testchar(tvb, pinfo, offset+2, FETCH, 0, &function_code) &&
+ testchar(tvb, pinfo, offset+3, MATCH, ETX, NULL)) {
+ ack_start = offset;
+ function_start = offset + 2;
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Function Message '%c' + ACK", function_code);
+ set_addr(pinfo, SRC, rid, sid, did);
+ } else if (testchar(tvb, pinfo, offset, FETCH, 0, &function_code) &&
+ testchar(tvb, pinfo, offset+1, MATCH, ETX, NULL)) {
+ function_start = offset;
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Function Message '%c'", function_code);
+ set_addr(pinfo, SRC, rid, sid, did);
+ }
+ }
+ }
+ if ((check_col(pinfo->cinfo, COL_INFO)) && strlen(msg_msg))
+ col_add_str(pinfo->cinfo, COL_INFO, msg_msg);
+
+ while (tvb_length_remaining(tvb, offset)) { /* now look for the ETX */
+ if ((tvb_get_guint8(tvb, offset) & 0x7f) == ETX) {
+ if (header_length == -1) header_length = offset; /* the header ends at an STX, or if not found, the ETX */
+ etx_start = offset;
+ offset++;
+ break;
+ }
+ offset++;
+ }
+ if (tvb_length_remaining(tvb, offset)) /* if there is anything left, it could be the BCC and pads */
+ bcc_start = offset;
+
+ if (tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_uts, tvb, 0, -1, "UTS");
+ uts_tree = proto_item_add_subtree(ti, ett_uts);
+
+ if (msg_type == NOTRAFFIC) {
+ proto_tree_add_protocol_format(uts_tree, proto_uts, tvb, 0, 2, "No Traffic");
+ proto_tree_add_protocol_format(uts_tree, proto_uts, tvb, 2, -1, "ETX + padding");
+ } else {
+ ti = proto_tree_add_text(uts_tree, tvb, 0, header_length, "Header");
+ uts_header_tree = proto_item_add_subtree(ti, ett_header_uts);
+
+ proto_tree_add_protocol_format(uts_header_tree, proto_uts, tvb, 0, 1, "SOH");
+
+ if (rid == GRID) proto_tree_add_uint_format(uts_header_tree, hf_rid, tvb, 1, 1, rid, "RID (%02X) (General)", rid );
+ else proto_tree_add_uint_format(uts_header_tree, hf_rid, tvb, 1, 1, rid, "RID (%02X)", rid );
+ if (sid == GSID) proto_tree_add_uint_format(uts_header_tree, hf_sid, tvb, 2, 1, sid, "SID (%02X) (General)", sid );
+ else proto_tree_add_uint_format(uts_header_tree, hf_sid, tvb, 2, 1, sid, "SID (%02X)", sid );
+ if (sid == GDID) proto_tree_add_uint_format(uts_header_tree, hf_did, tvb, 3, 1, did, "DID (%02X) (General)", did );
+ else proto_tree_add_uint_format(uts_header_tree, hf_did, tvb, 3, 1, did, "DID (%02X)", did );
+
+ if (nak_start) proto_tree_add_boolean_format(uts_header_tree, hf_retxrequest, tvb, nak_start, 2, 1, "Re-transmit Request");
+ if (ack_start) proto_tree_add_boolean_format(uts_header_tree, hf_ack, tvb, ack_start, 2, 1, "Ack");
+ if (replyrequest_start) proto_tree_add_boolean_format(uts_header_tree, hf_replyrequest, tvb, replyrequest_start, 2, 1, "Reply Request");
+ if (busy_start) proto_tree_add_boolean_format(uts_header_tree, hf_busy, tvb, busy_start, 2, 1, "Busy");
+ if (notbusy_start) proto_tree_add_boolean_format(uts_header_tree, hf_notbusy, tvb, notbusy_start, 2, 1, "Not Busy");
+ if (msgwaiting_start) proto_tree_add_boolean_format(uts_header_tree, hf_msgwaiting, tvb, msgwaiting_start, 1, 1, "Message Waiting");
+ if (function_start)
+ proto_tree_add_uint_format(uts_header_tree, hf_function, tvb, function_start, 1, function_code, "Function '%c'", function_code );
+
+ if (stx_start) {
+ proto_tree_add_protocol_format(uts_header_tree, proto_uts, tvb, stx_start, 1, "Start of Text" );
+ length = tvb_length_remaining(tvb, stx_start+1); /* find out how much message remains */
+ if (etx_start) length = (etx_start - stx_start - 1); /* and the data part is the rest... whatever preceeds the ETX if it exists */
+ data_ptr = tvb_get_ephemeral_string(tvb, stx_start+1, length); /* copy the string for dissecting */
+ proto_tree_add_string_format(uts_tree, hf_data, tvb, stx_start + 1, length, data_ptr, "Text (%d byte%s)", length, plurality(length, "", "s"));
+ }
+ if (etx_start) {
+ ti = proto_tree_add_text(uts_tree, tvb, etx_start, -1, "Trailer");
+ uts_trailer_tree = proto_item_add_subtree(ti, ett_trailer_uts);
+
+ if (etx_start) proto_tree_add_protocol_format(uts_trailer_tree, proto_uts, tvb, etx_start, 1, "ETX" );
+ if (bcc_start) proto_tree_add_protocol_format(uts_trailer_tree, proto_uts, tvb, bcc_start, -1, "CCC + padding" );
+ }
+ }
+ }
+}
+
+void
+proto_register_uts(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_rid, { "RID", "uts.rid", FT_UINT8, BASE_HEX, NULL, 0, "Remote Identifier address", HFILL }},
+ { &hf_sid, { "SID", "uts.sid", FT_UINT8, BASE_HEX, NULL, 0, "Site Identifier address", HFILL }},
+ { &hf_did, { "DID", "uts.did", FT_UINT8, BASE_HEX, NULL, 0, "Device Identifier address", HFILL }},
+ { &hf_retxrequest, { "ReTxRequst", "uts.retxrequst", FT_BOOLEAN, BASE_NONE, NULL, 0, "TRUE if Re-transmit Request", HFILL }},
+ { &hf_ack, { "Ack", "uts.ack", FT_BOOLEAN, BASE_NONE, NULL, 0, "TRUE if Ack", HFILL }},
+ { &hf_replyrequest, { "ReplyRequst", "uts.replyrequest", FT_BOOLEAN, BASE_NONE, NULL, 0, "TRUE if Reply Request", HFILL }},
+ { &hf_busy, { "Busy", "uts.busy", FT_BOOLEAN, BASE_NONE, NULL, 0, "TRUE if Busy", HFILL }},
+ { &hf_notbusy, { "NotBusy", "uts.notbusy", FT_BOOLEAN, BASE_NONE, NULL, 0, "TRUE if Not Busy", HFILL }},
+ { &hf_msgwaiting, { "MsgWaiting", "uts.msgwaiting", FT_BOOLEAN, BASE_NONE, NULL, 0, "TRUE if Message Waiting", HFILL }},
+ { &hf_function, { "Function", "uts.function", FT_UINT8, BASE_HEX, NULL, 0, "Function Code value", HFILL }},
+ { &hf_data, { "Data", "uts.data", FT_STRING, BASE_NONE, NULL, 0, "User Data Message", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_uts,
+ &ett_header_uts,
+ &ett_trailer_uts,
+ };
+
+ proto_uts = proto_register_protocol("Unisys Transmittal System", "UTS", "uts"); /* name, short name, abbrev */
+ proto_register_field_array(proto_uts, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ register_dissector("uts", dissect_uts, proto_uts);
+}