diff options
-rw-r--r-- | AUTHORS | 2 | ||||
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | Makefile.nmake | 1 | ||||
-rw-r--r-- | ethertype.c | 8 | ||||
-rw-r--r-- | etypes.h | 10 | ||||
-rw-r--r-- | ieee-float.h | 84 | ||||
-rw-r--r-- | packet-mpls.c | 193 | ||||
-rw-r--r-- | packet-mpls.h | 13 | ||||
-rw-r--r-- | packet-ospf.c | 263 | ||||
-rw-r--r-- | packet-ospf.h | 10 | ||||
-rw-r--r-- | packet-rsvp.c | 636 |
11 files changed, 1082 insertions, 142 deletions
@@ -112,6 +112,8 @@ Brad Robel-Forrest <bradr@watchguard.com> { Ashok Narayanan <ashokn@cisco.com> { RSVP Match Selected functionality + Support for reading compressed capture files + MPLS } Aaron Hillegass <aaron@classmax.com> { diff --git a/Makefile.am b/Makefile.am index 89aa4ebad2..55fbf05e21 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ # Makefile.am # Automake file for Ethereal # -# $Id: Makefile.am,v 1.174 2000/03/03 12:00:28 gram Exp $ +# $Id: Makefile.am,v 1.175 2000/03/09 18:31:49 ashokn Exp $ # # Ethereal - Network traffic analyzer # By Gerald Combs <gerald@zing.org> @@ -132,6 +132,8 @@ DISSECTOR_SOURCES = \ packet-mapi.h \ packet-mount.c \ packet-mount.h \ + packet-mpls.c \ + packet-mpls.h \ packet-nbipx.c \ packet-nbipx.h \ packet-nbns.c \ diff --git a/Makefile.nmake b/Makefile.nmake index d98b8c05eb..3b4ecb5348 100644 --- a/Makefile.nmake +++ b/Makefile.nmake @@ -66,6 +66,7 @@ DISSECTOR_OBJECTS = \ packet-lpd.obj \ packet-mapi.obj \ packet-mount.obj \ + packet-mpls.obj \ packet-nbipx.obj \ packet-nbns.obj \ packet-ncp.obj \ diff --git a/ethertype.c b/ethertype.c index 60387139a9..93344ec03b 100644 --- a/ethertype.c +++ b/ethertype.c @@ -2,7 +2,7 @@ * Routines for calling the right protocol for the ethertype. * This is called by both packet-eth.c (Ethernet II) and packet-llc.c (SNAP) * - * $Id: ethertype.c,v 1.27 2000/02/15 21:01:56 gram Exp $ + * $Id: ethertype.c,v 1.28 2000/03/09 18:31:50 ashokn Exp $ * * Gilbert Ramirez <gram@xiexie.org> * @@ -48,6 +48,7 @@ #include "packet-vines.h" #include "packet-vlan.h" #include "packet-x25.h" +#include "packet-mpls.h" const value_string etype_vals[] = { {ETHERTYPE_IP, "IP" }, @@ -64,6 +65,8 @@ const value_string etype_vals[] = { {ETHERTYPE_PPPOED, "PPPoE Discovery"}, {ETHERTYPE_PPPOES, "PPPoE Session" }, {ETHERTYPE_VLAN, "802.1Q Virtual LAN" }, + {ETHERTYPE_MPLS, "MPLS label switched packet" }, + {ETHERTYPE_MPLS_MULTI, "MPLS multicast label switched packet" }, {0, NULL } }; void @@ -141,6 +144,9 @@ ethertype(guint16 etype, int offset, case ETHERTYPE_SNMP: dissect_snmp(pd, offset, fd, tree); break; + case ETHERTYPE_MPLS: + dissect_mpls(pd, offset, fd, tree); + break; default: dissect_data(pd, offset, fd, tree); if (check_col(fd, COL_PROTOCOL)) { col_add_fstr(fd, COL_PROTOCOL, "0x%04x", etype); } @@ -1,7 +1,7 @@ /* etypes.h * Defines ethernet packet types, similar to tcpdump's ethertype.h * - * $Id: etypes.h,v 1.12 2000/01/13 17:59:13 guy Exp $ + * $Id: etypes.h,v 1.13 2000/03/09 18:31:50 ashokn Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -106,6 +106,14 @@ #define ETHERTYPE_SNMP 0x814c /* SNMP over Ethernet, RFC 1089 */ #endif +#ifndef ETHERTYPE_MPLS +#define ETHERTYPE_MPLS 0x8847 /* MPLS unicast packet */ +#endif + +#ifndef ETHERTYPE_MPLS_MULTI +#define ETHERTYPE_MPLS_MULTI 0x8848 /* MPLS multicast packet */ +#endif + #endif /* etypes.h */ diff --git a/ieee-float.h b/ieee-float.h new file mode 100644 index 0000000000..1fb612971f --- /dev/null +++ b/ieee-float.h @@ -0,0 +1,84 @@ +/********************************************************************** + * + * ieee_float.h + * + * Implements simple stuff to convert from IEEE float types + * to 32-bit longs + * + * (C) Ashok Narayanan, 2000 + * + * $Id: ieee-float.h,v 1.1 2000/03/09 18:31:50 ashokn Exp $ + * + * For license details, see the COPYING file with this distribution + * + **********************************************************************/ + +#ifndef IEEE_FLOAT_H +#define IEEE_FLOAT_H + +/* Stuff for IEEE float handling */ + +#define IEEE_NUMBER_WIDTH 32 /* bits in number */ +#define IEEE_EXP_WIDTH 8 /* bits in exponent */ +#define IEEE_MANTISSA_WIDTH 23 /* IEEE_NUMBER_WIDTH - 1 - IEEE_EXP_WIDTH */ + +#define IEEE_SIGN_MASK 0x80000000 +#define IEEE_EXPONENT_MASK 0x7F800000 +#define IEEE_MANTISSA_MASK 0x007FFFFF +#define IEEE_INFINITY IEEE_EXPONENT_MASK + +#define IEEE_IMPLIED_BIT (1 << IEEE_MANTISSA_WIDTH) +#define IEEE_INFINITE ((1 << IEEE_EXP_WIDTH) - 1) +#define IEEE_BIAS ((1 << (IEEE_EXP_WIDTH - 1)) - 1) + +#define MINUS_INFINITY (signed)0x80000000L +#define PLUS_INFINITY 0x7FFFFFFF + +static inline int ieee_float_is_zero (long number) +{ + return(!(number & ~IEEE_SIGN_MASK)); +} + +/* + * simple conversion: ieee floating point to long + */ +static long pieee_to_long (const void *p) +{ + long number; + long sign; + long exponent; + long mantissa; + + number = pntohl(p); + sign = number & IEEE_SIGN_MASK; + exponent = number & IEEE_EXPONENT_MASK; + mantissa = number & IEEE_MANTISSA_MASK; + + if (ieee_float_is_zero(number)) { + /* number is zero, unnormalized, or not-a-number */ + return 0; + } + if (IEEE_INFINITY == exponent) { + /* number is positive or negative infinity, or a special value */ + return (sign? MINUS_INFINITY: PLUS_INFINITY); + } + + exponent = (exponent >> IEEE_MANTISSA_WIDTH) - IEEE_BIAS; + if (exponent < 0) { + /* number is between zero and one */ + return 0; + } + + mantissa |= IEEE_IMPLIED_BIT; + if (exponent <= IEEE_MANTISSA_WIDTH) + mantissa >>= IEEE_MANTISSA_WIDTH - exponent; + else + mantissa <<= exponent - IEEE_MANTISSA_WIDTH; + + if (sign) + return -mantissa; + else + return mantissa; +} + +#endif diff --git a/packet-mpls.c b/packet-mpls.c new file mode 100644 index 0000000000..88825cdcfc --- /dev/null +++ b/packet-mpls.c @@ -0,0 +1,193 @@ +/* packet-mpls.c + * Routines for MPLS data packet disassembly + * + * (c) Copyright Ashok Narayanan <ashokn@cisco.com> + * + * $Id: packet-mpls.c,v 1.1 2000/03/09 18:31:50 ashokn Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@zing.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. + */ + +/* + * NOTES + * + * This module defines routines to handle Ethernet-encapsulated MPLS IP packets. + * It should implement all the functionality in <draft-ietf-mpls-label-encaps-07.txt> + * Multicast MPLS support is not tested yet + */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif + +#include <glib.h> +#include "packet.h" +#include "packet-mpls.h" +#include "packet-ip.h" + +static gint proto_mpls = -1; + +static gint ett_mpls = -1; + +/* Special labels in MPLS */ +enum { + IP4_EXPLICIT_NULL = 0, + ROUTER_ALERT, + IP6_EXPLICIT_NULL, + IMPLICIT_NULL, + + MAX_RESERVED = 15 +}; + +static const value_string special_labels[] = { + {IP4_EXPLICIT_NULL, "IPv4 Explicit-Null"}, + {ROUTER_ALERT, "Router Alert"}, + {IP6_EXPLICIT_NULL, "IPv6 Explicit-Null"}, + {IMPLICIT_NULL, "Implicit-Null"}, + {0, NULL } +}; + +/* MPLS filter values */ +enum mpls_filter_keys { + + /* Is the packet MPLS-encapsulated? */ + MPLSF_PACKET, + + /* MPLS encap properties */ + MPLSF_LABEL, + MPLSF_EXP, + MPLSF_BOTTOM_OF_STACK, + MPLSF_TTL, + + MPLSF_MAX +}; + +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_LABEL], + {"MPLS Label", "mpls.label", FT_UINT32, BASE_NONE, NULL, 0x0, + "" }}, + + {&mpls_filter[MPLSF_EXP], + {"MPLS Experimental Bits", "mpls.exp", FT_UINT8, BASE_NONE, NULL, 0x0, + "" }}, + + {&mpls_filter[MPLSF_BOTTOM_OF_STACK], + {"MPLS Bottom Of Label Stack", "mpls.bottom", FT_UINT8, BASE_NONE, NULL, 0x0, + "" }}, + + {&mpls_filter[MPLSF_TTL], + {"MPLS TTL", "mpls.ttl", FT_UINT8, BASE_NONE, NULL, 0x0, + "" }}, +}; + +/* + * Given a 4-byte MPLS label starting at "start", decode this. + * 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, + 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]; +} + +void +dissect_mpls(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) +{ + guint32 label; + guint8 exp; + guint8 bos; + guint8 ttl; + + proto_tree *mpls_tree; + proto_item *ti; + + if (check_col(fd, COL_PROTOCOL)) { + col_add_str(fd,COL_PROTOCOL, "MPLS"); + } + + if (check_col(fd,COL_INFO)) { + col_add_fstr(fd,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); + + if (tree) { + + ti = proto_tree_add_item(tree, proto_mpls, offset, 4, NULL); + mpls_tree = proto_item_add_subtree(ti, ett_mpls); + + if (label <= MAX_RESERVED) + proto_tree_add_text(mpls_tree, offset, 3, + "Label: %d (%s)", + label, val_to_str(label, special_labels, + "Reserved - Unknown")); + else + proto_tree_add_text(mpls_tree, offset, 3, + "Label: %d", label); + proto_tree_add_item_hidden(mpls_tree, mpls_filter[MPLSF_LABEL], + offset,3, label); + proto_tree_add_item(mpls_tree,mpls_filter[MPLSF_EXP], + offset+2,1, exp); + proto_tree_add_item(mpls_tree,mpls_filter[MPLSF_BOTTOM_OF_STACK], + offset+2,1, bos); + proto_tree_add_item(mpls_tree,mpls_filter[MPLSF_TTL], + offset+3,1, ttl); + } + offset += 4; + if (bos) break; + } + dissect_ip(pd, offset, fd, tree); +} + +void +proto_register_mpls(void) +{ + static gint *ett[] = { + &ett_mpls, + }; + + proto_mpls = proto_register_protocol("MultiProtocol Label Switching Header", "mpls"); + proto_register_field_array(proto_mpls, mplsf_info, array_length(mplsf_info)); + proto_register_subtree_array(ett, array_length(ett)); +} + diff --git a/packet-mpls.h b/packet-mpls.h new file mode 100644 index 0000000000..3a624f703b --- /dev/null +++ b/packet-mpls.h @@ -0,0 +1,13 @@ +/********************************************************************** + * + * packet-mpls.h + * + * (C) Ashok Narayanan <ashokn@cisco.com> + * + * $Id: packet-mpls.h,v 1.1 2000/03/09 18:31:51 ashokn Exp $ + * + * For license details, see the COPYING file with this distribution + * + **********************************************************************/ + +void dissect_mpls(const u_char *, int, frame_data *, proto_tree *); diff --git a/packet-ospf.c b/packet-ospf.c index ff4c017167..2ba07f91ce 100644 --- a/packet-ospf.c +++ b/packet-ospf.c @@ -2,7 +2,7 @@ * Routines for OSPF packet disassembly * (c) Copyright Hannes R. Boehm <hannes@boehm.org> * - * $Id: packet-ospf.c,v 1.19 2000/03/07 05:21:54 guy Exp $ + * $Id: packet-ospf.c,v 1.20 2000/03/09 18:31:51 ashokn Exp $ * * At this time, this module is able to analyze OSPF * packets as specified in RFC2328. MOSPF (RFC1584) and other @@ -49,6 +49,7 @@ #include <glib.h> #include "packet.h" #include "packet-ospf.h" +#include "ieee-float.h" static int proto_ospf = -1; @@ -60,6 +61,12 @@ static gint ett_ospf_lsr = -1; static gint ett_ospf_lsa = -1; static gint ett_ospf_lsa_upd = -1; +/* Trees for opaque LSAs */ +static gint ett_ospf_lsa_mpls = -1; +static gint ett_ospf_lsa_mpls_router = -1; +static gint ett_ospf_lsa_mpls_link = -1; +static gint ett_ospf_lsa_mpls_link_stlv = -1; + void dissect_ospf(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { e_ospfhdr ospfh; @@ -400,6 +407,224 @@ dissect_ospf_ls_ack(const u_char *pd, int offset, frame_data *fd, proto_tree *tr } +/* + * Returns if an LSA is opaque, i.e. requires special treatment + */ +int is_opaque(int lsa_type) +{ + return (lsa_type >= 9 && lsa_type <= 11); +} + +/* MPLS/TE TLV types */ +#define MPLS_TLV_ROUTER 1 +#define MPLS_TLV_LINK 2 + +/* MPLS/TE Link STLV types */ +enum { + MPLS_LINK_TYPE = 1, + MPLS_LINK_ID, + MPLS_LINK_LOCAL_IF, + MPLS_LINK_REMOTE_IF, + MPLS_LINK_TE_METRIC, + MPLS_LINK_MAX_BW, + MPLS_LINK_MAX_RES_BW, + MPLS_LINK_UNRES_BW, + MPLS_LINK_COLOR, +}; + +static value_string mpls_link_stlv_str[] = { + {MPLS_LINK_TYPE, "Link Type"}, + {MPLS_LINK_ID, "Link ID"}, + {MPLS_LINK_LOCAL_IF, "Local Interface IP Address"}, + {MPLS_LINK_REMOTE_IF, "Remote Interface IP Address"}, + {MPLS_LINK_TE_METRIC, "Traffic Engineering Metric"}, + {MPLS_LINK_MAX_BW, "Maximum Bandwidth"}, + {MPLS_LINK_MAX_RES_BW, "Maximum Reservable Bandwidth"}, + {MPLS_LINK_UNRES_BW, "Unreserved Bandwidth"}, + {MPLS_LINK_COLOR, "Resource Class/Color"}, +}; + +/* + * Dissect MPLS/TE opaque LSA + */ + +void dissect_ospf_lsa_mpls(const u_char *pd, + int offset, + frame_data *fd, + proto_tree *tree, + e_ospf_lsa_hdr *lsa_hdr) { + proto_item *ti; + proto_tree *mpls_tree; + proto_tree *tlv_tree; + proto_tree *stlv_tree; + + int length; + int tlv_type; + int tlv_length; + + int link_len; + int stlv_type, stlv_len; + char *stlv_name; + int i; + + ti = proto_tree_add_text(tree, offset, ntohs(lsa_hdr->length) - 20, + "MPLS Traffic Engineering LSA"); + mpls_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls); + + for (length = 0; length < ntohs(lsa_hdr->length) - 20; length += 4) { + tlv_type = pntohs(pd+offset+length); + tlv_length = pntohs(pd+offset+length + 2); + + switch(tlv_type) { + case MPLS_TLV_ROUTER: + ti = proto_tree_add_text(mpls_tree, offset+length, tlv_length+4, + "Router Address: %s", + ip_to_str((pd+offset+length+4))); + tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_router); + proto_tree_add_text(tlv_tree, offset+length, 2, "TLV Type: 1 - Router Address"); + proto_tree_add_text(tlv_tree, offset+length+2, 2, "TLV Length: %d", tlv_length); + proto_tree_add_text(tlv_tree, offset+length+4, 4, "Router Address: %s", + ip_to_str((pd+offset+length+4))); + break; + case MPLS_TLV_LINK: + ti = proto_tree_add_text(mpls_tree, offset+length, tlv_length+4, + "Link Information"); + tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link); + proto_tree_add_text(tlv_tree, offset+length, 2, "TLV Type: 2 - Link Information"); + proto_tree_add_text(tlv_tree, offset+length+2, 2, "TLV Length: %d", tlv_length); + + /* Walk down the sub-TLVs for link information */ + for (link_len = length + 4; link_len < length + 4 + tlv_length; link_len += 4) { + stlv_type = pntohs(pd+offset+link_len); + stlv_len = pntohs(pd+offset+link_len + 2); + stlv_name = val_to_str(stlv_type, mpls_link_stlv_str, "Unknown sub-TLV"); + switch(stlv_type) { + + case MPLS_LINK_TYPE: + ti = proto_tree_add_text(tlv_tree, offset+link_len, stlv_len+4, + "%s: %d", stlv_name, + *((guint8 *)pd + offset + link_len + 4)); + stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv); + proto_tree_add_text(stlv_tree, offset+link_len, 2, + "TLV Type: %d: %s", stlv_type, stlv_name); + proto_tree_add_text(stlv_tree, offset+link_len+2, 2, "TLV Length: %d", stlv_len); + proto_tree_add_text(stlv_tree, offset+link_len+4, 1, "%s: %d", stlv_name, + *((guint8 *)pd + offset + link_len + 4)); + break; + + case MPLS_LINK_ID: + ti = proto_tree_add_text(tlv_tree, offset+link_len, stlv_len+4, + "%s: %s (%x)", stlv_name, + ip_to_str(pd + offset + link_len + 4), + pntohl(pd + offset + link_len + 4)); + stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv); + proto_tree_add_text(stlv_tree, offset+link_len, 2, + "TLV Type: %d: %s", stlv_type, stlv_name); + proto_tree_add_text(stlv_tree, offset+link_len+2, 2, "TLV Length: %d", stlv_len); + proto_tree_add_text(stlv_tree, offset+link_len+4, 4, "%s: %s (%x)", stlv_name, + ip_to_str(pd + offset + link_len + 4), + pntohl(pd + offset + link_len + 4)); + break; + + case MPLS_LINK_LOCAL_IF: + case MPLS_LINK_REMOTE_IF: + ti = proto_tree_add_text(tlv_tree, offset+link_len, stlv_len+4, + "%s: %s", stlv_name, + ip_to_str(pd+offset+link_len+4)); + stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv); + proto_tree_add_text(stlv_tree, offset+link_len, 2, + "TLV Type: %d: %s", stlv_type, stlv_name); + proto_tree_add_text(stlv_tree, offset+link_len+2, 2, "TLV Length: %d", stlv_len); + proto_tree_add_text(stlv_tree, offset+link_len+4, 4, "%s: %s", stlv_name, + ip_to_str(pd+offset+link_len+4)); + + break; + + case MPLS_LINK_TE_METRIC: + case MPLS_LINK_COLOR: + ti = proto_tree_add_text(tlv_tree, offset+link_len, stlv_len+4, + "%s: %d", stlv_name, + pntohl(pd + offset + link_len + 4)); + stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv); + proto_tree_add_text(stlv_tree, offset+link_len, 2, + "TLV Type: %d: %s", stlv_type, stlv_name); + proto_tree_add_text(stlv_tree, offset+link_len+2, 2, "TLV Length: %d", stlv_len); + proto_tree_add_text(stlv_tree, offset+link_len+4, 4, "%s: %d", stlv_name, + pntohl(pd + offset + link_len + 4)); + break; + + case MPLS_LINK_MAX_BW: + case MPLS_LINK_MAX_RES_BW: + ti = proto_tree_add_text(tlv_tree, offset+link_len, stlv_len+4, + "%s: %d", stlv_name, + pieee_to_long(pd + offset + link_len + 4)); + stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv); + proto_tree_add_text(stlv_tree, offset+link_len, 2, + "TLV Type: %d: %s", stlv_type, stlv_name); + proto_tree_add_text(stlv_tree, offset+link_len+2, 2, "TLV Length: %d", stlv_len); + proto_tree_add_text(stlv_tree, offset+link_len+4, 4, "%s: %d", stlv_name, + pieee_to_long(pd + offset + link_len + 4)); + break; + + case MPLS_LINK_UNRES_BW: + ti = proto_tree_add_text(tlv_tree, offset+link_len, stlv_len+4, + "%s", stlv_name); + stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv); + proto_tree_add_text(stlv_tree, offset+link_len, 2, + "TLV Type: %d: %s", stlv_type, stlv_name); + proto_tree_add_text(stlv_tree, offset+link_len+2, 2, "TLV Length: %d", stlv_len); + for (i=0; i<8; i++) + proto_tree_add_text(stlv_tree, offset+link_len+4+(i*4), 4, + "Pri %d: %d", i, + pieee_to_long(pd + offset + link_len + 4 + i*4)); + break; + + default: + proto_tree_add_text(tlv_tree, offset+link_len, stlv_len+4, + "Unknown Link sub-TLV: %d", stlv_type); + } + link_len += ((stlv_len+3)/4)*4; + } + + break; + + default: + ti = proto_tree_add_text(mpls_tree, offset+length, tlv_length+4, + "Unknown LSA: %d", tlv_type); + tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link); + proto_tree_add_text(tlv_tree, offset+length, 2, "TLV Type: %d - Unknown", tlv_type); + proto_tree_add_text(tlv_tree, offset+length+2, 2, "TLV Length: %d", tlv_length); + proto_tree_add_text(tlv_tree, offset+length+4, tlv_length, "TLV Data"); + break; + } + + length += tlv_length; + + } +} + +/* + * Dissect opaque LSAs + */ +void dissect_ospf_lsa_opaque(const u_char *pd, + int offset, + frame_data *fd, + proto_tree *tree, + e_ospf_lsa_hdr *lsa_hdr) { + guint8 opaque_id = *((guint8 *) &(lsa_hdr->ls_id)); + + switch(opaque_id) { + + case OSPF_LSA_MPLS_TE: + dissect_ospf_lsa_mpls(pd, offset, fd, tree, lsa_hdr); + break; + + default: + proto_tree_add_text(tree, offset, END_OF_FRAME, "Unknown LSA Type"); + break; + } /* switch on opaque LSA id */ +} + int dissect_ospf_lsa(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int disassemble_body) { e_ospf_lsa_hdr lsa_hdr; @@ -426,6 +651,9 @@ dissect_ospf_lsa(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, e_ospf_asexternal_lsa asext_lsa; guint32 asext_metric; + /* data structures for opaque LSA */ + guint32 ls_id; + proto_tree *ospf_lsa_tree; proto_item *ti; @@ -449,6 +677,15 @@ dissect_ospf_lsa(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, case OSPF_LSTYPE_ASEXT: lsa_type="AS-external-LSA"; break; + case OSPF_LSTYPE_OP_LINKLOCAL: + lsa_type="Opaque LSA, Link-local scope"; + break; + case OSPF_LSTYPE_OP_AREALOCAL: + lsa_type="Opaque LSA, Area-local scope"; + break; + case OSPF_LSTYPE_OP_ASWIDE: + lsa_type="Opaque LSA, AS-wide scope"; + break; default: lsa_type="unknown"; } @@ -467,8 +704,15 @@ dissect_ospf_lsa(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, proto_tree_add_text(ospf_lsa_tree, offset + 2, 1, "Options: %d ", lsa_hdr.options); proto_tree_add_text(ospf_lsa_tree, offset + 3, 1, "LSA Type: %d (%s)", lsa_hdr.ls_type, lsa_type); - proto_tree_add_text(ospf_lsa_tree, offset + 4, 4, "Link State ID: %s ", - ip_to_str((guint8 *) &(lsa_hdr.ls_id))); + if (is_opaque(lsa_hdr.ls_type)) { + ls_id = ntohl(lsa_hdr.ls_id); + proto_tree_add_text(ospf_lsa_tree, offset + 4, 1, "Link State ID Opaque Type: %u ", + (ls_id >> 24) & 0xff); + proto_tree_add_text(ospf_lsa_tree, offset + 5, 3, "Link State ID Opaque ID: %u ", + ls_id & 0xffffff); + } else + proto_tree_add_text(ospf_lsa_tree, offset + 4, 4, "Link State ID: %s ", + ip_to_str((guint8 *) &(lsa_hdr.ls_id))); proto_tree_add_text(ospf_lsa_tree, offset + 8, 4, "Advertising Router: %s ", ip_to_str((guint8 *) &(lsa_hdr.adv_router))); @@ -599,7 +843,14 @@ dissect_ospf_lsa(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, proto_tree_add_text(ospf_lsa_tree, offset + 12, 4,"External Route Tag: %ld", (long)ntohl(asext_lsa.external_tag)); break; - default: + + case OSPF_LSTYPE_OP_LINKLOCAL: + case OSPF_LSTYPE_OP_AREALOCAL: + case OSPF_LSTYPE_OP_ASWIDE: + dissect_ospf_lsa_opaque(pd, offset, fd, ospf_lsa_tree, &lsa_hdr); + break; + + default: /* unknown LSA type */ proto_tree_add_text(ospf_lsa_tree, offset, END_OF_FRAME, "Unknown LSA Type"); } @@ -623,6 +874,10 @@ proto_register_ospf(void) &ett_ospf_lsr, &ett_ospf_lsa, &ett_ospf_lsa_upd, + &ett_ospf_lsa_mpls, + &ett_ospf_lsa_mpls_router, + &ett_ospf_lsa_mpls_link, + &ett_ospf_lsa_mpls_link_stlv }; proto_ospf = proto_register_protocol("Open Shortest Path First", "ospf"); diff --git a/packet-ospf.h b/packet-ospf.h index d7618e2c16..039af76f01 100644 --- a/packet-ospf.h +++ b/packet-ospf.h @@ -1,6 +1,6 @@ /* packet-ospf.h (c) 1998 Hannes Boehm */ -/* $Id: packet-ospf.h,v 1.6 2000/02/15 21:02:49 gram Exp $ */ +/* $Id: packet-ospf.h,v 1.7 2000/03/09 18:31:51 ashokn Exp $ */ #define OSPF_HEADER_LENGTH 24 @@ -32,6 +32,11 @@ #define OSPF_LSTYPE_ASBR 4 #define OSPF_LSTYPE_ASEXT 5 +/* Opaque LSA types */ +#define OSPF_LSTYPE_OP_LINKLOCAL 9 +#define OSPF_LSTYPE_OP_AREALOCAL 10 +#define OSPF_LSTYPE_OP_ASWIDE 11 + #define OSPF_LINK_PTP 1 #define OSPF_LINK_TRANSIT 2 #define OSPF_LINK_STUB 3 @@ -39,6 +44,9 @@ #define OSPF_LSA_HEADER_LENGTH 20 +/* Known opaque LSAs */ +#define OSPF_LSA_MPLS_TE 1 + typedef struct _e_ospfhdr { guint8 version; guint8 packet_type; diff --git a/packet-rsvp.c b/packet-rsvp.c index cb5188940b..9c19f410fd 100644 --- a/packet-rsvp.c +++ b/packet-rsvp.c @@ -3,7 +3,7 @@ * * (c) Copyright Ashok Narayanan <ashokn@cisco.com> * - * $Id: packet-rsvp.c,v 1.14 2000/03/07 06:32:37 guy Exp $ + * $Id: packet-rsvp.c,v 1.15 2000/03/09 18:31:51 ashokn Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -34,6 +34,9 @@ * defined in RFC2210 are also supported. * * IPv6 support is not completely tested + * + * Mar 3, 2000: Added support for MPLS/TE objects, as defined in + * <draft-ietf-mpls-rsvp-lsp-tunnel-04.txt> */ @@ -72,6 +75,7 @@ #include "packet-ip.h" #include "packet-ipv6.h" #include "packet-rsvp.h" +#include "ieee-float.h" static int proto_rsvp = -1; @@ -92,6 +96,14 @@ static gint ett_rsvp_adspec = -1; static gint ett_rsvp_adspec_subtree = -1; static gint ett_rsvp_integrity = -1; static gint ett_rsvp_policy = -1; +static gint ett_rsvp_label = -1; +static gint ett_rsvp_label_request = -1; +static gint ett_rsvp_session_attribute = -1; +static gint ett_rsvp_session_attribute_flags = -1; +static gint ett_rsvp_explicit_route = -1; +static gint ett_rsvp_explicit_route_subobj = -1; +static gint ett_rsvp_record_route = -1; +static gint ett_rsvp_record_route_subobj = -1; static gint ett_rsvp_unknown_class = -1; @@ -123,6 +135,7 @@ static value_string message_type_vals[] = { enum rsvp_classes { RSVP_CLASS_NULL=0, RSVP_CLASS_SESSION, + RSVP_CLASS_HOP=3, RSVP_CLASS_INTEGRITY, RSVP_CLASS_TIME_VALUES, @@ -135,7 +148,14 @@ enum rsvp_classes { RSVP_CLASS_SENDER_TSPEC, RSVP_CLASS_ADSPEC, RSVP_CLASS_POLICY, - RSVP_CLASS_CONFIRM + RSVP_CLASS_CONFIRM, + RSVP_CLASS_LABEL, + + RSVP_CLASS_LABEL_REQUEST=19, + RSVP_CLASS_EXPLICIT_ROUTE, + RSVP_CLASS_RECORD_ROUTE, + + RSVP_CLASS_SESSION_ATTRIBUTE=207, }; static value_string rsvp_class_vals[] = { @@ -153,7 +173,12 @@ static value_string rsvp_class_vals[] = { {RSVP_CLASS_SENDER_TSPEC, "SENDER TSPEC object"}, {RSVP_CLASS_ADSPEC, "ADSPEC object"}, {RSVP_CLASS_POLICY, "POLICY object"}, - {RSVP_CLASS_CONFIRM, "CONFIRM object"} + {RSVP_CLASS_CONFIRM, "CONFIRM object"}, + {RSVP_CLASS_LABEL, "LABEL object"}, + {RSVP_CLASS_LABEL_REQUEST, "LABEL REQUEST object"}, + {RSVP_CLASS_EXPLICIT_ROUTE, "EXPLICIT ROUTE object"}, + {RSVP_CLASS_RECORD_ROUTE, "RECORD ROUTE object"}, + {RSVP_CLASS_SESSION_ATTRIBUTE, "SESSION ATTRIBUTE object"}, }; /* @@ -525,24 +550,27 @@ static value_string adspec_params[] = { {136, "Since-last-reshaping point composed D"}, }; +/* -------------------- Stuff for MPLS/TE objects -------------------- */ -/* Stuff for IEEE float handling */ - -#define IEEE_NUMBER_WIDTH 32 /* bits in number */ -#define IEEE_EXP_WIDTH 8 /* bits in exponent */ -#define IEEE_MANTISSA_WIDTH 23 /* IEEE_NUMBER_WIDTH - 1 - IEEE_EXP_WIDTH */ - -#define IEEE_SIGN_MASK 0x80000000 -#define IEEE_EXPONENT_MASK 0x7F800000 -#define IEEE_MANTISSA_MASK 0x007FFFFF -#define IEEE_INFINITY IEEE_EXPONENT_MASK +typedef struct { + rsvp_object base; + guint32 labels[0]; +} label; -#define IEEE_IMPLIED_BIT (1 << IEEE_MANTISSA_WIDTH) -#define IEEE_INFINITE ((1 << IEEE_EXP_WIDTH) - 1) -#define IEEE_BIAS ((1 << (IEEE_EXP_WIDTH - 1)) - 1) +typedef struct { + rsvp_object base; + guint16 _reserved; + guint16 l3pid; +} label_request; -#define MINUS_INFINITY (signed)0x80000000L -#define PLUS_INFINITY 0x7FFFFFFF +typedef struct { + rsvp_object base; + guint8 setup_prio; + guint8 hold_prio; + guint8 flags; + guint8 name_len; + guint8 name[0]; +} session_attribute; static const value_string proto_vals[] = { {IP_PROTO_ICMP, "ICMP"}, {IP_PROTO_IGMP, "IGMP"}, @@ -583,16 +611,28 @@ enum rsvp_filter_keys { RSVPF_ADSPEC, RSVPF_POLICY, RSVPF_CONFIRM, + RSVPF_LABEL, + RSVPF_DUMMY_2, + RSVPF_DUMMY_3, + RSVPF_LABEL_REQUEST, + RSVPF_EXPLICIT_ROUTE, + RSVPF_RECORD_ROUTE, + + RSVPF_SESSION_ATTRIBUTE, + RSVPF_UNKNOWN_OBJ, /* Session object */ RSVPF_SESSION_IP, RSVPF_SESSION_PROTO, RSVPF_SESSION_PORT, + RSVPF_SESSION_TUNNEL_ID, + RSVPF_SESSION_EXT_TUNNEL_ID, /* Sender template */ RSVPF_SENDER_IP, RSVPF_SENDER_PORT, + RSVPF_SENDER_LSP_ID, /* Sentinel */ RSVPF_MAX @@ -698,6 +738,26 @@ static hf_register_info rsvpf_info[] = { { "CONFIRM", "rsvp.confirm", FT_UINT8, BASE_NONE, NULL, 0x0, "" }}, + {&rsvp_filter[RSVPF_LABEL], + { "LABEL", "rsvp.label", FT_UINT8, BASE_NONE, NULL, 0x0, + "" }}, + + {&rsvp_filter[RSVPF_LABEL_REQUEST], + { "LABEL REQUEST", "rsvp.label_request", FT_UINT8, BASE_NONE, NULL, 0x0, + "" }}, + + {&rsvp_filter[RSVPF_SESSION_ATTRIBUTE], + { "SESSION ATTRIBUTE", "rsvp.session_attribute", FT_UINT8, BASE_NONE, NULL, 0x0, + "" }}, + + {&rsvp_filter[RSVPF_EXPLICIT_ROUTE], + { "EXPLICIT ROUTE", "rsvp.explicit_route", FT_UINT8, BASE_NONE, NULL, 0x0, + "" }}, + + {&rsvp_filter[RSVPF_RECORD_ROUTE], + { "RECORD ROUTE", "rsvp.record_route", FT_UINT8, BASE_NONE, NULL, 0x0, + "" }}, + {&rsvp_filter[RSVPF_UNKNOWN_OBJ], { "Unknown object", "rsvp.obj_unknown", FT_UINT8, BASE_NONE, NULL, 0x0, "" }}, @@ -715,13 +775,25 @@ static hf_register_info rsvpf_info[] = { { "Protocol", "rsvp.session.proto", FT_UINT8, BASE_NONE, VALS(proto_vals), 0x0, "" }}, - /* Sender template fields */ + {&rsvp_filter[RSVPF_SESSION_TUNNEL_ID], + { "Tunnel ID", "rsvp.session.tunnel_id", FT_UINT16, BASE_NONE, NULL, 0x0, + "" }}, + + {&rsvp_filter[RSVPF_SESSION_EXT_TUNNEL_ID], + { "Extended tunnel ID", "rsvp.session.ext_tunnel_id", FT_UINT32, BASE_NONE, NULL, 0x0, + "" }}, + + /* Sender template/Filterspec fields */ {&rsvp_filter[RSVPF_SENDER_IP], - { "Sender Template IPv4 address", "rsvp.template.ip", FT_IPv4, BASE_NONE, NULL, 0x0, + { "Sender IPv4 address", "rsvp.sender.ip", FT_IPv4, BASE_NONE, NULL, 0x0, "" }}, {&rsvp_filter[RSVPF_SENDER_PORT], - { "Sender Template port number", "rsvp.template.port", FT_UINT16, BASE_NONE, NULL, 0x0, + { "Sender port number", "rsvp.sender.port", FT_UINT16, BASE_NONE, NULL, 0x0, + "" }}, + + {&rsvp_filter[RSVPF_SENDER_LSP_ID], + { "Sender LSP ID", "rsvp.sender.lsp_id", FT_UINT16, BASE_NONE, NULL, 0x0, "" }} }; @@ -742,73 +814,37 @@ static inline int rsvp_class_to_filter_num(int classnum) case RSVP_CLASS_ADSPEC : case RSVP_CLASS_POLICY : case RSVP_CLASS_CONFIRM : + case RSVP_CLASS_LABEL : + case RSVP_CLASS_LABEL_REQUEST : + case RSVP_CLASS_EXPLICIT_ROUTE : + case RSVP_CLASS_RECORD_ROUTE : return classnum + RSVPF_OBJECT; + break; + + case RSVP_CLASS_SESSION_ATTRIBUTE : + return RSVPF_SESSION_ATTRIBUTE; default: return RSVPF_UNKNOWN_OBJ; } } -static inline int ieee_float_is_zero (long number) -{ - return(!(number & ~IEEE_SIGN_MASK)); -} - -/* - * simple conversion: ieee floating point to long - */ -static long ieee_to_long (const void *p) -{ - long number; - long sign; - long exponent; - long mantissa; - - number = pntohl(p); - sign = number & IEEE_SIGN_MASK; - exponent = number & IEEE_EXPONENT_MASK; - mantissa = number & IEEE_MANTISSA_MASK; - - if (ieee_float_is_zero(number)) { - /* number is zero, unnormalized, or not-a-number */ - return 0; - } - if (IEEE_INFINITY == exponent) { - /* number is positive or negative infinity, or a special value */ - return (sign? MINUS_INFINITY: PLUS_INFINITY); - } - - exponent = (exponent >> IEEE_MANTISSA_WIDTH) - IEEE_BIAS; - if (exponent < 0) { - /* number is between zero and one */ - return 0; - } - - mantissa |= IEEE_IMPLIED_BIT; - if (exponent <= IEEE_MANTISSA_WIDTH) - mantissa >>= IEEE_MANTISSA_WIDTH - exponent; - else - mantissa <<= exponent - IEEE_MANTISSA_WIDTH; - - if (sign) - return -mantissa; - else - return mantissa; -} - void dissect_rsvp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { - proto_tree *rsvp_tree = NULL, *ti; + proto_tree *rsvp_tree = NULL, *ti, *ti2; proto_tree *rsvp_header_tree; proto_tree *rsvp_object_tree; + proto_tree *rsvp_sa_flags_tree; + proto_tree *rsvp_ero_subtree; char *packet_type, *object_type; rsvp_header *hdr; rsvp_object *obj; - int i, len, mylen; + int i, j, k, l, len, mylen; int msg_length; int obj_length; int offset2; + struct e_in6_addr *ip6a; hdr = (rsvp_header *)&pd[offset]; packet_type = match_strval(hdr->message_type, message_type_vals); @@ -827,27 +863,27 @@ dissect_rsvp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) rsvp_tree = proto_item_add_subtree(ti, ett_rsvp); ti = proto_tree_add_text(rsvp_tree, offset, - sizeof(rsvp_header), "RSVP Header"); + sizeof(rsvp_header), "RSVP Header"); rsvp_header_tree = proto_item_add_subtree(ti, ett_rsvp_hdr); proto_tree_add_text(rsvp_header_tree, offset, 1, "RSVP Version: %u", - (hdr->ver_flags & 0xf0)>>4); + (hdr->ver_flags & 0xf0)>>4); proto_tree_add_text(rsvp_header_tree, offset, 1, "Flags: %02X", - hdr->ver_flags & 0xf); + hdr->ver_flags & 0xf); proto_tree_add_item(rsvp_header_tree, rsvp_filter[RSVPF_MSG], offset+1, 1, hdr->message_type); if (hdr->message_type >= RSVPF_MAX) { - proto_tree_add_text(rsvp_header_tree, offset+1, 1, "Message Type: %u - Unknown", - hdr->message_type); - return; + proto_tree_add_text(rsvp_header_tree, offset+1, 1, "Message Type: %u - Unknown", + hdr->message_type); + return; } proto_tree_add_item_hidden(rsvp_header_tree, rsvp_filter[RSVPF_MSG + hdr->message_type], - offset+1, 1, 1); + offset+1, 1, 1); proto_tree_add_text(rsvp_header_tree, offset + 2 , 2, "Message Checksum"); proto_tree_add_text(rsvp_header_tree, offset + 4 , 1, "Sending TTL: %u", - hdr->sending_ttl); + hdr->sending_ttl); proto_tree_add_text(rsvp_header_tree, offset + 6 , 2, "Message length: %d", - msg_length); + msg_length); offset += sizeof(rsvp_header); len = 0; @@ -856,19 +892,14 @@ dissect_rsvp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) obj_length = pntohs(pd+offset); if (!BYTES_ARE_IN_FRAME(offset, obj_length)) { proto_tree_add_text(rsvp_tree, offset, 1, - "Further data not captured"); + "Further data not captured"); break; } object_type = match_strval(obj->class, rsvp_class_vals); if (!object_type) object_type = "Unknown"; - /* - ti = proto_tree_add_text(rsvp_tree, offset, - obj_length, - "%s (%u)", object_type, obj->class); - */ ti = proto_tree_add_item_hidden(rsvp_tree, rsvp_filter[RSVPF_OBJECT], - offset, obj_length, obj->class); + offset, obj_length, obj->class); ti = proto_tree_add_item(rsvp_tree, rsvp_filter[rsvp_class_to_filter_num(obj->class)], offset, obj_length, obj->class); @@ -885,26 +916,15 @@ dissect_rsvp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) obj->class, object_type); switch(obj->type) { case 1: { - /*rsvp_session_ipv4 *sess = (rsvp_session_ipv4 *)obj;*/ proto_tree_add_text(rsvp_object_tree, offset+3, 1, "C-type: 1 - IPv4"); - /* - proto_tree_add_text(rsvp_object_tree, offset2, 4, - "Destination address: %s", - ip_to_str((guint8 *) &(sess->destination))); - */ proto_tree_add_item(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_IP], - offset2, 4, pntohl(pd+offset2)); + offset2, 4, *(ulong *)(pd+offset2)); - /* proto_tree_add_text(rsvp_object_tree, offset2+4, 1, - "Protocol: %u", sess->protocol);*/ proto_tree_add_item(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_PROTO], - offset2+4, 1, pntohs(pd+offset2+4)); + offset2+4, 1, *(pd+offset2+4)); proto_tree_add_text(rsvp_object_tree, offset2+5, 1, "Flags: %x", pntohs(pd+offset2+5)); - /* proto_tree_add_text(rsvp_object_tree, offset2+6, 2, - "Destination port: %u", - pntohs(pd+offset2+6)); */ proto_tree_add_item(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_PORT], offset2+6, 2, pntohs(pd+offset2+6)); break; @@ -927,6 +947,19 @@ dissect_rsvp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) break; } + case 7: { + proto_tree_add_text(rsvp_object_tree, offset+3, 1, + "C-type: 7 - IPv4 LSP"); + proto_tree_add_item(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_IP], + offset2, 4, *(ulong *)(pd+offset2)); + + proto_tree_add_item(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_TUNNEL_ID], + offset2+6, 2, pntohs(pd+offset2+6)); + proto_tree_add_item(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_EXT_TUNNEL_ID], + offset2+8, 4, *(ulong *)(pd+offset2+8)); + break; + } + default: { proto_tree_add_text(rsvp_object_tree, offset+3, 1, "C-type: Unknown (%u)", @@ -1099,14 +1132,13 @@ dissect_rsvp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) } case 2: { - struct e_in6_addr *ip; proto_tree_add_text(rsvp_object_tree, offset+3, 1, "C-type: 2 - IPv6"); while (mylen>sizeof(rsvp_object)) { - ip = (struct e_in6_addr *)pd+offset2; + ip6a = (struct e_in6_addr *)pd+offset2; proto_tree_add_text(rsvp_object_tree, offset2, 16, "IPv6 Address: %s", - ip6_to_str(ip)); + ip6_to_str(ip6a)); offset2 += 16; mylen -= 16; } @@ -1212,14 +1244,13 @@ dissect_rsvp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) common_template: switch(obj->type) { case 1: { - rsvp_template_ipv4 *tem = (rsvp_template_ipv4 *)obj; proto_tree_add_text(rsvp_object_tree, offset+3, 1, "C-type: 1 - IPv4"); - proto_tree_add_text(rsvp_object_tree, offset2, 4, - "Source address: %s", - ip_to_str((guint8 *) &(tem->source))); - proto_tree_add_text(rsvp_object_tree, offset2+6, 2, - "Source port: %u", pntohs(pd+offset2+6)); + proto_tree_add_item(rsvp_object_tree, rsvp_filter[RSVPF_SENDER_IP], + offset2, 4, *(ulong *)(pd+offset2)); + + proto_tree_add_item(rsvp_object_tree, rsvp_filter[RSVPF_SENDER_PORT], + offset2+6, 2, pntohs(pd+offset2+6)); break; } @@ -1235,6 +1266,17 @@ dissect_rsvp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) break; } + case 7: { + proto_tree_add_text(rsvp_object_tree, offset+3, 1, + "C-type: 7 - IPv4 LSP"); + proto_tree_add_item(rsvp_object_tree, rsvp_filter[RSVPF_SENDER_IP], + offset2, 4, *(ulong *)(pd+offset2)); + + proto_tree_add_item(rsvp_object_tree, rsvp_filter[RSVPF_SENDER_LSP_ID], + offset2+6, 2, pntohs(pd+offset2+6)); + break; + } + default: { proto_tree_add_text(rsvp_object_tree, offset+3, 1, "C-type: Unknown (%u)", @@ -1262,11 +1304,11 @@ dissect_rsvp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) obj->class, object_type); proto_tree_add_text(rsvp_object_tree, offset2, 1, - "Message format version: %u", - tspec->version>>4); + "Message format version: %u", + tspec->version>>4); proto_tree_add_text(rsvp_object_tree, offset2+2, 2, - "Data length: %u words, not including header", - pntohs(pd+offset2+2)); + "Data length: %u words, not including header", + pntohs(pd+offset2+2)); mylen -=4; offset2 +=4; @@ -1279,10 +1321,10 @@ dissect_rsvp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) "Service header: %u - %s", sh->service_num, str); proto_tree_add_text(rsvp_object_tree, offset2+2, 2, - "Length of service %u data: %u words, " - "not including header", - sh->service_num, - ntohs(sh->length)); + "Length of service %u data: %u words, " + "not including header", + sh->service_num, + ntohs(sh->length)); offset2+=4; mylen -=4; @@ -1308,13 +1350,13 @@ dissect_rsvp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) ntohs(ist->parameter_length)); proto_tree_add_text(rsvp_object_tree, offset2+4, 4, "Token bucket rate: %ld", - ieee_to_long(pd+offset2+4)); + pieee_to_long(pd+offset2+4)); proto_tree_add_text(rsvp_object_tree, offset2+8, 4, "Token bucket size: %ld", - ieee_to_long(pd+offset2+8)); + pieee_to_long(pd+offset2+8)); proto_tree_add_text(rsvp_object_tree, offset2+12, 4, "Peak data rate: %ld", - ieee_to_long(pd+offset2+12)); + pieee_to_long(pd+offset2+12)); proto_tree_add_text(rsvp_object_tree, offset2+16, 4, "Minimum policed unit: %u", pntohl(pd+offset2+16)); @@ -1374,11 +1416,11 @@ dissect_rsvp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) obj->class, object_type); proto_tree_add_text(rsvp_object_tree, offset2, 1, - "Message format version: %u", - flowspec->version>>4); + "Message format version: %u", + flowspec->version>>4); proto_tree_add_text(rsvp_object_tree, offset2+2, 2, - "Data length: %u words, not including header", - pntohs(pd+offset2+2)); + "Data length: %u words, not including header", + pntohs(pd+offset2+2)); mylen -=4; offset2+=4; @@ -1391,10 +1433,10 @@ dissect_rsvp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) "Service header: %u - %s", sh->service_num, str); proto_tree_add_text(rsvp_object_tree, offset2+2, 2, - "Length of service %u data: %u words, " - "not including header", - sh->service_num, - ntohs(sh->length)); + "Length of service %u data: %u words, " + "not including header", + sh->service_num, + ntohs(sh->length)); offset2+=4; mylen -=4; @@ -1420,13 +1462,13 @@ dissect_rsvp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) ntohs(isf->tspec.parameter_length)); proto_tree_add_text(rsvp_object_tree, offset2+4, 4, "Token bucket rate: %ld", - ieee_to_long(pd+offset2+4)); + pieee_to_long(pd+offset2+4)); proto_tree_add_text(rsvp_object_tree, offset2+8, 4, "Token bucket size: %ld", - ieee_to_long(pd+offset2+8)); + pieee_to_long(pd+offset2+8)); proto_tree_add_text(rsvp_object_tree, offset2+12, 4, "Peak data rate: %ld", - ieee_to_long(pd+offset2+12)); + pieee_to_long(pd+offset2+12)); proto_tree_add_text(rsvp_object_tree, offset2+16, 4, "Minimum policed unit: %u", pntohl(pd+offset2+16)); @@ -1453,7 +1495,7 @@ dissect_rsvp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) proto_tree_add_text(rsvp_object_tree, offset2+28, 4, "Rate: %ld", - ieee_to_long(pd+offset2+28)); + pieee_to_long(pd+offset2+28)); proto_tree_add_text(rsvp_object_tree, offset2+32, 4, "Slack term: %u", pntohl(pd+offset2+32)); @@ -1519,7 +1561,7 @@ dissect_rsvp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) (pntohs(&shdr->length)+1)<<2, str?str:"Unknown"); adspec_tree = proto_item_add_subtree(ti, - ett_rsvp_adspec_subtree); + ett_rsvp_adspec_subtree); proto_tree_add_text(adspec_tree, offset2, 1, "Service header %u - %s", shdr->service_num, str); @@ -1557,7 +1599,7 @@ dissect_rsvp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) (pntohs(&phdr->length)+1)<<2, "%s - %lu (type %u, length %u)", str, - ieee_to_long(&phdr->dataval), + pieee_to_long(&phdr->dataval), phdr->id, pntohs(&phdr->length)); break; default: @@ -1599,6 +1641,324 @@ dissect_rsvp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) obj->class, object_type); goto default_class; + case RSVP_CLASS_LABEL_REQUEST : + rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_label_request); + proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", + obj_length); + proto_tree_add_text(rsvp_object_tree, offset+2, 1, + "Class number: %d - %s", + obj->class, object_type); + switch(obj->type) { + case 1: { + unsigned short l3pid = pntohs(pd+offset2+2); + proto_tree_add_text(rsvp_object_tree, offset+3, 1, + "C-type: 1"); + proto_tree_add_text(rsvp_object_tree, offset2+2, 2, + "L3PID: 0x%04x", l3pid); + break; + } + + default: { + proto_tree_add_text(rsvp_object_tree, offset+3, 1, + "C-type: Unknown (%d)", + obj->type); + i = obj_length - sizeof(rsvp_object); + proto_tree_add_text(rsvp_object_tree, offset2, i, + "Data (%d bytes)", i); + break; + } + } + break; + + case RSVP_CLASS_LABEL : + rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_label); + proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", + obj_length); + proto_tree_add_text(rsvp_object_tree, offset+2, 1, + "Class number: %d - %s", + obj->class, object_type); + switch(obj->type) { + case 1: { + proto_tree_add_text(rsvp_object_tree, offset+3, 1, + "C-type: 1"); + for (i=1, l = 0; l < obj_length - 4; l+=4, i++) + proto_tree_add_text(rsvp_object_tree, offset2+l, 4, + "Label %d: %d %s", + i, pntohl(pd+offset2+l), + l == obj_length - 8 ? + "(Top label)" : ""); + break; + } + + default: { + proto_tree_add_text(rsvp_object_tree, offset+3, 1, + "C-type: Unknown (%d)", + obj->type); + i = obj_length - sizeof(rsvp_object); + proto_tree_add_text(rsvp_object_tree, offset2, i, + "Data (%d bytes)", i); + break; + } + } + break; + + case RSVP_CLASS_SESSION_ATTRIBUTE : + rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_session_attribute); + proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", + obj_length); + proto_tree_add_text(rsvp_object_tree, offset+2, 1, + "Class number: %d - %s", + obj->class, object_type); + switch(obj->type) { + case 7: { + char s_name[64]; + session_attribute *s_attr = (session_attribute *)&pd[offset]; + proto_tree_add_text(rsvp_object_tree, offset+3, 1, + "C-type: 7 - IPv4 LSP"); + proto_tree_add_text(rsvp_object_tree, offset2, 1, + "Setup priority: %d", s_attr->setup_prio); + proto_tree_add_text(rsvp_object_tree, offset2+1, 1, + "Hold priority: %d", s_attr->hold_prio); + ti2 = proto_tree_add_text(rsvp_object_tree, offset2+2, 1, + "Flags: %0x", s_attr->flags); + rsvp_sa_flags_tree = proto_item_add_subtree(ti2, + ett_rsvp_session_attribute_flags); + proto_tree_add_text(rsvp_sa_flags_tree, offset2+2, 1, + ".......%d: Local protection: %s", + s_attr->flags & 0x1 ? 1 : 0, + s_attr->flags & 0x1 ? "Set" : "Not set"); + proto_tree_add_text(rsvp_sa_flags_tree, offset2+2, 1, + "......%d.: Merging permitted: %s", + s_attr->flags & 0x2 ? 1 : 0, + s_attr->flags & 0x2 ? "Set" : "Not set"); + proto_tree_add_text(rsvp_sa_flags_tree, offset2+2, 1, + ".....%d..: Ingress note may reroute: %s", + s_attr->flags & 0x4 ? 1 : 0, + s_attr->flags & 0x4 ? "Set" : "Not set"); + + proto_tree_add_text(rsvp_object_tree, offset2+3, 1, + "Name length: %d", s_attr->name_len); + memset(s_name, 0, 64); + strncpy(s_name, s_attr->name, 60); + if (s_attr->name_len>60) sprintf(&(s_name[60]), "..."); + proto_tree_add_text(rsvp_object_tree, offset2+4, s_attr->name_len, + "Name: %s", s_name); + break; + } + + default: { + proto_tree_add_text(rsvp_object_tree, offset+3, 1, + "C-type: Unknown (%d)", + obj->type); + i = obj_length - sizeof(rsvp_object); + proto_tree_add_text(rsvp_object_tree, offset2, i, + "Data (%d bytes)", i); + break; + } + } + break; + + case RSVP_CLASS_EXPLICIT_ROUTE : + rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_explicit_route); + proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", + obj_length); + proto_tree_add_text(rsvp_object_tree, offset+2, 1, + "Class number: %d - %s", + obj->class, object_type); + switch(obj->type) { + case 1: { + proto_tree_add_text(rsvp_object_tree, offset+3, 1, + "C-type: 1"); + for (i=1, l = 0; l < obj_length - 4; i++) { + j = ((unsigned char)pd[offset2+l]) & 0x7f; + switch(j) { + case 1: /* IPv4 */ + k = ((unsigned char)pd[offset2+l]) & 0x80; + ti2 = proto_tree_add_text(rsvp_object_tree, + offset2+l, 8, + "IPv4 Subobject - %s, %s", + ip_to_str(&pd[offset2+l+2]), + k ? "Loose" : "Strict"); + rsvp_ero_subtree = + proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); + proto_tree_add_text(rsvp_ero_subtree, offset2+l, 1, + k ? "Loose Hop " : "Strict Hop"); + proto_tree_add_text(rsvp_ero_subtree, offset2+l, 1, + "Type: 1 (IPv4)"); + proto_tree_add_text(rsvp_ero_subtree, offset2+l+1, 1, + "Length: %d", pd[offset2+l+1]); + proto_tree_add_text(rsvp_ero_subtree, offset2+l+2, 4, + "IPv4 hop: %s", ip_to_str(&pd[offset2+l+2])); + proto_tree_add_text(rsvp_ero_subtree, offset2+l+6, 1, + "Prefix length: %d", pd[offset2+l+6]); + break; + + case 2: /* IPv6 */ + ti2 = proto_tree_add_text(rsvp_object_tree, + offset2+l, 20, + "IPv6 Subobject"); + rsvp_ero_subtree = + proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); + k = ((unsigned char)pd[offset2+l]) & 0x80; + proto_tree_add_text(rsvp_ero_subtree, offset2+l, 1, + k ? "Loose Hop " : "Strict Hop"); + proto_tree_add_text(rsvp_ero_subtree, offset2+l, 1, + "Type: 2 (IPv6)"); + proto_tree_add_text(rsvp_ero_subtree, offset2+l+1, 1, + "Length: %d", pd[offset2+l+1]); + ip6a = (struct e_in6_addr *)pd+offset2+l+2; + proto_tree_add_text(rsvp_ero_subtree, offset2+l+2, 16, + "IPv6 hop: %s", ip6_to_str(ip6a)); + proto_tree_add_text(rsvp_ero_subtree, offset2+l+18, 1, + "Prefix length: %d", pd[offset2+l+6]); + break; + + case 32: /* AS */ + k = pntohs(offset2+l+2); + ti2 = proto_tree_add_text(rsvp_object_tree, + offset2+l, 4, + "Autonomous System %d", k); + rsvp_ero_subtree = + proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); + proto_tree_add_text(rsvp_ero_subtree, offset2+l, 1, + k ? "Loose Hop " : "Strict Hop"); + proto_tree_add_text(rsvp_ero_subtree, offset2+l, 1, + "Type: 32 (Autonomous System Number)"); + proto_tree_add_text(rsvp_ero_subtree, offset2+l+1, 1, + "Length: %d", pd[offset2+l+1]); + proto_tree_add_text(rsvp_ero_subtree, offset2+l+2, 2, + "Autonomous System %d", k); + break; + + case 64: /* Path Term */ + k = ((unsigned char)pd[offset2+l]) & 0x80; + ti2 = proto_tree_add_text(rsvp_object_tree, + offset2+l, 4, + "LSP Path Termination"); + rsvp_ero_subtree = + proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); + proto_tree_add_text(rsvp_ero_subtree, offset2+l, 1, + k ? "Loose Hop " : "Strict Hop"); + proto_tree_add_text(rsvp_ero_subtree, offset2+l, 1, + "Type: 64 (MPLS LSP Path Termination)"); + proto_tree_add_text(rsvp_ero_subtree, offset2+l+1, 1, + "Length: %d", pd[offset2+l+1]); + break; + + default: /* Unknown subobject */ + k = ((unsigned char)pd[offset2+l]) & 0x80; + ti2 = proto_tree_add_text(rsvp_object_tree, + offset2+l, pd[offset2+l+1], + "Unknown subobject: %d", j); + rsvp_ero_subtree = + proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); + proto_tree_add_text(rsvp_ero_subtree, offset2+l, 1, + k ? "Loose Hop " : "Strict Hop"); + proto_tree_add_text(rsvp_ero_subtree, offset2+l, 1, + "Type: %d (Unknown)", j); + proto_tree_add_text(rsvp_ero_subtree, offset2+l+1, 1, + "Length: %d", pd[offset2+l+1]); + + } + + l += ((unsigned char)pd[offset2+l+1]); + } + break; + } + default: { + proto_tree_add_text(rsvp_object_tree, offset+3, 1, + "C-type: Unknown (%d)", + obj->type); + i = obj_length - sizeof(rsvp_object); + proto_tree_add_text(rsvp_object_tree, offset2, i, + "Data (%d bytes)", i); + break; + } + } + break; + + + case RSVP_CLASS_RECORD_ROUTE : + rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_record_route); + proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", + obj_length); + proto_tree_add_text(rsvp_object_tree, offset+2, 1, + "Class number: %d - %s", + obj->class, object_type); + switch(obj->type) { + case 1: { + proto_tree_add_text(rsvp_object_tree, offset+3, 1, + "C-type: 1"); + for (i=1, l = 0; l < obj_length - 4; i++) { + j = (unsigned char)pd[offset2+l]; + switch(j) { + case 1: /* IPv4 */ + ti2 = proto_tree_add_text(rsvp_object_tree, + offset2+l, 8, + "IPv4 Subobject - %s", + ip_to_str(&pd[offset2+l+2])); + rsvp_ero_subtree = + proto_item_add_subtree(ti2, ett_rsvp_record_route_subobj); + proto_tree_add_text(rsvp_ero_subtree, offset2+l, 1, + "Type: 1 (IPv4)"); + proto_tree_add_text(rsvp_ero_subtree, offset2+l+1, 1, + "Length: %d", pd[offset2+l+1]); + proto_tree_add_text(rsvp_ero_subtree, offset2+l+2, 4, + "IPv4 hop: %s", ip_to_str(&pd[offset2+l+2])); + proto_tree_add_text(rsvp_ero_subtree, offset2+l+6, 1, + "Prefix length: %d", pd[offset2+l+6]); + break; + + case 2: /* IPv6 */ + ti2 = proto_tree_add_text(rsvp_object_tree, + offset2+l, 20, + "IPv6 Subobject"); + rsvp_ero_subtree = + proto_item_add_subtree(ti2, ett_rsvp_record_route_subobj); + proto_tree_add_text(rsvp_ero_subtree, offset2+l, 1, + "Type: 2 (IPv6)"); + proto_tree_add_text(rsvp_ero_subtree, offset2+l+1, 1, + "Length: %d", pd[offset2+l+1]); + ip6a = (struct e_in6_addr *)pd+offset2+l+2; + proto_tree_add_text(rsvp_ero_subtree, offset2+l+2, 16, + "IPv6 hop: %s", ip6_to_str(ip6a)); + proto_tree_add_text(rsvp_ero_subtree, offset2+l+18, 1, + "Prefix length: %d", pd[offset2+l+6]); + break; + + default: /* Unknown subobject */ + k = ((unsigned char)pd[offset2+l]) & 0x80; + ti2 = proto_tree_add_text(rsvp_object_tree, + offset2+l, pd[offset2+l+1], + "Unknown subobject: %d", j); + rsvp_ero_subtree = + proto_item_add_subtree(ti2, ett_rsvp_record_route_subobj); + proto_tree_add_text(rsvp_ero_subtree, offset2+l, 1, + k ? "Loose Hop " : "Strict Hop"); + proto_tree_add_text(rsvp_ero_subtree, offset2+l, 1, + "Type: %d (Unknown)", j); + proto_tree_add_text(rsvp_ero_subtree, offset2+l+1, 1, + "Length: %d", pd[offset2+l+1]); + + } + + l += ((unsigned char)pd[offset2+l+1]); + } + break; + } + + default: { + proto_tree_add_text(rsvp_object_tree, offset+3, 1, + "C-type: Unknown (%d)", + obj->type); + i = obj_length - sizeof(rsvp_object); + proto_tree_add_text(rsvp_object_tree, offset2, i, + "Data (%d bytes)", i); + break; + } + } + break; + default : rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_unknown_class); proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", @@ -1609,7 +1969,7 @@ dissect_rsvp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) default_class: i = obj_length - sizeof(rsvp_object); proto_tree_add_text(rsvp_object_tree, offset2, i, - "Data (%d bytes)", i); + "Data (%d bytes)", i); break; case RSVP_CLASS_NULL : @@ -1644,6 +2004,14 @@ proto_register_rsvp(void) &ett_rsvp_adspec_subtree, &ett_rsvp_integrity, &ett_rsvp_policy, + &ett_rsvp_label, + &ett_rsvp_label_request, + &ett_rsvp_session_attribute, + &ett_rsvp_session_attribute_flags, + &ett_rsvp_explicit_route, + &ett_rsvp_explicit_route_subobj, + &ett_rsvp_record_route, + &ett_rsvp_record_route_subobj, &ett_rsvp_unknown_class, }; |