From Francesco Fondelli:
authorjake <jake@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 13 Jul 2008 17:19:33 +0000 (17:19 +0000)
committerjake <jake@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 13 Jul 2008 17:19:33 +0000 (17:19 +0000)
Attached is a patch for:
- PW Associated Channel Header dissection as per RFC 4385
- PW MPLS Control Word dissection as per RFC 4385
- mpls subdissector table indexed by label value
- enhanced "what's past last mpls label?" heuristic
- Ethernet PW (w/o CW) support as per RFC 4448

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@25730 f5534014-38df-0310-8fa8-9805f1628bb7

AUTHORS
epan/dissectors/packet-mpls.c
epan/dissectors/packet-mpls.h
epan/dissectors/packet-pw-eth.c [new file with mode: 0644]
epan/packet.c
epan/packet_info.h
gtk/decode_as_dlg.c

diff --git a/AUTHORS b/AUTHORS
index d6af84a1143b6741e4a657d8b8d357a1e3c8e658..51a37ecec4dd6eb63d1df089a2c2b0c2e50e802b 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -2296,6 +2296,11 @@ Francesco Fondelli       <francesco.fondelli [AT] gmail.com> {
        Linux Packet Generator support
        rval_to_str() and alike
        Export the capture file into C Arrays format
+       PW Associated Channel Header dissection as per RFC 4385
+       PW MPLS Control Word dissection as per RFC 4385
+       mpls subdissector table indexed by label value
+       enhanced "what's past last mpls label?" heuristic
+       Ethernet PW (w/o CW) support as per RFC 4448
 }
 
 Bill Meier             <wmeier [AT] newsguy.com> {
index 69398c5a53128fcd92efd73d3f46bfdb2f2b5d08..705de9ea00653fb2cea3ed877a277fbffff84d9b 100644 (file)
@@ -5,7 +5,11 @@
  * (c) Copyright Ashok Narayanan <ashokn@cisco.com>
  *
  * (c) Copyright 2006, _FF_ Francesco Fondelli <francesco.fondelli@gmail.com>  
- *                     added MPLS OAM support, ITU-T Y.1711
+ *     - added MPLS OAM support, ITU-T Y.1711
+ *     - PW Associated Channel Header dissection as per RFC 4385
+ *     - PW MPLS Control Word dissection as per RFC 4385
+ *     - mpls subdissector table indexed by label value
+ *     - enhanced "what's past last mpls label?" heuristic
  *
  * $Id$
  *
 #include <epan/etypes.h>
 #include <epan/prefs.h>
 #include <epan/ipproto.h>
+#include <epan/addr_resolv.h>
 #include "packet-ppp.h"
 #include "packet-mpls.h"
 
 static gint proto_mpls = -1;
+static gint proto_pw_ach = -1;
+static gint proto_pw_mcw = -1;
 
 static gint ett_mpls = -1;
-static gint ett_mpls_control = -1;
+static gint ett_mpls_pw_ach = -1;
+static gint ett_mpls_pw_mcw = -1;
 static gint ett_mpls_oam = -1;
 
 const value_string special_labels[] = {
@@ -71,10 +79,6 @@ const value_string special_labels[] = {
 
 /* MPLS filter values */
 enum mpls_filter_keys {
-
-    /* Is the packet MPLS-encapsulated? */
-/*    MPLSF_PACKET,*/
-
     /* MPLS encap properties */
     MPLSF_LABEL,
     MPLSF_EXP,
@@ -85,8 +89,16 @@ enum mpls_filter_keys {
 };
 
 static int mpls_filter[MPLSF_MAX];
-static int hf_mpls_control_control = -1;
-static int hf_mpls_control_res = -1;
+
+static int hf_mpls_1st_nibble = -1;
+
+static int hf_mpls_pw_ach_ver = -1;
+static int hf_mpls_pw_ach_res = -1;
+static int hf_mpls_pw_ach_channel_type = -1;
+
+static int hf_mpls_pw_mcw_flags = -1;
+static int hf_mpls_pw_mcw_length = -1;
+static int hf_mpls_pw_mcw_sequence_number = -1;
 
 static int hf_mpls_oam_function_type = -1;
 static int hf_mpls_oam_ttsi = -1;
@@ -134,10 +146,7 @@ static const value_string oam_defect_type_vals[] = {
 
 static hf_register_info mplsf_info[] = {
 
-/*    {&mpls_filter[MPLSF_PACKET],
-     {"MPLS Label Switched Packet", "mpls", FT_UINT8, BASE_DEC, NULL, 0x0,
-      "", HFILL }},*/
-
+    /* MPLS header fields */
     {&mpls_filter[MPLSF_LABEL],
      {"MPLS Label", "mpls.label", FT_UINT32, BASE_DEC, VALS(special_labels), 0x0,
       "", HFILL }},
@@ -154,13 +163,39 @@ static hf_register_info mplsf_info[] = {
      {"MPLS TTL", "mpls.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
       "", HFILL }},
 
-    {&hf_mpls_control_control,
-     {"MPLS Control Channel", "mpls.cw.control", FT_UINT8, BASE_DEC, NULL, 0xF0,
-      "First nibble", HFILL }},
+    /* 1st nibble */
+     {&hf_mpls_1st_nibble,
+     {"MPLS 1st nibble", "mpls.1st_nibble", FT_UINT8, 
+       BASE_DEC, NULL, 0x0, "MPLS 1st nibble", HFILL }},
+
+    /* PW Associated Channel Header fields */
+    {&hf_mpls_pw_ach_ver,
+     {"PW Associated Channel Version", "pwach.ver", FT_UINT8, BASE_DEC, 
+      NULL, 0x0, "PW Associated Channel Version", HFILL }},
+
+    {&hf_mpls_pw_ach_res,
+     {"Reserved", "pwach.res", FT_UINT8, BASE_DEC, 
+      NULL, 0x0, "Reserved", HFILL }},
+
+    {&hf_mpls_pw_ach_channel_type,
+     {"PW Associated Channel Type", "pwach.channel_type", FT_UINT16, BASE_HEX, 
+      NULL, 0x0, "PW Associated Channel Type", HFILL }},
+
+    /* Generic/Preferred PW MPLS Control Word fields */
+    {&hf_mpls_pw_mcw_flags,
+     {"Generic/Preferred PW MPLS Control Word Flags", "pwmcw.flags", FT_UINT8,
+      BASE_HEX, NULL, 0x0, "Generic/Preferred PW MPLS Control Word Flags", 
+      HFILL }},
+
+    {&hf_mpls_pw_mcw_length,
+     {"Generic/Preferred PW MPLS Control Word Length", "pwmcw.length", FT_UINT8,
+      BASE_DEC, NULL, 0x0, "Generic/Preferred PW MPLS Control Word Length", 
+      HFILL }},
 
-    {&hf_mpls_control_res,
-     {"Reserved", "mpls.cw.res", FT_UINT16, BASE_HEX, NULL, 0xFFF, 
-      "Reserved", HFILL }},
+    {&hf_mpls_pw_mcw_sequence_number,
+     {"Generic/Preferred PW MPLS Control Word Sequence Number",
+      "pwmcw.sequence_number", FT_UINT16, BASE_DEC, NULL, 0x0,
+      "Generic/Preferred PW MPLS Control Word Sequence Number", HFILL }},
 
     /* OAM header fields */
     {&hf_mpls_oam_function_type,
@@ -193,6 +228,7 @@ static dissector_handle_t ipv6_handle;
 static dissector_handle_t eth_withoutfcs_handle;
 static dissector_handle_t data_handle;
 static dissector_table_t ppp_subdissector_table;
+static dissector_table_t mpls_subdissector_table;
 
 /*
  * Given a 4-byte MPLS label starting at offset "offset", in tvbuff "tvb",
@@ -214,43 +250,93 @@ void decode_mpls_label(tvbuff_t *tvb, int offset,
     *ttl = tvb_get_guint8(tvb, offset+3);
 }
 
+/*
+ * FF: PW Associated Channel Header dissection as per RFC 4385.
+ */
 static void
-dissect_mpls_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+dissect_pw_ach(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
-    proto_tree  *mpls_control_tree = NULL;
-    proto_item  *ti;
-    tvbuff_t    *next_tvb;
-    guint8      ctrl;
-    guint16     res, ppp_proto;
+    proto_tree  *mpls_pw_ach_tree = NULL;
+    proto_item  *ti = NULL;
+    tvbuff_t    *next_tvb = NULL;
+    guint8      ver = 0;
+    guint16     res = 0;
+    guint16     channel_type = 0;
 
-    if (tvb_reported_length_remaining(tvb, 0) < 4){
-        if(tree)
+    if (tvb_reported_length_remaining(tvb, 0) < 4) {
+        if (tree)
             proto_tree_add_text(tree, tvb, 0, -1, "Error processing Message");
         return;
     }
-    ctrl = (tvb_get_guint8(tvb, 0) & 0xF0) >> 4;
-    res = tvb_get_ntohs(tvb, 0) & 0x0FFF;
-    ppp_proto = tvb_get_ntohs(tvb, 2);
+    ver = (tvb_get_guint8(tvb, 0) & 0x0F);
+    res = tvb_get_guint8(tvb, 1);
+    channel_type = tvb_get_ntohs(tvb, 2);
     if (tree) {
-        ti = proto_tree_add_text(tree, tvb, 0, 4, "MPLS PW Control Channel Header");
-        mpls_control_tree = proto_item_add_subtree(ti, ett_mpls_control);
-        if(mpls_control_tree == NULL) return;
-
-        proto_tree_add_uint_format(mpls_control_tree, hf_mpls_control_control, tvb, 0, 1,
-            ctrl, "Control Channel: 0x%1x", ctrl);
-        proto_tree_add_uint_format(mpls_control_tree, hf_mpls_control_res, tvb, 0, 2,
-            res, "Reserved: 0x%03x", res);
-        proto_tree_add_text(mpls_control_tree, tvb, 2, 2,
-            "PPP DLL Protocol Number: %s (0x%04X)", 
-                val_to_str(ppp_proto, ppp_vals, "Unknown"), ppp_proto);
+        ti = proto_tree_add_item(tree, proto_pw_ach, tvb, 0, 4, FALSE);
+        mpls_pw_ach_tree = proto_item_add_subtree(ti, ett_mpls_pw_ach);
+        if (mpls_pw_ach_tree == NULL)
+            return;
+        proto_tree_add_uint_format(mpls_pw_ach_tree, hf_mpls_pw_ach_ver,
+                                   tvb, 0, 1, ver, "Version: %d", ver);
+        ti = proto_tree_add_uint_format(mpls_pw_ach_tree, hf_mpls_pw_ach_res,
+                                        tvb, 1, 1, res, "Reserved: 0x%02x", res);
+        PROTO_ITEM_SET_HIDDEN(ti);
+        if (res != 0)
+            proto_tree_add_text(mpls_pw_ach_tree, tvb, 1, 1,
+                "Error: this byte is reserved and must be 0");
+        proto_tree_add_uint_format(mpls_pw_ach_tree, hf_mpls_pw_ach_channel_type,
+                                   tvb, 2, 2, channel_type,
+                                   "Channel Type: %s (0x%04x)",
+                                   val_to_str(channel_type, ppp_vals, "Unknown"),
+                                              channel_type);
     }
     next_tvb = tvb_new_subset(tvb, 4, -1, -1);
-    if (!dissector_try_port(ppp_subdissector_table, ppp_proto
-        next_tvb, pinfo, tree)) {
+    if (!dissector_try_port(ppp_subdissector_table, channel_type
+                            next_tvb, pinfo, tree)) {
             call_dissector(data_handle, next_tvb, pinfo, tree);
     }
+}
 
-
+/*
+ * FF: Generic/Preferred PW MPLS Control Word dissection as per RFC 4385.
+ */
+static void
+dissect_pw_mcw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+    proto_tree  *mpls_pw_mcw_tree = NULL;
+    proto_item  *ti = NULL;
+    tvbuff_t    *next_tvb = NULL;
+    guint8      flags = 0;
+    guint8      frg = 0;
+    guint8      length = 0;
+    guint16     sequence_number = 0;
+
+    if (tvb_reported_length_remaining(tvb, 0) < 4) {
+        if (tree)
+            proto_tree_add_text(tree, tvb, 0, -1, "Error processing Message");
+        return;
+    }
+    /* bits 4 to 7 and FRG bits are displayed together */
+    flags = (tvb_get_guint8(tvb, 0) & 0x0F) << 2;
+    frg = (tvb_get_guint8(tvb, 1) & 0xC0) >> 6;
+    flags |= frg;
+    length = tvb_get_guint8(tvb, 1) & 0x3F;
+    sequence_number = tvb_get_ntohs(tvb, 2);
+    if (tree) {
+        ti = proto_tree_add_item(tree, proto_pw_mcw, tvb, 0, 4, FALSE);
+        mpls_pw_mcw_tree = proto_item_add_subtree(ti, ett_mpls_pw_mcw);
+        if (mpls_pw_mcw_tree == NULL)
+            return;
+        proto_tree_add_uint_format(mpls_pw_mcw_tree, hf_mpls_pw_mcw_flags,
+                                   tvb, 0, 1, flags, "Flags: 0x%02x", flags);
+        ti = proto_tree_add_uint_format(mpls_pw_mcw_tree, hf_mpls_pw_mcw_length,
+                                        tvb, 1, 1, length, "Length: %u", length);
+        proto_tree_add_uint_format(mpls_pw_mcw_tree, hf_mpls_pw_mcw_sequence_number,
+                                   tvb, 2, 2, sequence_number,
+                                   "Sequence Number: %d", sequence_number);
+    }
+    next_tvb = tvb_new_subset(tvb, 4, -1, -1);
+    call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree);
 }
 
 static void
@@ -460,7 +546,30 @@ dissect_mpls_oam_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_
     proto_tree_add_item(mpls_oam_tree, hf_mpls_oam_bip16, tvb, offset, 2, TRUE);
     offset+=2;
 }
-    
+
+/* 
+ * FF: this function returns TRUE if the first 12 bytes in tvb looks like
+ *     two valid ethernet addresses.  FALSE otherwise. 
+ */
+static gboolean
+looks_like_plain_eth(tvbuff_t *tvb _U_)
+{
+    const gchar *manuf_name_da = NULL;
+    const gchar *manuf_name_sa = NULL;
+
+    if (tvb_reported_length_remaining(tvb, 0) < 14) {
+        return FALSE;
+    }
+
+    manuf_name_da = get_manuf_name_if_known(tvb_get_ptr(tvb, 0, 6));
+    manuf_name_sa = get_manuf_name_if_known(tvb_get_ptr(tvb, 6, 6));
+
+    if (manuf_name_da && manuf_name_sa) {
+        return TRUE;
+    }
+
+    return FALSE;
+}
 
 static void
 dissect_mpls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
@@ -470,7 +579,7 @@ dissect_mpls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     guint8 exp;
     guint8 bos;
     guint8 ttl;
-    guint8 ipvers;
+    guint8 nibble;
 
     proto_tree  *mpls_tree = NULL;
     proto_item  *ti;
@@ -488,7 +597,8 @@ dissect_mpls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     while (tvb_reported_length_remaining(tvb, offset) > 0) {
        
        decode_mpls_label(tvb, offset, &label, &exp, &bos, &ttl);
-               
+       pinfo->mpls_label = label;
+       
        if (tree) {
 
            ti = proto_tree_add_item(tree, proto_mpls, tvb, offset, 4, FALSE);
@@ -531,17 +641,34 @@ dissect_mpls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        offset += 4;
        if (bos) break;
     }
+
+    nibble = (tvb_get_guint8(tvb, offset) >> 4) & 0x0F;
+    ti = proto_tree_add_uint(mpls_tree, hf_mpls_1st_nibble, tvb, offset, 1, nibble);
+    PROTO_ITEM_SET_HIDDEN(ti);
+
     next_tvb = tvb_new_subset(tvb, offset, -1, -1);
 
-    ipvers = (tvb_get_guint8(tvb, offset) >> 4) & 0x0F;
-    if (ipvers == 6) {
-      call_dissector(ipv6_handle, next_tvb, pinfo, tree);
-    } else if (ipvers == 4) {
-      call_dissector(ipv4_handle, next_tvb, pinfo, tree);
-    } else if (ipvers == 1) {
-      dissect_mpls_control(next_tvb, pinfo, tree);
-    } else {
-      call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree);
+    if (!dissector_try_port(mpls_subdissector_table, label,
+                             next_tvb, pinfo, tree)) {
+        if (nibble == 6) {
+           call_dissector(ipv6_handle, next_tvb, pinfo, tree);
+        } else if (nibble == 4) {
+           call_dissector(ipv4_handle, next_tvb, pinfo, tree);
+        } else if (nibble == 1) {
+           dissect_pw_ach(next_tvb, pinfo, tree);
+        } else if (nibble == 0) {
+           if (looks_like_plain_eth(next_tvb)) {
+               call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree);
+           } else {
+               dissect_pw_mcw(next_tvb, pinfo, tree);
+           }
+        } else {
+               /*
+                * FF: no external hint, 1st nibble is not 6, 4, 1 or 0... 
+                * good luck!
+                */
+               call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree);
+        }
     }
 }
 
@@ -550,12 +677,21 @@ proto_register_mpls(void)
 {
        static gint *ett[] = {
                &ett_mpls,
-                &ett_mpls_control,
+               &ett_mpls_pw_ach,
+               &ett_mpls_pw_mcw,
                &ett_mpls_oam,
        };
 
+       /* FF: mpls subdissector table is indexed by label */
+       mpls_subdissector_table = register_dissector_table("mpls.label",
+                                                           "MPLS protocol", 
+                                                           FT_UINT32, BASE_DEC);
        proto_mpls = proto_register_protocol("MultiProtocol Label Switching Header",
-           "MPLS", "mpls");
+                                             "MPLS", "mpls");
+       proto_pw_ach = proto_register_protocol("PW Associated Channel Header",
+                                               "PWACH", "pwach");
+       proto_pw_mcw = proto_register_protocol("PW MPLS Control Word (generic/preferred)",
+                                               "PWMCW", "pwmcw");
        proto_register_field_array(proto_mpls, mplsf_info, array_length(mplsf_info));
        proto_register_subtree_array(ett, array_length(ett));
        register_dissector("mpls", dissect_mpls, proto_mpls);
@@ -575,7 +711,6 @@ proto_reg_handoff_mpls(void)
         data_handle = find_dissector("data");
         ppp_subdissector_table = find_dissector_table("ppp.protocol");
 
-
        mpls_handle = create_dissector_handle(dissect_mpls, proto_mpls);
        dissector_add("ethertype", ETHERTYPE_MPLS, mpls_handle);
        dissector_add("ethertype", ETHERTYPE_MPLS_MULTI, mpls_handle);
@@ -585,5 +720,5 @@ proto_reg_handoff_mpls(void)
        dissector_add("chdlctype", ETHERTYPE_MPLS_MULTI, mpls_handle);
        dissector_add("gre.proto", ETHERTYPE_MPLS, mpls_handle);
        dissector_add("gre.proto", ETHERTYPE_MPLS_MULTI, mpls_handle);
-    dissector_add("ip.proto", IP_PROTO_MPLS_IN_IP, mpls_handle);
+       dissector_add("ip.proto", IP_PROTO_MPLS_IN_IP, mpls_handle);
 }
index d52fb70462c35b2f53151aecf65f05255d37bce3..c328f529274d26e199b07f0750357fa8ce149dd6 100644 (file)
@@ -37,7 +37,8 @@ enum {
     LABEL_IP6_EXPLICIT_NULL,
     LABEL_IMPLICIT_NULL,
     LABEL_OAM_ALERT = 14,
-    LABEL_MAX_RESERVED = 15
+    LABEL_MAX_RESERVED = 15,
+    LABEL_INVALID = 0xffffffff
 };
 
 extern const value_string special_labels[];
diff --git a/epan/dissectors/packet-pw-eth.c b/epan/dissectors/packet-pw-eth.c
new file mode 100644 (file)
index 0000000..941c771
--- /dev/null
@@ -0,0 +1,159 @@
+/* packet-pw-eth.c
+ * Routines for ethernet PW dissection:
+ * it should be conformance to RFC 4448.
+ *
+ * Copyright 2008 _FF_
+ *
+ * Francesco Fondelli <francesco dot fondelli, gmail dot com>
+ *
+ * $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.
+ */
+
+#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 <epan/prefs.h>
+
+#include "packet-mpls.h"
+
+static gint proto_pw_eth = -1;
+static gint proto_pw_eth_nocw = -1;
+
+static gint ett_pw_eth = -1;
+
+static int hf_pw_eth = -1;
+static int hf_pw_eth_cw = -1;
+static int hf_pw_eth_cw_sequence_number = -1;
+
+static hf_register_info hf[] = {
+       {
+               &hf_pw_eth,
+               {
+                       "PW (ethernet)", 
+                       "pweth", FT_BOOLEAN, 
+                       0, NULL, 0x0, NULL, HFILL
+               }
+       },
+       {
+               &hf_pw_eth_cw,
+               {
+                       "PW Control Word (ethernet)", 
+                       "pweth.cw", FT_BOOLEAN, 
+                       0, NULL, 0x0, NULL, HFILL
+               }
+       },
+       {
+               &hf_pw_eth_cw_sequence_number,
+               {
+                       "PW sequence number (ethernet)", 
+                       "pweth.cw.sequence_number", FT_UINT16, 
+                       BASE_DEC, NULL, 0x0, NULL, HFILL
+               }
+       }
+};
+
+static gint *ett[] = {
+       &ett_pw_eth
+};
+
+static dissector_handle_t eth_withoutfcs_handle;
+
+static void
+dissect_pw_eth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+       proto_tree *pw_eth_tree = NULL;
+       proto_item *ti = NULL;
+       tvbuff_t *next_tvb = NULL;
+       guint16 sequence_number = 0;
+       
+       if (tvb_reported_length_remaining(tvb, 0) < 4) {
+               if (tree)
+                       proto_tree_add_text(tree, tvb, 0, -1, 
+                                           "Error processing Message");
+               return;
+       }
+       sequence_number = tvb_get_ntohs(tvb, 2);
+       if (tree) {
+               ti = proto_tree_add_boolean(tree, hf_pw_eth_cw, tvb, 0, 0, TRUE);
+               PROTO_ITEM_SET_HIDDEN(ti);
+               ti = proto_tree_add_item(tree, proto_pw_eth, tvb, 0, 4, FALSE);
+               pw_eth_tree = proto_item_add_subtree(ti, ett_pw_eth);
+               if (pw_eth_tree == NULL)
+                       return;
+               proto_tree_add_uint_format(pw_eth_tree, 
+                                          hf_pw_eth_cw_sequence_number,
+                                          tvb, 2, 2, sequence_number,
+                                          "Sequence Number: %d", 
+                                          sequence_number);
+       }
+       next_tvb = tvb_new_subset(tvb, 4, -1, -1);
+       call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree);
+}
+
+static void
+dissect_pw_eth_nocw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+       tvbuff_t *next_tvb = NULL;
+       proto_item *ti = NULL;
+
+       if (tree) {
+               ti = proto_tree_add_boolean(tree, hf_pw_eth, tvb, 0, 0, TRUE);
+               PROTO_ITEM_SET_HIDDEN(ti);
+       }
+       next_tvb = tvb_new_subset(tvb, 0, -1, -1);
+       call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree);
+}
+
+void
+proto_register_pw_eth(void)
+{
+       proto_pw_eth = proto_register_protocol("PW Control Word (ethernet)",
+                                               "PWETH", "pweth");
+       proto_pw_eth_nocw = proto_register_protocol("PW (ethernet)",
+                                                   "PWETH (no CW)", 
+                                                   "");
+       proto_register_field_array(proto_pw_eth, hf, array_length(hf));
+       proto_register_subtree_array(ett, array_length(ett));
+       register_dissector("pw_eth", dissect_pw_eth, proto_pw_eth);
+       register_dissector("pw_eth_nocw", dissect_pw_eth_nocw, 
+                          proto_pw_eth_nocw);
+}
+
+void
+proto_reg_handoff_pw_eth(void)
+{
+       dissector_handle_t pw_eth_handle;
+       dissector_handle_t pw_eth_handle_nocw;
+
+       eth_withoutfcs_handle = find_dissector("eth_withoutfcs");
+
+       pw_eth_handle = create_dissector_handle(dissect_pw_eth, proto_pw_eth);
+       dissector_add("mpls.label", LABEL_INVALID, pw_eth_handle);
+       pw_eth_handle_nocw = create_dissector_handle(dissect_pw_eth_nocw, 
+                                                    proto_pw_eth_nocw);
+       dissector_add("mpls.label", LABEL_INVALID, pw_eth_handle_nocw);
+}
index 1bdcfc39a512d1e2e56a0d82e274902912327a9e..07c93b2cb779d6fe534117cbc1f2a71841b25dab 100644 (file)
@@ -279,6 +279,7 @@ dissect_packet(epan_dissect_t *edt, union wtap_pseudo_header *pseudo_header,
        edt->pi.dst.len = 0;
        edt->pi.dst.data = NULL;
        edt->pi.ethertype = 0;
+       edt->pi.mpls_label = 0;
        edt->pi.ipproto  = 0;
        edt->pi.ipxptype = 0;
        edt->pi.ctype = CT_NONE;
index 6e6a1ae465ef334a8653b7dbcbf4b1c699c5d597..eb963b6532ba882610d4b2ecfa857d29ec5d7f23 100644 (file)
@@ -54,6 +54,7 @@ typedef struct _packet_info {
   guint32 ethertype;           /* Ethernet Type Code, if this is an Ethernet packet */
   guint32 ipproto;             /* IP protocol, if this is an IP packet */
   guint32 ipxptype;            /* IPX packet type, if this is an IPX packet */
+  guint32 mpls_label;          /* last mpls label in label stack, if this is a MPLS packet */
   circuit_type ctype;          /* type of circuit, for protocols with a VC identifier */
   guint32 circuit_id;          /* circuit ID, for protocols with a VC identifier */
   const char *noreassembly_reason;  /* reason why reassembly wasn't done, if any */
index 9d003d31606c8612d9f519aaa659ce9f9d50c48d..a88ac8ce9a2446f97fa4437c9b1064bb803d36a9 100644 (file)
@@ -1640,6 +1640,14 @@ decode_add_notebook (GtkWidget *format_hb)
        gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
     }
 
+    /* Add mpls selection page */
+    if (cfile.edt->pi.mpls_label) {
+       g_snprintf(buffer, 40, "Data after label %u", cfile.edt->pi.mpls_label);
+       page = decode_add_simple_page(buffer, "MPLS", "mpls.label", cfile.edt->pi.mpls_label);
+       label = gtk_label_new("MPLS");
+       gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
+    }
+
     /* Add network selection page */
     if (cfile.edt->pi.ipproto) {
        /*