Add dissector for LINKTYPE_EPON
authorPhilip Rosenberg-Watt <p.rosenberg-watt@cablelabs.com>
Tue, 22 Apr 2014 20:16:40 +0000 (14:16 -0600)
committerEvan Huus <eapache@gmail.com>
Mon, 28 Apr 2014 15:26:32 +0000 (15:26 +0000)
See IEEE Standard 802.3-2012 Section 5, Clause 65 and CableLabs DPoE
Security and Certificate Specification 1.0, Section 6.

Currently dissects 1G mode. 10G mode will be added when hardware is
available.

Change-Id: I6232af9bf6807644ef66a120d97e5fa5927988fe
Reviewed-on: https://code.wireshark.org/review/1284
Tested-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Reviewed-by: Evan Huus <eapache@gmail.com>
docbook/release-notes.asciidoc
epan/CMakeLists.txt
epan/dissectors/Makefile.common
epan/dissectors/packet-epon.c [new file with mode: 0644]
wiretap/pcap-common.c
wiretap/wtap.c
wiretap/wtap.h

index 6bcf161bff13934530266722ff2b2430d898987d..cb092caa85f62cad80b0ed255ded382550c0d089 100644 (file)
@@ -121,6 +121,7 @@ Cisco MetaData
 DCE/RPC MDSSVC
 DeviceNet
 Ethernet Local Management Interface (E-LMI)
+Ethernet Passive Optical Network (EPON)
 ELF file format
 EXPORTED PDU
 FINGER
