*
* (c) Copyright Ashok Narayanan <ashokn@cisco.com>
*
- * $Id: packet-mpls.c,v 1.2 2000/03/13 16:36:31 gram Exp $
+ * $Id: packet-mpls.c,v 1.25 2002/01/21 07:36:37 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 "packet.h"
-#include "packet-mpls.h"
-#include "packet-ip.h"
+#include <epan/packet.h>
+#include "ppptypes.h"
+#include "etypes.h"
static gint proto_mpls = -1;
enum mpls_filter_keys {
/* Is the packet MPLS-encapsulated? */
- MPLSF_PACKET,
+/* MPLSF_PACKET,*/
/* MPLS encap properties */
MPLSF_LABEL,
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_filter[MPLSF_PACKET],
+ {"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 ipv4_handle;
+static dissector_handle_t ipv6_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);
}
-void
-dissect_mpls(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
+static void
+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;
- if (check_col(fd, COL_PROTOCOL)) {
- col_add_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)) {
- 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, offset, 4, NULL);
+ 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],
- 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_item(mpls_tree, mpls_filter[MPLSF_LABEL],
+ proto_tree_add_uint(mpls_tree, mpls_filter[MPLSF_LABEL], tvb,
offset, 3, label);
- proto_tree_add_item(mpls_tree,mpls_filter[MPLSF_EXP],
+ proto_tree_add_uint(mpls_tree,mpls_filter[MPLSF_EXP], tvb,
offset+2,1, exp);
- proto_tree_add_item(mpls_tree,mpls_filter[MPLSF_BOTTOM_OF_STACK],
+ proto_tree_add_uint(mpls_tree,mpls_filter[MPLSF_BOTTOM_OF_STACK], tvb,
offset+2,1, bos);
- proto_tree_add_item(mpls_tree,mpls_filter[MPLSF_TTL],
+ proto_tree_add_uint(mpls_tree,mpls_filter[MPLSF_TTL], tvb,
offset+3,1, ttl);
}
offset += 4;
if (bos) break;
}
- dissect_ip(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 {
+ call_dissector(ipv4_handle, next_tvb, pinfo, tree);
+ }
}
void
&ett_mpls,
};
- proto_mpls = proto_register_protocol("MultiProtocol Label Switching Header", "mpls");
+ proto_mpls = proto_register_protocol("MultiProtocol Label Switching Header",
+ "MPLS", "mpls");
proto_register_field_array(proto_mpls, mplsf_info, array_length(mplsf_info));
proto_register_subtree_array(ett, array_length(ett));
}
+void
+proto_reg_handoff_mpls(void)
+{
+ dissector_handle_t mpls_handle;
+
+ /*
+ * Get a handle for the IPv4 and IPv6 dissectors.
+ */
+ ipv4_handle = find_dissector("ip");
+ ipv6_handle = find_dissector("ipv6");
+
+ 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);
+}