diff options
author | Stig Bjørlykke <stig@bjorlykke.org> | 2007-12-16 14:21:37 +0000 |
---|---|---|
committer | Stig Bjørlykke <stig@bjorlykke.org> | 2007-12-16 14:21:37 +0000 |
commit | fa34d4685193d15f856182c73e097702be1453e3 (patch) | |
tree | d74c802d7aa125ab811a5e94734c6a25ebb1f456 /epan | |
parent | 53f5c9aaf5a15b46c6615e8dfc414c6f08464843 (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.common | 3 | ||||
-rw-r--r-- | epan/dissectors/packet-ipars.c | 188 | ||||
-rw-r--r-- | epan/dissectors/packet-lapb.c | 2 | ||||
-rw-r--r-- | epan/dissectors/packet-sita.c | 309 | ||||
-rw-r--r-- | epan/dissectors/packet-uts.c | 338 |
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); +} |