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 | |
parent | 53f5c9aaf5a15b46c6615e8dfc414c6f08464843 (diff) | |
download | wireshark-fa34d4685193d15f856182c73e097702be1453e3.tar.gz wireshark-fa34d4685193d15f856182c73e097702be1453e3.tar.bz2 wireshark-fa34d4685193d15f856182c73e097702be1453e3.zip |
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
-rw-r--r-- | AUTHORS | 7 | ||||
-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 | ||||
-rw-r--r-- | wiretap/libpcap.c | 103 | ||||
-rw-r--r-- | wiretap/wtap.c | 3 | ||||
-rw-r--r-- | wiretap/wtap.h | 66 |
9 files changed, 1018 insertions, 1 deletions
@@ -2682,6 +2682,13 @@ Sake Blok <sake [AT] euronet.nl> { temporary coloring rules with hotkeys } +Fulko Hew <fulko.hew [AT] gmail.com> { + SITA protocol dissection (ALC, UTS, Frame Relay, X.25) + UTS WAN protocol dissection + IPARS/ALC (International Passenger Airline Reservation System/Airline + Link Control) WAN protocol dissection +} + and by: Pavel Roskin <proski [AT] gnu.org> 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); +} diff --git a/wiretap/libpcap.c b/wiretap/libpcap.c index e8bd95ade1..268d25d370 100644 --- a/wiretap/libpcap.c +++ b/wiretap/libpcap.c @@ -76,6 +76,16 @@ #define MTP2_HDR_LEN 4 /* length of the header */ /* + * A header containing additional SITA WAN information. + */ +#define SITA_FLAGS_OFFSET 0 /* 1 byte */ +#define SITA_SIGNALS_OFFSET 1 /* 1 byte */ +#define SITA_ERRORS1_OFFSET 2 /* 1 byte */ +#define SITA_ERRORS2_OFFSET 3 /* 1 byte */ +#define SITA_PROTO_OFFSET 4 /* 1 byte */ +#define SITA_HDR_LEN 5 /* length of the header */ + +/* * The fake link-layer header of LAPD packets. */ #ifndef ETH_P_LAPD @@ -127,6 +137,10 @@ static gboolean libpcap_get_mtp2_pseudoheader(const guint8 *mtp2_hdr, union wtap_pseudo_header *pseudo_header); static gboolean libpcap_read_mtp2_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info); +static gboolean libpcap_get_sita_pseudoheader(const guint8 *sita_phdr, + union wtap_pseudo_header *pseudo_header); +static gboolean libpcap_read_sita_pseudoheader(FILE_T fh, + union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info); static gboolean libpcap_get_lapd_pseudoheader(const guint8 *lapd_phdr, union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info); static gboolean libpcap_read_lapd_pseudoheader(FILE_T fh, @@ -429,6 +443,8 @@ static const struct { { 189, WTAP_ENCAP_USB_LINUX }, /* Per-Packet Information header */ { 192, WTAP_ENCAP_PPI }, + /* SITA File Encapsulation */ + { 196, WTAP_ENCAP_SITA }, /* Endace Record File Encapsulation */ { 197, WTAP_ENCAP_ERF }, /* Bluetooth HCI UART transport (part H:4) frames, like hcidump */ @@ -1371,6 +1387,29 @@ static gboolean libpcap_read(wtap *wth, int *err, gchar **err_info, wth->data_offset += LAPD_SLL_LEN; break; + case WTAP_ENCAP_SITA: + if (packet_size < SITA_HDR_LEN) { + /* + * Uh-oh, the packet isn't big enough to even + * have a pseudo-header. + */ + *err = WTAP_ERR_BAD_RECORD; + *err_info = g_strdup_printf("libpcap: SITA file has a %u-byte packet, too small to have even a SITA pseudo-header\n", + packet_size); + return FALSE; + } + if (!libpcap_read_sita_pseudoheader(wth->fh, &wth->pseudo_header, + err, err_info)) + return FALSE; /* Read error */ + + /* + * Don't count the pseudo-header as part of the packet. + */ + orig_size -= SITA_HDR_LEN; + packet_size -= SITA_HDR_LEN; + wth->data_offset += SITA_HDR_LEN; + break; + case WTAP_ENCAP_USB_LINUX: if (packet_size < sizeof (struct linux_usb_phdr)) { /* @@ -1576,6 +1615,14 @@ libpcap_seek_read(wtap *wth, gint64 seek_off, } break; + case WTAP_ENCAP_SITA: + if (!libpcap_read_sita_pseudoheader(wth->random_fh, pseudo_header, + err, err_info)) { + /* Read error */ + return FALSE; + } + break; + case WTAP_ENCAP_USB_LINUX: if (!libpcap_read_linux_usb_pseudoheader(wth, wth->random_fh, pseudo_header, err)) @@ -1986,6 +2033,36 @@ libpcap_read_lapd_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_heade err_info); } +static gboolean +libpcap_get_sita_pseudoheader(const guint8 *sita_phdr, + union wtap_pseudo_header *pseudo_header) +{ + pseudo_header->sita.flags = sita_phdr[SITA_FLAGS_OFFSET]; + pseudo_header->sita.signals = sita_phdr[SITA_SIGNALS_OFFSET]; + pseudo_header->sita.errors1 = sita_phdr[SITA_ERRORS1_OFFSET]; + pseudo_header->sita.errors2 = sita_phdr[SITA_ERRORS2_OFFSET]; + pseudo_header->sita.proto = sita_phdr[SITA_PROTO_OFFSET]; + return TRUE; +} + +static gboolean +libpcap_read_sita_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info _U_) +{ + guint8 sita_phdr[SITA_HDR_LEN]; + int bytes_read; + + errno = WTAP_ERR_CANT_READ; + bytes_read = file_read(sita_phdr, 1, SITA_HDR_LEN, fh); + if (bytes_read != SITA_HDR_LEN) { + *err = file_error(fh); + if (*err == 0) + *err = WTAP_ERR_SHORT_READ; + return FALSE; + } + + return libpcap_get_sita_pseudoheader(sita_phdr, pseudo_header); +} + static void libpcap_swap_linux_usb_pseudoheader(struct linux_usb_phdr *phdr) { @@ -2364,6 +2441,7 @@ static gboolean libpcap_dump(wtap_dumper *wdh, guint8 irda_hdr[IRDA_SLL_LEN]; guint8 lapd_hdr[LAPD_SLL_LEN]; guint8 mtp2_hdr[MTP2_HDR_LEN]; + guint8 sita_hdr[SITA_HDR_LEN]; guint8 erf_hdr[ sizeof(struct erf_mc_phdr)]; int hdrsize, size; @@ -2385,6 +2463,10 @@ static gboolean libpcap_dump(wtap_dumper *wdh, hdrsize = LAPD_SLL_LEN; break; + case WTAP_ENCAP_SITA: + hdrsize = SITA_HDR_LEN; + break; + case WTAP_ENCAP_USB_LINUX: hdrsize = sizeof (struct linux_usb_phdr); break; @@ -2602,6 +2684,27 @@ static gboolean libpcap_dump(wtap_dumper *wdh, wdh->bytes_dumped += sizeof(lapd_hdr); break; + case WTAP_ENCAP_SITA: + /* + * Write the SITA header. + */ + memset(&sita_hdr, 0, sizeof(sita_hdr)); + sita_hdr[SITA_FLAGS_OFFSET] = pseudo_header->sita.flags; + sita_hdr[SITA_SIGNALS_OFFSET] = pseudo_header->sita.signals; + sita_hdr[SITA_ERRORS1_OFFSET] = pseudo_header->sita.errors1; + sita_hdr[SITA_ERRORS2_OFFSET] = pseudo_header->sita.errors2; + sita_hdr[SITA_PROTO_OFFSET] = pseudo_header->sita.proto; + nwritten = fwrite(&sita_hdr, 1, sizeof(sita_hdr), wdh->fh); + if (nwritten != sizeof(sita_hdr)) { + if (nwritten == 0 && ferror(wdh->fh)) + *err = errno; + else + *err = WTAP_ERR_SHORT_WRITE; + return FALSE; + } + wdh->bytes_dumped += sizeof(sita_hdr); + break; + case WTAP_ENCAP_USB_LINUX: /* * Write out the pseudo-header; it has the same format diff --git a/wiretap/wtap.c b/wiretap/wtap.c index 759fbed3da..2ddb55bbfc 100644 --- a/wiretap/wtap.c +++ b/wiretap/wtap.c @@ -389,6 +389,9 @@ static struct encap_type_info encap_table_base[] = { /* WTAP_ENCAP_BT_H4 */ { "Bluetooth H4 with linux header", "bluetooth-h4" }, + + /* WTAP_ENCAP_SITA */ + { "SITA WAN packets", "sita-wan" }, }; gint wtap_num_encap_types = sizeof(encap_table_base) / sizeof(struct encap_type_info); diff --git a/wiretap/wtap.h b/wiretap/wtap.h index 030aa08456..2c0df52b26 100644 --- a/wiretap/wtap.h +++ b/wiretap/wtap.h @@ -194,6 +194,7 @@ extern "C" { #define WTAP_ENCAP_PPI 97 #define WTAP_ENCAP_ERF 98 #define WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR 99 +#define WTAP_ENCAP_SITA 100 #define WTAP_NUM_ENCAP_TYPES wtap_get_num_encap_types() @@ -644,6 +645,70 @@ struct erf_mc_phdr { } subhdr; }; +#define SITA_FRAME_DIR_TXED (0x00) /* values of sita_phdr.flags */ +#define SITA_FRAME_DIR_RXED (0x01) +#define SITA_FRAME_DIR (0x01) /* mask */ +#define SITA_ERROR_NO_BUFFER (0x80) + +#define SITA_SIG_DSR (0x01) /* values of sita_phdr.signals */ +#define SITA_SIG_DTR (0x02) +#define SITA_SIG_CTS (0x04) +#define SITA_SIG_RTS (0x08) +#define SITA_SIG_DCD (0x10) +#define SITA_SIG_UNDEF1 (0x20) +#define SITA_SIG_UNDEF2 (0x40) +#define SITA_SIG_UNDEF3 (0x80) + +#define SITA_ERROR_TX_UNDERRUN (0x01) /* values of sita_phdr.errors2 (if SITA_FRAME_DIR_TXED) */ +#define SITA_ERROR_TX_CTS_LOST (0x02) +#define SITA_ERROR_TX_UART_ERROR (0x04) +#define SITA_ERROR_TX_RETX_LIMIT (0x08) +#define SITA_ERROR_TX_UNDEF1 (0x10) +#define SITA_ERROR_TX_UNDEF2 (0x20) +#define SITA_ERROR_TX_UNDEF3 (0x40) +#define SITA_ERROR_TX_UNDEF4 (0x80) + +#define SITA_ERROR_RX_FRAMING (0x01) /* values of sita_phdr.errors1 (if SITA_FRAME_DIR_RXED) */ +#define SITA_ERROR_RX_PARITY (0x02) +#define SITA_ERROR_RX_COLLISION (0x04) +#define SITA_ERROR_RX_FRAME_LONG (0x08) +#define SITA_ERROR_RX_FRAME_SHORT (0x10) +#define SITA_ERROR_RX_UNDEF1 (0x20) +#define SITA_ERROR_RX_UNDEF2 (0x40) +#define SITA_ERROR_RX_UNDEF3 (0x80) + +#define SITA_ERROR_RX_NONOCTET_ALIGNED (0x01) /* values of sita_phdr.errors2 (if SITA_FRAME_DIR_RXED) */ +#define SITA_ERROR_RX_ABORT (0x02) +#define SITA_ERROR_RX_CD_LOST (0x04) +#define SITA_ERROR_RX_DPLL (0x08) +#define SITA_ERROR_RX_OVERRUN (0x10) +#define SITA_ERROR_RX_FRAME_LEN_VIOL (0x20) +#define SITA_ERROR_RX_CRC (0x40) +#define SITA_ERROR_RX_BREAK (0x80) + +#define SITA_PROTO_UNUSED (0x00) /* values of sita_phdr.proto */ +#define SITA_PROTO_BOP_LAPB (0x01) +#define SITA_PROTO_ETHERNET (0x02) +#define SITA_PROTO_ASYNC_INTIO (0x03) +#define SITA_PROTO_ASYNC_BLKIO (0x04) +#define SITA_PROTO_ALC (0x05) +#define SITA_PROTO_UTS (0x06) +#define SITA_PROTO_PPP_HDLC (0x07) +#define SITA_PROTO_SDLC (0x08) +#define SITA_PROTO_TOKENRING (0x09) +#define SITA_PROTO_I2C (0x10) +#define SITA_PROTO_DPM_LINK (0x11) +#define SITA_PROTO_BOP_FRL (0x12) + +struct sita_phdr { + guint8 flags; + guint8 signals; + guint8 errors1; + guint8 errors2; + guint8 proto; +}; + + union wtap_pseudo_header { struct eth_phdr eth; struct x25_phdr x25; @@ -661,6 +726,7 @@ union wtap_pseudo_header { struct catapult_dct2000_phdr dct2000; struct linux_usb_phdr linux_usb; struct erf_mc_phdr erf; + struct sita_phdr sita; }; struct wtap_nstime { |