Show unknown AFP command codes in decimal in the summary line, as we
[obnox/wireshark/wip.git] / packet-mpls.c
index cef22a446af982f791fa6646a0eea5c41d5a44d1..a036cefdbb69fcf3ab83771307c6c43365d23949 100644 (file)
@@ -3,12 +3,11 @@
  * 
  * (c) Copyright Ashok Narayanan <ashokn@cisco.com>
  *
- * $Id: packet-mpls.c,v 1.13 2001/01/03 06:55:30 guy Exp $
+ * $Id: packet-mpls.c,v 1.26 2002/03/18 18:56:53 guy Exp $
  *
  * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@zing.org>
+ * By Gerald Combs <gerald@ethereal.com>
  * 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
 #endif
 
 #include <glib.h>
-#include "etypes.h"
-#include "packet.h"
-#include "packet-ip.h"
+#include <epan/packet.h>
 #include "ppptypes.h"
-#include "packet-ppp.h"
+#include "etypes.h"
 
 static gint proto_mpls = -1;
 
@@ -90,98 +87,110 @@ static int mpls_filter[MPLSF_MAX];
 static hf_register_info mplsf_info[] = {
 
 /*    {&mpls_filter[MPLSF_PACKET], 
-     {"MPLS Label Switched Packet", "mpls", FT_UINT8, BASE_NONE, NULL, 0x0, 
-      "" }},*/
+     {"MPLS Label Switched Packet", "mpls", FT_UINT8, BASE_DEC, NULL, 0x0, 
+      "", HFILL }},*/
 
     {&mpls_filter[MPLSF_LABEL], 
      {"MPLS Label", "mpls.label", FT_UINT32, BASE_DEC, VALS(special_labels), 0x0, 
-      "" }},
+      "", HFILL }},
 
     {&mpls_filter[MPLSF_EXP], 
      {"MPLS Experimental Bits", "mpls.exp", FT_UINT8, BASE_DEC, NULL, 0x0, 
-      "" }},
+      "", HFILL }},
 
     {&mpls_filter[MPLSF_BOTTOM_OF_STACK], 
      {"MPLS Bottom Of Label Stack", "mpls.bottom", FT_UINT8, BASE_DEC, NULL, 0x0, 
-      "" }},
+      "", HFILL }},
 
     {&mpls_filter[MPLSF_TTL], 
      {"MPLS TTL", "mpls.ttl", FT_UINT8, BASE_DEC, NULL, 0x0, 
-      "" }},
+      "", HFILL }},
 };
 
-static dissector_handle_t ip_handle;
+static dissector_handle_t ipv4_handle;
+static dissector_handle_t ipv6_handle;
+static dissector_handle_t eth_handle;
 
 /*
- * Given a 4-byte MPLS label starting at "start", decode this.
+ * Given a 4-byte MPLS label starting at offset "offset", in tvbuff "tvb",
+ * decode it.
  * Return the label in "label", EXP bits in "exp",
  * bottom_of_stack in "bos", and TTL in "ttl"
  */