index cfe744c25ec190526e7943753768a7cf57c45546..5d6fe549fc8d2cb35b0cd49bfad2e056af1080de 100644 (file)
@@ -627,6 +627,7 @@ set(DISSECTOR_SRC
        dissectors/packet-epl.c
        dissectors/packet-epl_v1.c
        dissectors/packet-epmd.c
+       dissectors/packet-epon.c
        dissectors/packet-erf.c
        dissectors/packet-erldp.c
        dissectors/packet-esio.c
index 24a5a6a52547b5419708f626262f15f5e0309a4b..7182b2fa26012e1c7f3c0a5732206168683d601e 100644 (file)
@@ -547,6 +547,7 @@ DISSECTOR_SRC = \
        packet-epl.c            \
        packet-epl_v1.c         \
        packet-epmd.c           \
+       packet-epon.c           \
        packet-erf.c            \
        packet-erldp.c          \
        packet-esio.c           \
diff --git a/epan/dissectors/packet-epon.c b/epan/dissectors/packet-epon.c
new file mode 100644 (file)
index 0000000..680ac11
--- /dev/null
@@ -0,0 +1,297 @@
+/* packet-epon.c
+ * Routines for Ethernet Passive Optical Network dissection
+ * Copyright 2014, Philip Rosenberg-Watt <p.rosenberg-watt[at]cablelabs.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.
+ */
+
+/* 2014-04      Philip Rosenberg-Watt <p.rosenberg-watt[at]cablelabs.com>
+ *               + EPON preamble with CableLabs DPoE securty byte.
+ *                 See IEEE 802.3-2012 Section 5, Clause 65 and
+ *                 CableLabs DPoE SEC 1.0 specification.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/expert.h>
+#include <epan/prefs.h>
+
+#include <epan/addr_resolv.h>
+#include <epan/crc8-tvb.h>
+
+void proto_register_epon(void);
+void proto_reg_handoff_epon(void);
+
+static int proto_epon = -1;
+static int hf_epon_dpoe_security = -1;
+static int hf_epon_dpoe_encrypted = -1;
+static int hf_epon_dpoe_reserved = -1;
+static int hf_epon_dpoe_encrypted_data = -1;
+static int hf_epon_dpoe_keyid = -1;
+static int hf_epon_mode = -1;
+static int hf_epon_llid = -1;
+static int hf_epon_checksum = -1;
+
+static expert_field ei_epon_sld_bad = EI_INIT;
+static expert_field ei_epon_dpoe_reserved_bad = EI_INIT;
+static expert_field ei_epon_dpoe_bad = EI_INIT;
+static expert_field ei_epon_dpoe_encrypted_data = EI_INIT;
+static expert_field ei_epon_checksum_bad = EI_INIT;
+
+static dissector_handle_t eth_handle;
+
+static gint ett_epon = -1;
+static gint ett_epon_sec = -1;
+static gint ett_epon_checksum = -1;
+
+static const true_false_string epon_mode_tfs = {
+  "Broadcast/Multicast",
+  "Unicast"
+};
+
+static int
+dissect_epon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+             void *data _U_)
+{
+  proto_tree  *epon_tree;
+  proto_item  *ti;
+  proto_item  *item;
+  proto_tree  *sec_tree;
+  tvbuff_t    *next_tvb;
+  guint       checksum;
+  guint       sent_checksum;
+  guint       offset = 0;
+  guint       dpoe_sec_byte;
+  gboolean    dpoe_encrypted = FALSE;
+
+  /* Start_of_Packet delimiter (/S/) can either happen in byte 1 or byte 2,
+   * making the captured preamble either 7 or 6 bytes in length. If the
+   * preamble starts with 0x55, then /S/ happened in byte 1, making the
+   * captured preamble 7 bytes in length.
+   */
+  if (tvb_get_ntoh24(tvb, 0) == 0x55D555) {
+    offset += 1;
+  } else if (tvb_get_ntohs(tvb, 0) == 0xD555) {
+    offset += 0;
+  } else {
+    item = proto_tree_add_item(tree, proto_epon, tvb, offset, 0, ENC_NA);
+    expert_add_info(pinfo, item, &ei_epon_sld_bad);
+    return 0;
+  }
+
+  /* Set the columns */
+  col_set_str(pinfo->cinfo, COL_PROTOCOL, "EPON");
+  col_set_str(pinfo->cinfo, COL_INFO, "EPON Preamble");
+
+  /* Create display subtree for the protocol */
+  ti = proto_tree_add_item(tree, proto_epon, tvb, 0+offset, 6, ENC_NA);
+  epon_tree = proto_item_add_subtree(ti, ett_epon);
+
+  /* Decode byte 5 of the preamble according to CableLabs DPoE specification.
+   * If security is disabled, the DPoE byte will remain 0x55 and no decoding
+   * is necessary.
+   */
+  dpoe_sec_byte = tvb_get_guint8(tvb, 2+offset);
+  if (dpoe_sec_byte != 0x55) {
+    guint       dpoe_keyid;
+    guint       dpoe_reserved;
+
+    item = proto_tree_add_item(epon_tree, hf_epon_dpoe_security,
+                               tvb, 2+offset, 1, ENC_NA);
+    sec_tree = proto_item_add_subtree(item, ett_epon_sec);
+
+    /* The DPoE security byte is split into three fields:
+     * bits 7-2 are reserved in 1G mode
+     * bit 1 is the encryption mode
+     * bit 0 is the key ID
+     */
+    dpoe_reserved = dpoe_sec_byte & 0xFC;
+    dpoe_encrypted = dpoe_sec_byte & 0x02;
+    dpoe_keyid = dpoe_sec_byte & 0x01;
+
+    /* Add encryption status text to sec_tree subtree
+     */
+    proto_item_append_text(item, " (Encrypted: ");
+    if (dpoe_encrypted) {
+      proto_item_append_text(item, "True, Key ID: %x", dpoe_keyid);
+    } else {
+      proto_item_append_text(item, "False");
+    }
+    proto_item_append_text(item, ")");
+
+    /* We don't need to see the reserved bits of the DPoE security byte unless
+     * there's something wrong with them.
+     */
+    if (dpoe_reserved != 0x54) {
+      proto_tree_add_item(sec_tree, hf_epon_dpoe_reserved, tvb, 2+offset, 1,
+                          ENC_BIG_ENDIAN);
+      expert_add_info(pinfo, sec_tree, &ei_epon_dpoe_reserved_bad);
+    }
+
+    /* Add encryption and key ID bits
+     * Error if encryption is disabled but key bit is not 1
+     */
+    proto_tree_add_item(sec_tree, hf_epon_dpoe_encrypted, tvb, 2+offset, 1,
+                        ENC_BIG_ENDIAN);
+    proto_tree_add_item(sec_tree, hf_epon_dpoe_keyid, tvb, 2+offset, 1,
+                        ENC_BIG_ENDIAN);
+    if (!dpoe_encrypted && (dpoe_keyid == 0)) {
+      expert_add_info(pinfo, sec_tree, &ei_epon_dpoe_bad);
+    }
+
+  }
+
+  /* Mode bit
+   */
+  proto_tree_add_item(epon_tree, hf_epon_mode, tvb, 3+offset, 2,
+                      ENC_BIG_ENDIAN);
+
+  /* LLID
+   */
+  proto_tree_add_item(epon_tree, hf_epon_llid, tvb, 3+offset, 2,
+                      ENC_BIG_ENDIAN);
+
+  /* Verify the CRC-8 checksum
+   */
+  sent_checksum = tvb_get_guint8(tvb, 5+offset);
+  checksum = get_crc8_ieee8023_epon(tvb, 5, 0+offset);
+
+  if (sent_checksum == checksum) {
+    proto_tree_add_uint_format_value(epon_tree, hf_epon_checksum, tvb,
+                                     5+offset, 1, sent_checksum,
+                                     "0x%01x [correct]", sent_checksum);
+  } else {
+    item = proto_tree_add_uint_format_value(epon_tree, hf_epon_checksum, tvb,
+                                            5+offset, 1, sent_checksum,
+                                            "0x%01x [incorrect, should be 0x%01x]",
+                                            sent_checksum, checksum);
+    expert_add_info(pinfo, item, &ei_epon_checksum_bad);
+    col_append_str(pinfo->cinfo, COL_INFO, " [EPON PREAMBLE CHECKSUM INCORRECT]");
+  }
+
+  /* Do not bother parsing encrypted data, otherwise send the rest on to the
+   * eth dissector.
+   */
+  if (dpoe_encrypted) {
+    item = proto_tree_add_item(tree, hf_epon_dpoe_encrypted_data, tvb,
+                               6+offset, -1, ENC_NA);
+    expert_add_info(pinfo, item, &ei_epon_dpoe_encrypted_data);
+    col_append_str(pinfo->cinfo, COL_INFO, " [ENCRYPTED]");
+  } else {
+    next_tvb = tvb_new_subset_remaining(tvb, 6+offset);
+    call_dissector(eth_handle, next_tvb, pinfo, tree);
+  }
+
+  return tvb_captured_length(tvb);
+}
+
+void
+proto_register_epon(void)
+{
+  expert_module_t *expert_epon;
+
+  static hf_register_info hf[] = {
+    { &hf_epon_dpoe_security,
+      { "DPoE security", "epon.dpoe.sec", FT_UINT8, BASE_HEX, NULL, 0x0,
+        "DPoE security octet", HFILL }
+    },
+    { &hf_epon_dpoe_reserved,
+      { "Reserved", "epon.dpoe.reserved", FT_UINT8, BASE_DEC, NULL, 0xFC,
+        "Reserved in 1G mode", HFILL }
+    },
+    { &hf_epon_dpoe_encrypted,
+      { "Encryption enabled", "epon.dpoe.encrypted", FT_BOOLEAN, 8, NULL, 0x02,
+        "Specifies if this is an encrypted frame", HFILL }
+    },
+    { &hf_epon_dpoe_keyid,
+      { "Key ID", "epon.dpoe.keyid", FT_UINT8, BASE_HEX, NULL, 0x01,
+        "Identification number of the key used to encrypt this frame",
+        HFILL }
+    },
+    { &hf_epon_dpoe_encrypted_data,
+      { "Encrypted data", "epon.dpoe.encrypted.data", FT_BYTES, BASE_NONE,
+        NULL, 0x0, "DPoE encrypted data", HFILL }
+    },
+    { &hf_epon_mode,
+      { "Mode", "epon.mode", FT_BOOLEAN, 16, TFS(&epon_mode_tfs), 0x8000,
+        "Broadcast/multicast if true, unicast if false", HFILL }
+    },
+    { &hf_epon_llid,
+      { "LLID", "epon.llid", FT_UINT16, BASE_DEC_HEX, NULL, 0x7FFF,
+        "Logical Link ID", HFILL }
+    },
+    { &hf_epon_checksum,
+      { "Frame check sequence", "epon.checksum", FT_UINT8, BASE_HEX, NULL,
+        0x0, "EPON preamble checksum", HFILL }
+    },
+  };
+
+  static gint *ett[] = {
+    &ett_epon,
+    &ett_epon_sec,
+    &ett_epon_checksum
+  };
+
+  /* Setup protocol expert items */
+  static ei_register_info ei[] = {
+    { &ei_epon_checksum_bad,
+      { "epon.checksum_bad.expert", PI_CHECKSUM, PI_ERROR,
+        "Bad checksum", EXPFILL }
+    },
+    { &ei_epon_sld_bad,
+      { "epon.sld_bad.expert", PI_MALFORMED, PI_ERROR,
+        "Unable to locate SLD or invalid byte sequence: preamble must start with 0xD555", EXPFILL }
+    },
+    { &ei_epon_dpoe_reserved_bad,
+      { "epon.dpoe.encrypted.expert", PI_MALFORMED, PI_ERROR,
+        "Bits 7-2 of DPoE security byte must be 010101 in 1G mode.", EXPFILL }
+    },
+    { &ei_epon_dpoe_bad,
+      { "epon.dpoe.expert", PI_MALFORMED, PI_ERROR,
+        "DPoE security byte must be 0x55 if encrypton is disabled.", EXPFILL }
+    },
+    { &ei_epon_dpoe_encrypted_data,
+      { "epon.dpoe.encrypted.expert", PI_UNDECODED, PI_NOTE,
+        "Remaining data is encrypted and will not decode.", EXPFILL }
+    }
+  };
+
+  proto_epon = proto_register_protocol("IEEE 802.3 EPON Preamble",
+                                       "EPON", "epon");
+
+  proto_register_field_array(proto_epon, hf, array_length(hf));
+  proto_register_subtree_array(ett, array_length(ett));
+
+  expert_epon = expert_register_protocol(proto_epon);
+  expert_register_field_array(expert_epon, ei, array_length(ei));
+
+}
+
+void
+proto_reg_handoff_epon(void)
+{
+  dissector_handle_t epon_handle;
+
+  epon_handle = new_create_dissector_handle(dissect_epon, proto_epon);
+  dissector_add_uint("wtap_encap", WTAP_ENCAP_EPON, epon_handle);
+
+  eth_handle = find_dissector("eth");
+}
index a53fb47e670b971b899c1f3ef26d00692476aa80..77dd9f3d93f6db5c41012c5f3a386f5378bcf703 100644 (file)
@@ -427,7 +427,10 @@ static const struct {
        /* Apple PKTAP */
        { 258,          WTAP_ENCAP_PKTAP },
 
-       /*
+       /* Ethernet Passive Optical Network */
+       { 259,          WTAP_ENCAP_EPON },
+
+  /*
         * To repeat:
         *
         * If you need a new encapsulation type for libpcap files, do
index 343a9b23c4e8e3847591415533716dd1f7ae2767..403734706c18ce474c87f85ac1e481d4be1a7239 100644 (file)
@@ -732,6 +732,9 @@ static struct encap_type_info encap_table_base[] = {
 
        /* WTAP_ENCAP_PKTAP */
        { "Apple PKTAP", "pktap" },
+
+       /* WTAP_ENCAP_EPON */
+       { "Ethernet Passive Optical Network", "epon" },
 };
 
 WS_DLL_LOCAL
index 4b2f98112861a7354f7e734ccf4a55497a263fb2..ea8c3d132ef3b1d0c8326ec5a67122b576e8b8ce 100644 (file)
@@ -263,6 +263,7 @@ extern "C" {
 #define WTAP_ENCAP_LOGCAT_THREADTIME            170
 #define WTAP_ENCAP_LOGCAT_LONG                  171
 #define WTAP_ENCAP_PKTAP                        172
+#define WTAP_ENCAP_EPON                         173
 /* 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()