aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn A. Thacker <johnthacker@gmail.com>2016-01-04 11:53:41 -0500
committerAnders Broman <a.broman58@gmail.com>2016-01-05 05:20:13 +0000
commit85fd9df235dcf77117b45ade4494c99e983595ec (patch)
treed2f463df7f0373d302011f9889f2cacf88c3d487
parent6f8ca079b48a70a7bd33544b42f0bca7b6ff1ad1 (diff)
GFP: Add support for Generic Framing Procedure (ITU-T G.7041/Y.1303)
Add support for Generic Framing Procedure. Generic Framing Procedure (GFP) is used to map octet-aligned variable length payloads (e.g. Ethernet, MPLS, octet-aligned PPP, IP) into octet-synchronous signals such as SONET/SDH (ITU-T G.707) and OTN (ITU-T G.709). GFP is a telecommunications industry standard defined in ITU-T G.7041/Y.1303. (https://www.itu.int/rec/T-REC-G.7041/) Bug: 11961 Change-Id: Idf5b311e82b051b1ee65bde5149b3de405537b02 Reviewed-on: https://code.wireshark.org/review/13043 Petri-Dish: Alexis La Goutte <alexis.lagoutte@gmail.com> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Anders Broman <a.broman58@gmail.com>
-rw-r--r--docbook/release-notes.asciidoc1
-rw-r--r--epan/CMakeLists.txt1
-rw-r--r--epan/dissectors/Makefile.common1
-rw-r--r--epan/dissectors/packet-gfp.c679
-rw-r--r--wiretap/pcap-common.c7
-rw-r--r--wiretap/wtap.c7
-rw-r--r--wiretap/wtap.h2
7 files changed, 694 insertions, 4 deletions
diff --git a/docbook/release-notes.asciidoc b/docbook/release-notes.asciidoc
index 35729396fb..14ed508243 100644
--- a/docbook/release-notes.asciidoc
+++ b/docbook/release-notes.asciidoc
@@ -50,6 +50,7 @@ Nokia Intelligent Service Interface (ISI)
ISO14443
Extensible Control & Management Protocol (eCMP)
RTI TCP Transport Layer (RTITCP)
+ITU-T G.7041/Y.1303 Generic Framing Procedure (GFP)
// Items in --sort-and-group-- blocks will be sorted and comma-separated.
--sort-and-group--
--sort-and-group--
diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt
index 2f61110dd8..1fbb883754 100644
--- a/epan/CMakeLists.txt
+++ b/epan/CMakeLists.txt
@@ -712,6 +712,7 @@ set(DISSECTOR_SRC
dissectors/packet-ged125.c
dissectors/packet-geneve.c
dissectors/packet-gift.c
+ dissectors/packet-gfp.c
dissectors/packet-giop.c
dissectors/packet-git.c
dissectors/packet-glbp.c
diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common
index f88dbb3b05..eeeedf12b0 100644
--- a/epan/dissectors/Makefile.common
+++ b/epan/dissectors/Makefile.common
@@ -633,6 +633,7 @@ DISSECTOR_SRC = \
packet-gearman.c \
packet-ged125.c \
packet-geneve.c \
+ packet-gfp.c \
packet-gift.c \
packet-giop.c \
packet-git.c \
diff --git a/epan/dissectors/packet-gfp.c b/epan/dissectors/packet-gfp.c
new file mode 100644
index 0000000000..87bebab7d8
--- /dev/null
+++ b/epan/dissectors/packet-gfp.c
@@ -0,0 +1,679 @@
+/* packet-gfp.c
+ * Routines for Generic Framing Procedure dissection
+ * Copyright 2015, John Thacker <johnthacker@gmail.com>
+ *
+ * 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.
+ */
+
+/*
+ * Generic Framing Procedure (GFP) is used to map octet-aligned variable
+ * length payloads (e.g. Ethernet, MPLS, octet-aligned PPP, IP) into
+ * octet-synchronous signals such as SONET/SDH (ITU-T G.707) and OTN
+ * (ITU-T G.709). GFP is a telecommunications industry standard defined in
+ * ITU-T G.7041/Y.1303.
+ *
+ * Reference:
+ * https://www.itu.int/rec/T-REC-G.7041/
+ */
+
+#include <config.h>
+
+#include <epan/packet.h> /* Should be first Wireshark include (other than config.h) */
+#include <epan/expert.h>
+#include <epan/prefs.h>
+#include <epan/crc16-tvb.h>
+#include <epan/crc32-tvb.h>
+#include <epan/decode_as.h>
+#include <wiretap/wtap.h>
+
+/* Prototypes */
+/* (Required to prevent [-Wmissing-prototypes] warnings */
+void proto_reg_handoff_gfp(void);
+void proto_register_gfp(void);
+
+/* Initialize the protocol and registered fields */
+static int proto_gfp = -1;
+static int hf_gfp_pli = -1;
+static int hf_gfp_chec = -1;
+static int hf_gfp_chec_good = -1;
+static int hf_gfp_chec_bad = -1;
+static int hf_gfp_type = -1;
+static int hf_gfp_pti = -1;
+static int hf_gfp_pfi = -1;
+static int hf_gfp_exi = -1;
+static int hf_gfp_upi_data = -1;
+static int hf_gfp_upi_management = -1;
+static int hf_gfp_thec = -1;
+static int hf_gfp_thec_good = -1;
+static int hf_gfp_thec_bad = -1;
+static int hf_gfp_cid = -1;
+static int hf_gfp_ehec = -1;
+static int hf_gfp_ehec_good = -1;
+static int hf_gfp_ehec_bad = -1;
+static int hf_gfp_fcs = -1;
+static int hf_gfp_fcs_good = -1;
+static int hf_gfp_fcs_bad = -1;
+
+static expert_field ei_gfp_pli_idle_nonempty = EI_INIT;
+static expert_field ei_gfp_pli_unknown = EI_INIT;
+static expert_field ei_gfp_pli_invalid = EI_INIT;
+static expert_field ei_gfp_chec_bad = EI_INIT;
+static expert_field ei_gfp_thec_bad = EI_INIT;
+static expert_field ei_gfp_ehec_bad = EI_INIT;
+static expert_field ei_gfp_exi_short = EI_INIT;
+static expert_field ei_gfp_pfi_short = EI_INIT;
+static expert_field ei_gfp_payload_undecoded = EI_INIT;
+static expert_field ei_gfp_fcs_bad = EI_INIT;
+
+#define GFP_USER_DATA 0
+#define GFP_CLIENT_MANAGEMENT 4
+#define GFP_MANAGEMENT_COMMUNICATIONS 5
+
+#define GFP_EXT_NULL 0
+#define GFP_EXT_LINEAR 1
+#define GFP_EXT_RING 2
+
+/* Initialize the subtree pointers */
+static gint ett_gfp = -1;
+static gint ett_gfp_chec = -1;
+static gint ett_gfp_type = -1;
+static gint ett_gfp_thec = -1;
+static gint ett_gfp_ehec = -1;
+static gint ett_gfp_fcs = -1;
+
+static dissector_handle_t data_handle;
+static dissector_table_t gfp_dissector_table;
+
+/* ITU-T G.7041 6.1.1, 6.2 */
+static const range_string gfp_pli_rvals[] = {
+ {0, 0, "Idle Frame"},
+ {1, 3, "Control Frame (Reserved)"},
+ {4, G_MAXUINT16, "Client Frame"},
+ {0, 0, NULL}
+};
+
+static const int *gfp_type_data_fields[] = {
+ &hf_gfp_pti,
+ &hf_gfp_pfi,
+ &hf_gfp_exi,
+ &hf_gfp_upi_data,
+ NULL
+};
+
+static const int *gfp_type_management_fields[] = {
+ &hf_gfp_pti,
+ &hf_gfp_pfi,
+ &hf_gfp_exi,
+ &hf_gfp_upi_management,
+ NULL
+};
+
+static const value_string gfp_pti_vals[] = {
+ {GFP_USER_DATA, "User Data"},
+ {GFP_CLIENT_MANAGEMENT, "Client Management"},
+ {GFP_MANAGEMENT_COMMUNICATIONS, "Management Communications"},
+ {0, NULL}
+};
+
+static const value_string gfp_exi_vals[] = {
+ {GFP_EXT_NULL, "Null Extension Header"},
+ {GFP_EXT_LINEAR, "Linear Frame"},
+ {GFP_EXT_RING, "Ring Frame"},
+ {0, NULL}
+};
+
+static const range_string gfp_upi_data_rvals[] = {
+ {0, 0, "Reserved and not available"},
+ {1, 1, "Frame-Mapped Ethernet"},
+ {2, 2, "Frame-Mapped PPP"},
+ {3, 3, "Transparent Fibre Channel"},
+ {4, 4, "Transparent FICON"},
+ {5, 5, "Transparent ESCON"},
+ {6, 6, "Transparent Gbit Ethernet"},
+ {7, 7, "Reserved"},
+ {8, 8, "Frame-Mapped Multiple Access Protocol over SDH (MAPOS)"},
+ {9, 9, "Transparent DVB ASI"},
+ {10, 10, "Frame-Mapped IEEE 802.17 Resilient Packet Ring"},
+ {11, 11, "Frame-Mapped Fibre Channel FC-BBW"},
+ {12, 12, "Asycnchronous Transparent Fibre Channel"},
+ {13, 13, "Frame-Mapped MPLS"},
+ {14, 14, "Frame-Mapped MPLS (Multicast) [Deprecrated]"},
+ {15, 15, "Frame-Mapped OSI network layer protocols (IS-IS, ES-IS, CLNP)"},
+ {16, 16, "Frame-Mapped IPv4"},
+ {17, 17, "Frame-Mapped IPv6"},
+ {18, 18, "Frame-Mapped DVB-ASI"},
+ {19, 19, "Frame-Mapped 64B/66B encoded Ethernet, including frame preamble"},
+ {20, 20,"Frame-Mapped 64B/66B encoded Ethernet ordered set information"},
+ {21, 21, "Transparent transcoded FC-1200"},
+ {22, 239, "Reserved for future standardization"},
+ {240, 252, "Reserved for proprietary use"},
+ {253, 253, "Reserved for proprietary use, formerly Frame-Mapped 64B/66B encoded Ethernet, including frame preamble"},
+ {254, 254, "Reserved for proprietary use, formerly Frame-Mapped 64B/66B encoded Ethernet ordered set information"},
+ {255, 255, "Reserved and not available"},
+ {0, 0, NULL }
+};
+
+static const range_string gfp_upi_management_rvals[] = {
+ {0, 0, "Reserved and not available"},
+ {1, 1, "Client Signal Fail (Loss of Client Signal)"},
+ {2, 2, "Client Signal Fail (Loss of Character Synchronisation)"},
+ {3, 3, "Defect Clear Indication (DCI)"},
+ {4, 4, "Forward Defect Indication (FDI)"},
+ {5, 5, "Reverse Defect Indication (RDI)"},
+ {6, 223, "Reserved for future use"},
+ {224, 254, "Reserved for proprietary use"},
+ {255, 255, "Reserved and not available"},
+ {0, 0, NULL}
+};
+
+
+/* Even GFP idle frames must have 4 bytes for the core header.
+ * If data is received with fewer than this it is rejected. */
+#define GFP_MIN_LENGTH 4
+
+static void gfp_prompt(packet_info *pinfo, gchar* result)
+{
+ g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "UPI %u as",
+ GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_gfp, 0)));
+}
+
+static gpointer gfp_value(packet_info *pinfo)
+{
+ return p_get_proto_data(pinfo->pool, pinfo, proto_gfp, 0);
+}
+
+/* GFP has several identical 16 bit CRCs in its header (HECs). Note that
+ * this function increases the offset. */
+static void
+gfp_add_hec_tree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint *offset, const guint len, const int field, const int field_good, const int field_bad, const gint ett, expert_field *ei_bad)
+{
+
+ proto_item* ti = NULL;
+ proto_tree* hec_tree = NULL;
+ guint hec, hec_calc;
+
+ hec_calc = crc16_r3_ccitt_tvb(tvb, *offset, len);
+ *offset += len;
+ hec = tvb_get_ntohs(tvb, *offset);
+
+ if ( hec == hec_calc ) {
+ ti = proto_tree_add_uint_format_value(tree, field, tvb, *offset, 2, hec, "0x%04x [correct]", hec);
+ hec_tree = proto_item_add_subtree(ti, ett);
+ ti = proto_tree_add_boolean(hec_tree, field_good, tvb, *offset, 2, TRUE);
+ PROTO_ITEM_SET_GENERATED(ti);
+ ti = proto_tree_add_boolean(hec_tree, field_bad, tvb, *offset, 2, FALSE);
+ PROTO_ITEM_SET_GENERATED(ti);
+ } else {
+ ti = proto_tree_add_uint_format_value(tree, field, tvb, *offset, 2, hec, "0x%04x [incorrect, should be 0x%04x]", hec, hec_calc);
+ hec_tree = proto_item_add_subtree(ti, ett);
+ ti = proto_tree_add_boolean(hec_tree, field_good, tvb, *offset, 2, FALSE);
+ PROTO_ITEM_SET_GENERATED(ti);
+ ti = proto_tree_add_boolean(hec_tree, field_bad, tvb, *offset, 2, TRUE);
+ PROTO_ITEM_SET_GENERATED(ti);
+ expert_add_info(pinfo, ti, ei_bad);
+ }
+
+ *offset += 2;
+}
+
+/* G.7041 6.1.2 GFP payload area */
+static void
+dissect_gfp_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *gfp_tree, guint *offset, guint payload_len)
+{
+ tvbuff_t *payload_tvb;
+ proto_item *type_ti = NULL;
+ proto_item *fcs_ti;
+ proto_tree *fcs_tree = NULL;
+ guint pti, pfi, exi, upi;
+ guint fcs, fcs_calc;
+ guint fcs_len = 0;
+ dissector_handle_t handle;
+
+ /* G.7041 6.1.2.3 Payload area scrambling
+ * Note that payload when sent on the wire is scrambled as per ATM
+ * with a 1 + x^43 multiplicative scrambler. Likely already removed by
+ * the time we get a capture file (as with ATM). Could have a pref,
+ * but if it's present we have to save state over subsequent frames,
+ * always would fail to decode the first 43 payload bytes of a capture. */
+
+ /* G.7041 6.1.2.1 Payload Header - at least 4 bytes */
+ tvb_ensure_bytes_exist(tvb, *offset, 4);
+ payload_len -= 4;
+
+ /* G.7041 6.1.2.1.1 GFP type field - mandatory 2 bytes */
+ pti = tvb_get_bits8(tvb, 8*(*offset), 3);
+ pfi = tvb_get_bits8(tvb, 8*(*offset)+3, 1);
+ exi = tvb_get_bits8(tvb, 8*(*offset)+4, 4);
+ upi = tvb_get_guint8(tvb, *offset+1);
+ p_add_proto_data(pinfo->pool, pinfo, proto_gfp, 0, GUINT_TO_POINTER(upi));
+
+ col_add_str(pinfo->cinfo, COL_INFO, val_to_str(pti, gfp_pti_vals, "Reserved PTI (%d)"));
+ if (pti == GFP_USER_DATA ||
+ pti == GFP_MANAGEMENT_COMMUNICATIONS) {
+ /* G.7041 Table 6-3 - GFP_MANAGEMENT_COMMUNICATIONS
+ * uses the same UPI table as USER_DATA, though
+ * "not all of these UPI types are applicable" in that case. */
+ type_ti = proto_tree_add_bitmask_with_flags(gfp_tree, tvb, *offset, hf_gfp_type,
+ ett_gfp_type, gfp_type_data_fields, ENC_BIG_ENDIAN, BMT_NO_FLAGS);
+ col_append_sep_str(pinfo->cinfo, COL_INFO, ": ", rval_to_str(upi, gfp_upi_data_rvals, "Unknown 0x%02x"));
+ } else if (pti == GFP_CLIENT_MANAGEMENT) {
+ /* G.7041 Table 6-4 */
+ type_ti = proto_tree_add_bitmask_with_flags(gfp_tree, tvb, *offset, hf_gfp_type,
+ ett_gfp_type, gfp_type_management_fields, ENC_BIG_ENDIAN, BMT_NO_FLAGS);
+ col_append_sep_str(pinfo->cinfo, COL_INFO, ": ", rval_to_str(upi, gfp_upi_management_rvals, "Unknown 0x%02x"));
+ }
+
+ /* G.7041 6.1.2.1.2 Type HEC (tHEC) - mandatory 2 bytes */
+ gfp_add_hec_tree(tvb, pinfo, gfp_tree, offset, 2, hf_gfp_thec, hf_gfp_thec_good, hf_gfp_thec_bad, ett_gfp_thec, &ei_gfp_thec_bad);
+
+ switch (exi) {
+ case GFP_EXT_NULL:
+ /* G.7041 6.1.2.1.3.1 Null extension header */
+ break;
+
+ case GFP_EXT_LINEAR:
+ /* G.7041 6.1.2.1.3.2 Extension header for a linear frame */
+ if (payload_len < 4) {
+ expert_add_info(pinfo, type_ti, &ei_gfp_exi_short);
+ payload_len = 0;
+ }
+ else {
+ payload_len -= 4;
+ }
+ proto_tree_add_item(gfp_tree, hf_gfp_cid, tvb, *offset, 1, ENC_BIG_ENDIAN);
+ /* Next byte spare field, reserved */
+
+ /* 6.1.2.1.4 Extension HEC field */
+ gfp_add_hec_tree(tvb, pinfo, gfp_tree, offset, 2, hf_gfp_ehec, hf_gfp_ehec_good, hf_gfp_ehec_bad, ett_gfp_ehec, &ei_gfp_ehec_bad);
+ break;
+ case GFP_EXT_RING:
+ /* 6.1.2.1.3.3 Extension header for a ring frame */
+ /* "For further study." Undefined so fall through */
+ default:
+ /* Reserved */
+ /* TODO: Mark as error / unhandled? */
+ break;
+ }
+
+ proto_item_set_end(gfp_tree, tvb, *offset);
+
+ if (pfi == 1) { /* 6.1.2.2.1 Payload FCS field present */
+ if (payload_len < 4) {
+ expert_add_info(pinfo, type_ti, &ei_gfp_pfi_short);
+ fcs_len = payload_len;
+ payload_len = 0;
+ } else {
+ fcs_len = 4;
+ payload_len -= 4;
+ }
+
+ proto_tree_set_appendix(gfp_tree, tvb, *offset + payload_len, fcs_len);
+ fcs = tvb_get_ntohl(tvb, *offset + payload_len);
+ /* Same CRC32 as ATM */
+ /* As with ATM, we can either compute the CRC as it would be
+ * calculated and compare (last step involves taking the complement),
+ * or we can include the passed CRC in the input and check to see
+ * if the remainder is a known value. I like the first method
+ * only because it lets us display what we should have received. */
+ /* Method 1: */
+ fcs_calc = crc32_mpeg2_tvb_offset(tvb, *offset, payload_len);
+ if (fcs == ~fcs_calc) {
+ fcs_ti = proto_tree_add_uint_format_value(gfp_tree, hf_gfp_fcs, tvb, *offset+payload_len, 4, fcs, "0x%08x [correct]", fcs);
+ fcs_tree = proto_item_add_subtree(fcs_ti, ett_gfp_fcs);
+ fcs_ti = proto_tree_add_boolean(fcs_tree, hf_gfp_fcs_good, tvb, *offset+payload_len, 4, TRUE);
+ PROTO_ITEM_SET_GENERATED(fcs_ti);
+ fcs_ti = proto_tree_add_boolean(fcs_tree, hf_gfp_fcs_bad, tvb, *offset+payload_len, 4, FALSE);
+ PROTO_ITEM_SET_GENERATED(fcs_ti);
+ } else {
+ fcs_ti = proto_tree_add_uint_format_value(gfp_tree, hf_gfp_fcs, tvb, *offset+payload_len, 4, fcs, "0x%08x [incorrect, should be 0x%08x]", fcs, fcs_calc);
+ fcs_tree = proto_item_add_subtree(fcs_ti, ett_gfp_fcs);
+ fcs_ti = proto_tree_add_boolean(fcs_tree, hf_gfp_fcs_good, tvb, *offset+payload_len, 4, FALSE);
+ PROTO_ITEM_SET_GENERATED(fcs_ti);
+ fcs_ti = proto_tree_add_boolean(fcs_tree, hf_gfp_fcs_bad, tvb, *offset+payload_len, 4, TRUE);
+ PROTO_ITEM_SET_GENERATED(fcs_ti);
+ expert_add_info(pinfo, fcs_ti, &ei_gfp_fcs_bad);
+ }
+ /* Method 2: */
+ /* fcs_calc = crc32_mpeg2_tvb_offset(tvb, *offset, payload_len+4);
+ fcs_ti = proto_tree_add_uint(gfp_tree, hf_gfp_fcs, tvb, *offset+payload_len, 4, fcs);
+ proto_item_append_text(fcs_ti, (fcs_calc == 0xC704DD7B) ? " [correct]" : " [incorrect]"); */
+ }
+
+ /* Some client frames we can do. Others are not implemented yet.
+ * Transparent mode types are much trickier than frame-mapped,
+ * since they requires reassembling streams across multiple GFP packets. */
+ payload_tvb = tvb_new_subset_length(tvb, *offset, payload_len);
+ switch (pti) {
+ case GFP_USER_DATA:
+ case GFP_MANAGEMENT_COMMUNICATIONS:
+ handle = dissector_get_uint_handle(gfp_dissector_table, upi);
+ if (handle == NULL) {
+ expert_add_info_format(pinfo, type_ti, &ei_gfp_payload_undecoded, "Payload type 0x%02x (%s) unsupported", upi, rval_to_str_const(upi, gfp_upi_data_rvals, "UNKNOWN"));
+ handle = data_handle;
+ }
+ if (!call_dissector(handle, payload_tvb, pinfo, tree)) {
+ call_dissector(data_handle, payload_tvb, pinfo, tree);
+ }
+ break;
+
+ case GFP_CLIENT_MANAGEMENT:
+ call_dissector(data_handle, payload_tvb, pinfo, tree);
+ break;
+
+ default:
+ break;
+ }
+ offset += payload_len;
+ offset += fcs_len;
+
+}
+
+static int
+dissect_gfp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ void *data _U_)
+{
+ proto_item *ti, *pli_ti;
+ proto_tree *gfp_tree;
+ guint offset = 0;
+ int len = 0;
+ guint pli;
+
+ /*** HEURISTICS ***/
+
+ /* Check that the packet is long enough for it to belong to us. */
+ if (tvb_reported_length(tvb) < GFP_MIN_LENGTH)
+ return 0;
+
+ /*** COLUMN DATA ***/
+
+ /* Set the Protocol column to the constant string of GFP */
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "GFP");
+
+ col_clear(pinfo->cinfo, COL_INFO);
+ /* Avoid asserts for leaving these blank. */
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "N/A");
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "N/A");
+
+ /*** PROTOCOL TREE ***/
+
+ /* create display subtree for the protocol */
+ ti = proto_tree_add_item(tree, proto_gfp, tvb, 0, GFP_MIN_LENGTH, ENC_NA);
+
+ gfp_tree = proto_item_add_subtree(ti, ett_gfp);
+
+ /* ITU-T G.7041 6.1.1 GFP core header */
+ /* The core header could be scrambled (see G.7041 6.1.1.3) but isn't on
+ * the GFP level capture files I've seen as it's removed before then.
+ * If using this as a subdissector to a SDH or OTN dissector, that could
+ * be an issue. TODO: Maybe add a pref for scrambling? */
+ len = 2;
+ pli_ti = proto_tree_add_item_ret_uint(gfp_tree, hf_gfp_pli, tvb,
+ offset, len, ENC_BIG_ENDIAN, &pli);
+ if (pli < 4) { /* Don't interpret as payload length */
+ proto_item_append_text(pli_ti, " (%s)", rval_to_str_const(pli, gfp_pli_rvals, "Unknown"));
+ }
+ col_set_str(pinfo->cinfo, COL_INFO, rval_to_str_const(pli, gfp_pli_rvals, "Unknown"));
+
+ /* 6.1.1.2 Core HEC field */
+ gfp_add_hec_tree(tvb, pinfo, gfp_tree, &offset, len, hf_gfp_chec, hf_gfp_chec_good, hf_gfp_chec_bad, ett_gfp_chec, &ei_gfp_chec_bad);
+
+ if (pli == 0) { /* 6.2.1 GFP idle frames */
+ if (tvb_reported_length_remaining(tvb, offset)) {
+ expert_add_info(pinfo, pli_ti, &ei_gfp_pli_idle_nonempty);
+ }
+ } else if (pli < 4) { /* 6.2.2 Other control frames (reserved) */
+ expert_add_info(pinfo, pli_ti, &ei_gfp_pli_unknown);
+ } else {
+ /* G.7041 6.1.2 GFP payload area */
+ if (tvb_reported_length(tvb) < pli + offset) {
+ /* avoid signed / unsigned comparison */
+ proto_item_append_text(pli_ti, " (invalid, reported length is %u)", tvb_reported_length_remaining(tvb, offset));
+ expert_add_info(pinfo, pli_ti, &ei_gfp_pli_invalid);
+ }
+ dissect_gfp_payload(tvb, pinfo, tree, gfp_tree, &offset, pli);
+ }
+
+ /* Return the amount of data this dissector was able to dissect */
+ return offset;
+}
+
+void
+proto_register_gfp(void)
+{
+ /* Setup list of header fields See Section 1.5 of README.dissector for
+ * details. */
+ static hf_register_info hf[] = {
+ { &hf_gfp_pli,
+ { "Payload Length Indicator", "gfp.pli", FT_UINT16, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_gfp_chec,
+ { "Core HEC", "gfp.chec", FT_UINT16, BASE_HEX,
+ NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_gfp_chec_good,
+ { "Good cHEC", "gfp.chec_good", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "True: cHEC matches core header; False: doesn't match", HFILL }
+ },
+ { &hf_gfp_chec_bad,
+ { "Bad cHEC", "gfp.chec_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "True: cHEC doesn't match core header; False: matches", HFILL }
+ },
+ { &hf_gfp_type,
+ { "Type Field", "gfp.type", FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_gfp_pti,
+ { "PTI", "gfp.pti", FT_UINT16, BASE_HEX, VALS(gfp_pti_vals),
+ 0xE000, "Payload Type Identifier", HFILL }
+ },
+ { &hf_gfp_pfi,
+ { "PFI", "gfp.pfi", FT_BOOLEAN, 16, TFS(&tfs_present_absent),
+ 0x1000, "Payload FCS Indicator", HFILL }
+ },
+ { &hf_gfp_exi,
+ { "EXI", "gfp.exi", FT_UINT16, BASE_HEX, VALS(gfp_exi_vals),
+ 0x0F00, "Extension Header Identifier", HFILL }
+ },
+ { &hf_gfp_upi_data,
+ { "UPI", "gfp.upi", FT_UINT16, BASE_HEX|BASE_RANGE_STRING,
+ RVALS(gfp_upi_data_rvals),
+ 0xFF, "User Payload Identifier for Client Data Frame (or Management Communications Frame)", HFILL }
+ },
+ { &hf_gfp_upi_management,
+ { "UPI", "gfp.upi", FT_UINT16, BASE_HEX|BASE_RANGE_STRING,
+ RVALS(gfp_upi_management_rvals),
+ 0xFF, "User Payload Identifier for Client Management Frame", HFILL }
+ },
+ { &hf_gfp_thec,
+ { "Type HEC", "gfp.thec", FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_gfp_thec_good,
+ { "Good tHEC", "gfp.thec_good", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "True: tHEC matches type header; False: doesn't match", HFILL }
+ },
+ { &hf_gfp_thec_bad,
+ { "Bad tHEC", "gfp.thec_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "True: tHEC doesn't match type header; False: matches", HFILL }
+ },
+ { &hf_gfp_cid,
+ { "Channel ID", "gfp.cid", FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_gfp_ehec,
+ { "Extension HEC", "gfp.ehec", FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_gfp_ehec_good,
+ { "Good eHEC", "gfp.ehec_good", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "True: eHEC matches extension header; False: doesn't match", HFILL }
+ },
+ { &hf_gfp_ehec_bad,
+ { "Bad eHEC", "gfp.ehec_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "True: eHEC doesn't match extension header; False: matches", HFILL }
+ },
+ { &hf_gfp_fcs,
+ { "Payload FCS", "gfp.fcs", FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_gfp_fcs_good,
+ { "Good FCS", "gfp.fcs_good", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "True: FCS matches payload; False: doesn't match", HFILL }
+ },
+ { &hf_gfp_fcs_bad,
+ { "Bad eHEC", "gfp.fcs_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "True: FCS doesn't match payload; False: matches", HFILL }
+ }
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_gfp,
+ &ett_gfp_chec,
+ &ett_gfp_type,
+ &ett_gfp_thec,
+ &ett_gfp_ehec,
+ &ett_gfp_fcs
+ };
+
+ /* Setup protocol expert items */
+ static ei_register_info ei[] = {
+ { &ei_gfp_pli_idle_nonempty,
+ { "gfp.pli.idle.nonempty", PI_MALFORMED, PI_ERROR,
+ "Payload present on idle frame", EXPFILL }
+ },
+ { &ei_gfp_pli_unknown,
+ { "gfp.pli.unknown", PI_UNDECODED, PI_WARN,
+ "Unknown control frame type", EXPFILL }
+ },
+ { &ei_gfp_pli_invalid,
+ { "gfp.pli.invalid", PI_MALFORMED, PI_WARN,
+ "Bogus PLI does not match reported length", EXPFILL }
+ },
+ { &ei_gfp_chec_bad,
+ { "gfp.chec.bad", PI_CHECKSUM, PI_WARN,
+ "Bad cHEC", EXPFILL }
+ },
+ { &ei_gfp_thec_bad,
+ { "gfp.thec.bad", PI_CHECKSUM, PI_WARN,
+ "Bad tHEC", EXPFILL }
+ },
+ { &ei_gfp_ehec_bad,
+ { "gfp.ehec.bad", PI_CHECKSUM, PI_WARN,
+ "Bad eHEC", EXPFILL }
+ },
+ { &ei_gfp_exi_short,
+ { "gfp.exi.missing", PI_MALFORMED, PI_ERROR,
+ "EXI bit set but PLI too short for extension header", EXPFILL}
+ },
+ { &ei_gfp_pfi_short,
+ { "gfp.pfi.missing", PI_MALFORMED, PI_ERROR,
+ "PFI bit set but PLI too short for payload FCS", EXPFILL}
+ },
+ { &ei_gfp_payload_undecoded,
+ { "gfp.payload.undecoded", PI_UNDECODED, PI_WARN,
+ "Payload type not supported yet by the dissector", EXPFILL}
+ },
+ { &ei_gfp_fcs_bad,
+ { "gfp.fcs.bad", PI_CHECKSUM, PI_WARN,
+ "Bad FCS", EXPFILL }
+ }
+ };
+
+ /* Decode As handling */
+ static build_valid_func gfp_da_build_value[1] = {gfp_value};
+ static decode_as_value_t gfp_da_values = {gfp_prompt, 1, gfp_da_build_value};
+ static decode_as_t gfp_da = {"gfp", "GFP", "gfp.upi", 1, 0, &gfp_da_values, NULL, NULL,
+ decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
+
+ /* module_t *gfp_module; */
+ expert_module_t *expert_gfp;
+
+ /* Register the protocol name and description */
+ proto_gfp = proto_register_protocol("Generic Framing Procedure",
+ "GFP", "gfp");
+
+ /* Required function calls to register the header fields and subtrees */
+ proto_register_field_array(proto_gfp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ /* Required function calls to register expert items */
+ expert_gfp = expert_register_protocol(proto_gfp);
+ expert_register_field_array(expert_gfp, ei, array_length(ei));
+
+ /* Subdissectors for payload */
+ gfp_dissector_table = register_dissector_table("gfp.upi", "GFP UPI (for Client Data frames)",
+ FT_UINT8, BASE_DEC, DISSECTOR_TABLE_NOT_ALLOW_DUPLICATE);
+
+ /* Don't register a preferences module yet since there are no prefs in
+ * order to avoid a warning. (See section 2.6 of README.dissector
+ * for more details on preferences). */
+ /*gfp_module = prefs_register_protocol(proto_gfp, NULL);*/
+
+ register_decode_as(&gfp_da);
+}
+
+/* If this function is registered as a prefs callback (see
+ * prefs_register_protocol above) this function is also called by Wireshark's
+ * preferences manager whenever "Apply" or "OK" are pressed. In that case, it
+ * should accommodate being called more than once by use of the static
+ * 'initialized' variable included below.
+ *
+ * This form of the reg_handoff function is used if if you perform registration
+ * functions which are dependent upon prefs.
+ */
+void
+proto_reg_handoff_gfp(void)
+{
+ static dissector_handle_t gfp_handle;
+
+ gfp_handle = create_dissector_handle(dissect_gfp,
+ proto_gfp);
+
+ data_handle = find_dissector("data");
+
+ dissector_add_uint("wtap_encap", WTAP_ENCAP_GFP_T, gfp_handle);
+ dissector_add_uint("wtap_encap", WTAP_ENCAP_GFP_F, gfp_handle);
+
+ /* Add a few of the easiest UPIs to decode. There's more that probably
+ * would work, but are untested (frame mapped DVB, frame mapped Fibre
+ * Channel). The transparent mode ones are trickier, since without a
+ * one-to-one mapping of frames, we would have to reassemble payload
+ * packets across multiple GFP packets. */
+ dissector_add_uint("gfp.upi", 1, find_dissector("eth"));
+ dissector_add_uint("gfp.upi", 2, find_dissector("ppp_hdlc"));
+ dissector_add_uint("gfp.upi", 12, find_dissector("mpls"));
+ dissector_add_uint("gfp.upi", 13, find_dissector("mpls"));
+ dissector_add_uint("gfp.upi", 16, find_dissector("ip"));
+ dissector_add_uint("gfp.upi", 17, find_dissector("ipv6"));
+}
+
+/*
+ * Editor modelines - https://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/wiretap/pcap-common.c b/wiretap/pcap-common.c
index 2ae777e380..02be511875 100644
--- a/wiretap/pcap-common.c
+++ b/wiretap/pcap-common.c
@@ -306,10 +306,9 @@ static const struct {
{ 169, WTAP_ENCAP_GPRS_LLC },
- /*
- * 170 and 171 are reserved for ITU-T G.7041/Y.1303 Generic
- * Framing Procedure.
- */
+ /* ITU-T G.7041/Y.1303 Generic Framing Procedure. */
+ { 170, WTAP_ENCAP_GFP_T },
+ { 171, WTAP_ENCAP_GFP_F },
/* Registered by Gcom, Inc. */
{ 172, WTAP_ENCAP_GCOM_TIE1 },
diff --git a/wiretap/wtap.c b/wiretap/wtap.c
index c4c35e8a74..789adfbbfd 100644
--- a/wiretap/wtap.c
+++ b/wiretap/wtap.c
@@ -953,6 +953,13 @@ static struct encap_type_info encap_table_base[] = {
/* WTAP_ENCAP_ISO14443 */
{ "ISO 14443 contactless smartcard standards", "iso14443" },
+
+ /* WTAP_ENCAP_GFP_T */
+ { "ITU-T G.7041/Y.1303 Generic Framing Procedure Transparent mode", "gfp-t" },
+
+ /* WTAP_ENCAP_GFP_F */
+ { "ITU-T G.7041/Y.1303 Generic Framing Procedure Frame-mapped mode", "gfp-f" }
+
};
WS_DLL_LOCAL
diff --git a/wiretap/wtap.h b/wiretap/wtap.h
index df122fd3ad..0335607b2a 100644
--- a/wiretap/wtap.h
+++ b/wiretap/wtap.h
@@ -264,6 +264,8 @@ extern "C" {
#define WTAP_ENCAP_JSON 175
#define WTAP_ENCAP_NSTRACE_3_5 176
#define WTAP_ENCAP_ISO14443 177
+#define WTAP_ENCAP_GFP_T 178
+#define WTAP_ENCAP_GFP_F 179
/* After adding new item here, please also add new item to encap_table_base array */
#define WTAP_NUM_ENCAP_TYPES wtap_get_num_encap_types()