-void decode_mpls_label(const unsigned char *start,  
+void decode_mpls_label(tvbuff_t *tvb, int offset,
                       guint32 *label, guint8 *exp,
                       guint8 *bos, guint8 *ttl)
 {
-    *label = (start[0] << 12) + (start[1] << 4) + ((start[2] >> 4) & 0xff);
-    *exp = (start[2] >> 1) & 0x7;
-    *bos = (start[2] & 0x1);
-    *ttl = start[3];
+    guint8 octet0 = tvb_get_guint8(tvb, offset+0);
+    guint8 octet1 = tvb_get_guint8(tvb, offset+1);
+    guint8 octet2 = tvb_get_guint8(tvb, offset+2);
+
+    *label = (octet0 << 12) + (octet1 << 4) + ((octet2 >> 4) & 0xff);
+    *exp = (octet2 >> 1) & 0x7;
+    *bos = (octet2 & 0x1);
+    *ttl = tvb_get_guint8(tvb, offset+3);
 }
 
 static void
-dissect_mpls(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) 
+dissect_mpls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) 
 {
+    int offset = 0;
     guint32 label;
     guint8 exp;
     guint8 bos;
     guint8 ttl;
+    guint8 ipvers;
 
     proto_tree  *mpls_tree;
     proto_item  *ti;
+    tvbuff_t *next_tvb;
 
-    OLD_CHECK_DISPLAY_AS_DATA(proto_mpls, pd, offset, fd, tree);
-
-    if (check_col(fd, COL_PROTOCOL)) {
-       col_set_str(fd,COL_PROTOCOL, "MPLS");
+    if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+       col_set_str(pinfo->cinfo,COL_PROTOCOL, "MPLS");
     }
     
-    if (check_col(fd,COL_INFO)) {
-       col_add_fstr(fd,COL_INFO,"MPLS Label Switched Packet");
+    if (check_col(pinfo->cinfo,COL_INFO)) {
+       col_add_fstr(pinfo->cinfo,COL_INFO,"MPLS Label Switched Packet");
     }
 
     /* Start Decoding Here. */
-    while (1) {
-       if (!BYTES_ARE_IN_FRAME(offset, 4)) {
-           old_dissect_data(pd, offset, fd, tree);
-           return;
-       }
-
-       decode_mpls_label(pd+offset, &label, &exp, &bos, &ttl);
+    while (tvb_reported_length_remaining(tvb, offset) > 0) {
+       decode_mpls_label(tvb, offset, &label, &exp, &bos, &ttl);
 
        if (tree) {
 
-           ti = proto_tree_add_item(tree, proto_mpls, NullTVB, offset, 4, FALSE);
+           ti = proto_tree_add_item(tree, proto_mpls, tvb, offset, 4, FALSE);
            mpls_tree = proto_item_add_subtree(ti, ett_mpls);
 
            if (label <= MAX_RESERVED)
-               proto_tree_add_uint_format(mpls_tree, mpls_filter[MPLSF_LABEL], NullTVB,
-                                   offset, 3, label, "Label: %d (%s)", 
+               proto_tree_add_uint_format(mpls_tree, mpls_filter[MPLSF_LABEL], tvb,
+                                   offset, 3, label, "Label: %u (%s)", 
                                    label, val_to_str(label, special_labels, 
                                                      "Reserved - Unknown"));
            else
-               proto_tree_add_uint(mpls_tree, mpls_filter[MPLSF_LABEL], NullTVB,
+               proto_tree_add_uint(mpls_tree, mpls_filter[MPLSF_LABEL], tvb,
                                    offset, 3, label);
 
-           proto_tree_add_uint(mpls_tree,mpls_filter[MPLSF_EXP], NullTVB
+           proto_tree_add_uint(mpls_tree,mpls_filter[MPLSF_EXP], tvb
                                offset+2,1, exp);
-           proto_tree_add_uint(mpls_tree,mpls_filter[MPLSF_BOTTOM_OF_STACK], NullTVB
+           proto_tree_add_uint(mpls_tree,mpls_filter[MPLSF_BOTTOM_OF_STACK], tvb
                                offset+2,1, bos);
-           proto_tree_add_uint(mpls_tree,mpls_filter[MPLSF_TTL], NullTVB
+           proto_tree_add_uint(mpls_tree,mpls_filter[MPLSF_TTL], tvb
                                offset+3,1, ttl);
        }
        offset += 4;
        if (bos) break;
     }
-    old_call_dissector(ip_handle, pd, offset, fd, tree);
+    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 {
+      call_dissector(eth_handle, next_tvb, pinfo, tree);
+    }
 }
 
 void
@@ -200,11 +209,16 @@ proto_register_mpls(void)
 void
 proto_reg_handoff_mpls(void)
 {
-       old_dissector_add("ethertype", ETHERTYPE_MPLS, dissect_mpls);
-       old_dissector_add("ppp.protocol", PPP_MPLS_UNI, dissect_mpls);
+       dissector_handle_t mpls_handle;
 
        /*
-        * Get a handle for the IP dissector.
+        * Get a handle for the IPv4 and IPv6 dissectors.
         */
-       ip_handle = find_dissector("ip");
+       ipv4_handle = find_dissector("ip");
+       ipv6_handle = find_dissector("ipv6");
+       eth_handle = find_dissector("eth");
+
+       mpls_handle = create_dissector_handle(dissect_mpls, proto_mpls);
+       dissector_add("ethertype", ETHERTYPE_MPLS, mpls_handle);
+       dissector_add("ppp.protocol", PPP_MPLS_UNI, mpls_handle);
 }