wireshark/packet-rsvp.c
Guy Harris c57c848dfa Remove more "CHECK_DISPLAY_AS_DATA()" calls and "pinfo->current_proto ="
statements.

Move the setting of the Protocol column in various dissectors before
anything is fetched from the packet, and also clear the Info column at
that point in those and some other dissectors, so that if an exception
is thrown, the columns don't reflect the previous protocol.

Don't use

	col_add_fstr(..., "%s", string);

Use

	col_add_str(..., string);

as it does the same thing, but doesn't drag all the heavy *printf
machinery in.

Fix the DDTP dissector to set the Info column regardless of whether
we're building a protocol tree or not, and to set it to "Encrypted
payload" if the payload is encrypted.  Also fix a typo in a field name.

Register the FTP data dissector as being associated with the FTP data
protocol, not the FTP protocol (the removed "CHECK_DISPLAY_AS_DATA()"
call checked "proto_ftp_data", and the removed "pinfo->current_proto ="
line set it to "FTP-DATA", so it should be associated with
"proto_ftp_data").

Make the H1 dissector check whether the frame has at least 2 bytes in it
before checking the first two bytes; heuristic dissectors must not throw
exceptions until they've accepted the packet as one of theirs.

Use "tvb_format_text()" rather than "tvb_get_ptr()" and "format_text()"
in some dissectors where the result of "tvb_get_ptr()" is used only in
the "format_text()" call.

In the Quake dissector, don't check whether there are at least 4 bytes
in the packet - if we return, the packet won't be dissected at all (it's
not as if some other dissector will get to handle it), and, if we don't
return, we'll throw an exception if there aren't at least 4 bytes in the
packet, so the packet will be marked as short or malformed, as
appropriate.

In the RIPng dissector, associate the table of strings for the command
field with the command field, so that the dissector doesn't have to
format the string for the protocol tree entry itself, and so that the
filter construction dialog box can let you select "Request" or
"Response" from a list rather than requiring you to know the values for
"Request" and "Response".

Make "dissect_rpc()" static, as it's called only through a heuristic
dissector list.

Use "col_set_str()" to set the COL_PROTOCOL column for RPC protocols;
the string used is from a table provided by the dissector, and is a
string constant.

Don't format the Info column for WSP into a buffer and then format that
buffer into the column with "%s" - "col_add_fstr()" can do the
formatting for you, without having to allocate your own buffer (or run
through the *printf machinery twice).

Don't fetch fields from the WTP packet until you're ready to use them,
so that you don't throw an exception before you even set the Protocol
column or clear the Info column.

Use "pinfo->destport", not "pi.destport", in the Zebra dissector when
checking whether the packet is a request or reply, and do the check by
comparing with "pinfo->match_port" rather than TCP_PORT_ZEBRA (so that
if the dissector is ever registered on another port, it still correctly
determines whether the packet is a request or reply - the Network
Monitor HTTP dissector has port 80 wired into its brain, which is a bit
irritating if you're trying to get it to dissect HTTP proxy traffic on
port 3128 or proxy administration UI traffic on port 3132).

svn path=/trunk/; revision=2931
2001-01-22 08:03:46 +00:00

2048 lines
62 KiB
C

/* packet-rsvp.c
* Routines for RSVP packet disassembly
*
* (c) Copyright Ashok Narayanan <ashokn@cisco.com>
*
* $Id: packet-rsvp.c,v 1.33 2001/01/22 08:03:46 guy 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 disassemble RSVP packets, as defined in
* RFC 2205. All objects from RC2205 are supported, in IPv4 and IPv6 mode.
* In addition, the Integrated Services traffic specification objects
* 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>
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#include <glib.h>
#ifdef NEED_SNPRINTF_H
# include "snprintf.h"
#endif
#include "packet.h"
#include "packet-ip.h"
#include "packet-ipv6.h"
#include "ieee-float.h"
static int proto_rsvp = -1;
static gint ett_rsvp = -1;
static gint ett_rsvp_hdr = -1;
static gint ett_rsvp_session = -1;
static gint ett_rsvp_hop = -1;
static gint ett_rsvp_time_values = -1;
static gint ett_rsvp_error = -1;
static gint ett_rsvp_scope = -1;
static gint ett_rsvp_style = -1;
static gint ett_rsvp_confirm = -1;
static gint ett_rsvp_sender_template = -1;
static gint ett_rsvp_filter_spec = -1;
static gint ett_rsvp_sender_tspec = -1;
static gint ett_rsvp_flowspec = -1;
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;
/*
* RSVP message types
*/
typedef enum {
RSVP_MSG_PATH=1, RSVP_MSG_RESV, RSVP_MSG_PERR, RSVP_MSG_RERR,
RSVP_MSG_PTEAR, RSVP_MSG_RTEAR, RSVP_MSG_CONFIRM,
RSVP_MSG_RTEAR_CONFIRM=10
} rsvp_message_types;
static value_string message_type_vals[] = {
{RSVP_MSG_PATH, "PATH Message"},
{RSVP_MSG_RESV, "RESV Message"},
{RSVP_MSG_PERR, "PATH ERROR Message"},
{RSVP_MSG_RERR, "RESV ERROR Message"},
{RSVP_MSG_PTEAR, "PATH TEAR Message"},
{RSVP_MSG_RTEAR, "RESV TEAR Message"},
{RSVP_MSG_CONFIRM, "CONFIRM Message"},
{RSVP_MSG_RTEAR_CONFIRM, "RESV TEAR CONFIRM Message"},
{0, NULL}
};
/*
* RSVP classes
*/
#define MAX_RSVP_CLASS 15
enum rsvp_classes {
RSVP_CLASS_NULL=0,
RSVP_CLASS_SESSION,
RSVP_CLASS_HOP=3,
RSVP_CLASS_INTEGRITY,
RSVP_CLASS_TIME_VALUES,
RSVP_CLASS_ERROR,
RSVP_CLASS_SCOPE,
RSVP_CLASS_STYLE,
RSVP_CLASS_FLOWSPEC,
RSVP_CLASS_FILTER_SPEC,
RSVP_CLASS_SENDER_TEMPLATE,
RSVP_CLASS_SENDER_TSPEC,
RSVP_CLASS_ADSPEC,
RSVP_CLASS_POLICY,
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[] = {
{RSVP_CLASS_NULL, "NULL object"},
{RSVP_CLASS_SESSION, "SESSION object"},
{RSVP_CLASS_HOP, "HOP object"},
{RSVP_CLASS_INTEGRITY, "INTEGRITY object"},
{RSVP_CLASS_TIME_VALUES, "TIME VALUES object"},
{RSVP_CLASS_ERROR, "ERROR object"},
{RSVP_CLASS_SCOPE, "SCOPE object"},
{RSVP_CLASS_STYLE, "STYLE object"},
{RSVP_CLASS_FLOWSPEC, "FLOWSPEC object"},
{RSVP_CLASS_FILTER_SPEC, "FILTER SPEC object"},
{RSVP_CLASS_SENDER_TEMPLATE, "SENDER TEMPLATE object"},
{RSVP_CLASS_SENDER_TSPEC, "SENDER TSPEC object"},
{RSVP_CLASS_ADSPEC, "ADSPEC object"},
{RSVP_CLASS_POLICY, "POLICY 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"},
{0, NULL}
};
/*
* RSVP error values
*/
enum rsvp_error_types {
RSVP_ERROR_CONFIRM = 0,
RSVP_ERROR_ADMISSION,
RSVP_ERROR_POLICY,
RSVP_ERROR_NO_PATH,
RSVP_ERROR_NO_SENDER,
RSVP_ERROR_CONFLICT_RESV_STYLE,
RSVP_ERROR_UNKNOWN_RESV_STYLE,
RSVP_ERROR_CONFLICT_DEST_PORTS,
RSVP_ERROR_CONFLICT_SRC_PORTS,
RSVP_ERROR_PREEMPTED=12,
RSVP_ERROR_UNKNOWN_CLASS,
RSVP_ERROR_UNKNOWN_C_TYPE,
RSVP_ERROR_TRAFFIC = 21,
RSVP_ERROR_TRAFFIC_SYSTEM,
RSVP_ERROR_SYSTEM
};
static value_string rsvp_error_vals[] = {
{RSVP_ERROR_CONFIRM, "Confirmation"},
{RSVP_ERROR_ADMISSION, "Admission Control Failure "},
{RSVP_ERROR_POLICY, "Policy Control Failure"},
{RSVP_ERROR_NO_PATH, "No PATH information for this RESV message"},
{RSVP_ERROR_NO_SENDER, "No sender information for this RESV message"},
{RSVP_ERROR_CONFLICT_RESV_STYLE, "Conflicting reservation styles"},
{RSVP_ERROR_UNKNOWN_RESV_STYLE, "Unknown reservation style"},
{RSVP_ERROR_CONFLICT_DEST_PORTS, "Conflicting destination ports"},
{RSVP_ERROR_CONFLICT_SRC_PORTS, "Conflicting source ports"},
{RSVP_ERROR_PREEMPTED, "Service preempted"},
{RSVP_ERROR_UNKNOWN_CLASS, "Unknown object class"},
{RSVP_ERROR_UNKNOWN_C_TYPE, "Unknown object C-type"},
{RSVP_ERROR_TRAFFIC, "Traffic Control Error"},
{RSVP_ERROR_TRAFFIC_SYSTEM, "Traffic Control System Error"},
{0, NULL}
};
/*
* Defines the reservation style plus style-specific information that
* is not a FLOWSPEC or FILTER_SPEC object, in a RESV message.
*/
#define RSVP_DISTINCT (1 << 3)
#define RSVP_SHARED (2 << 3)
#define RSVP_SHARING_MASK (RSVP_DISTINCT | RSVP_SHARED)
#define RSVP_SCOPE_WILD 1
#define RSVP_SCOPE_EXPLICIT 2
#define RSVP_SCOPE_MASK 0x07
#define RSVP_WF (RSVP_SHARED | RSVP_SCOPE_WILD)
#define RSVP_FF (RSVP_DISTINCT | RSVP_SCOPE_EXPLICIT)
#define RSVP_SE (RSVP_SHARED | RSVP_SCOPE_EXPLICIT)
static value_string style_vals[] = {
{ RSVP_WF, "Wildcard Filter" },
{ RSVP_FF, "Fixed Filter" },
{ RSVP_SE, "Shared-Explicit" },
{ 0, NULL }
};
/*------------------------------*
* Object definitions
*------------------------------*/
/*
* Base RSVP object
*/
typedef struct {
guint16 length;
guint8 class;
guint8 type;
/* Data follows, as a sequence of bytes */
} rsvp_object;
/*
* RSVP message header
*/
typedef struct {
guint8 ver_flags; /* RSVP Version & flags */
guint8 message_type; /* type of message */
guint16 cksum; /* IP Checksum */
guint8 sending_ttl; /* ttl of message */
guint8 reserved_byte; /* reserved */
guint16 rsvp_length; /* length of RSVP data */
/* Objects follow, as a sequence of "rsvp_object"s */
} rsvp_header;
/*
* NULL object
*/
typedef struct {
rsvp_object base;
} rsvp_null;
/*
* SESSION object
*/
typedef struct {
rsvp_object base;
guint32 destination;
guint8 protocol;
guint8 flags;
guint16 port;
} rsvp_session_ipv4;
typedef struct {
rsvp_object base;
struct e_in6_addr destination;
guint8 protocol;
guint8 flags;
guint16 port;
} rsvp_session_ipv6;
/*
* HOP object
* Can be a PHOP or a NHOP
*/
typedef struct {
rsvp_object base;
guint32 neighbor;
guint32 lif_handle;
} rsvp_hop_ipv4;
typedef struct {
rsvp_object base;
struct e_in6_addr neighbor;
guint32 lif_handle;
} rsvp_hop_ipv6;
/*
* TIME_VALUES object
*/
typedef struct {
rsvp_object base;
gint32 refresh_ms;
} rsvp_time_values;
/*
* ERROR object
*/
typedef struct {
rsvp_object base;
guint32 error_node;
guint8 flags;
guint8 error_code;
guint16 error_value;
} rsvp_error_ipv4;
typedef struct {
rsvp_object base;
struct e_in6_addr error_node;
guint8 flags;
guint8 error_code;
guint16 error_value;
} rsvp_error_ipv6;
/*
* CONFIRM object
*/
typedef struct {
rsvp_object base;
guint32 receiver;
} rsvp_confirm_ipv4;
typedef struct {
rsvp_object base;
struct e_in6_addr receiver;
} rsvp_confirm_ipv6;
/*
* SCOPE object
*/
typedef struct {
rsvp_object base;
/* Source follows, as a sequence of 32-bit integers */
} rsvp_scope;
/*
* STYLE object
*/
typedef struct {
rsvp_object base;
guint32 reservation_type;
} rsvp_style;
/*
* Defines a subset of session data packets that should receive the
* desired QoS (specified by an FLOWSPEC object), in a RESV message.
*/
typedef struct {
rsvp_object base;
guint32 source; /* source sending data */
guint16 unused;
guint16 udp_source_port; /* port number */
} rsvp_filter_ipv4;
/*
* Contains a sender IP address and perhaps some additional
* demultiplexing information to identify a sender, in a PATH
* message.
*/
typedef struct {
rsvp_object base;
guint32 source; /* source sending data */
guint16 __reserved;
guint16 source_port; /* port number */
} rsvp_template_ipv4;
typedef struct {
rsvp_object base;
struct e_in6_addr source; /* source sending data */
guint16 __reserved;
guint16 source_port; /* port number */
} rsvp_template_ipv6;
/*
* Defines a desired QoS, in a RESV message.
*/
enum qos_service_type {
QOS_QUALITATIVE = 128, /* Qualitative service */
QOS_CONTROLLED_LOAD= 5, /* Controlled Load Service */
QOS_GUARANTEED = 2, /* Guaranteed service */
QOS_TSPEC = 1 /* Traffic specification */
};
static value_string qos_vals[] = {
{ QOS_QUALITATIVE, "Qualitative QoS" },
{ QOS_CONTROLLED_LOAD, "Controlled-load QoS" },
{ QOS_GUARANTEED, "Guaranteed rate QoS" },
{ QOS_TSPEC, "Traffic specification" },
{ 0, NULL }
};
static value_string svc_vals[] = {
{ 127, "Token bucket TSpec" },
{ 128, "Qualitative TSpec" },
{ 130, "Guaranteed-rate RSpec" },
{ 0, NULL }
};
enum rsvp_spec_types { INTSRV = 2 };
enum intsrv_services {
INTSRV_GENERAL = 1,
INTSRV_GTD = 2,
INTSRV_CLOAD = 5,
INTSRV_QUALITATIVE = 128
};
static value_string intsrv_services_str[] = {
{INTSRV_GENERAL, "Default General Parameters"},
{INTSRV_GTD, "Guaranteed"},
{INTSRV_CLOAD, "Controlled Load"},
{INTSRV_QUALITATIVE, "Qualitative"},
{ 0, NULL }
};
enum intsrv_field_name {
INTSRV_NON_IS_HOPS = 1, INTSRV_COMPOSED_NON_IS_HOPS,
INTSRV_IS_HOPS, INTSRV_COMPOSED_IS_HOPS,
INTSRV_PATH_BANDWIDTH, INTSRV_MIN_PATH_BANDWIDTH,
INTSRV_IF_LATENCY, INTSRV_PATH_LATENCY,
INTSRV_MTU, INTSRV_COMPOSED_MTU,
INTSRV_TOKEN_BUCKET_TSPEC = 127,
INTSRV_QUALITATIVE_TSPEC = 128,
INTSRV_GTD_RSPEC = 130,
INTSRV_DELAY = 131, /* Gtd Parameter C - Max Delay Bound - bytes */
INTSRV_MAX_JITTER, /* Gtd Parameter D - Max Jitter */
INTSRV_E2E_DELAY, /* Gtd Parameter Ctot */
INTSRV_E2E_MAX_JITTER, /* Gtd Parameter Dtot */
INTSRV_SHP_DELAY, /* Gtd Parameter Csum */
INTSRV_SHP_MAX_JITTER /* Gtd Parameter Dsum */
};
/*
* Subobjects for Integrated Services
*/
typedef struct {
guint8 service_num;
guint8 break_bit;
guint16 length;
} service_hdr;
typedef struct {
service_hdr svchdr;
guint8 param_id;
guint8 flags_tspec;
guint16 parameter_length;
guint32 rate;
guint32 depth;
guint32 peak;
guint32 min_unit;
guint32 max_unit;
} IS_tspec; /* RFC2210 */
typedef struct {
service_hdr svchdr;
guint8 param_id;
guint8 flags_tspec;
guint16 parameter_length;
guint32 max_unit;
} QUAL_tspec; /* Qualitative */
typedef struct {
rsvp_object base;
guint8 version;
guint8 __reserved_;
guint16 length_in_words;
/* Data follows, as a sequence of bytes */
} rsvp_tspec;
typedef struct {
guint8 param_id;
guint8 flags_rspec;
guint16 param2_length;
guint32 requested_rate;
guint32 slack;
} IS_rspec;
typedef struct {
IS_tspec tspec;
IS_rspec rspec;
} IS_flowspec; /* RFC 2210 */
typedef struct {
service_hdr svchdr;
guint8 param_id;
guint8 flags_tspec;
guint16 parameter_length;
guint32 max_unit;
} QUAL_flowspec; /* Qualitative */
typedef struct {
rsvp_object base;
guint8 version;
guint8 __reserved_;
guint16 length_in_words;
/* Data follows, as a sequence of bytes */
} rsvp_flowspec;
typedef struct {
guint8 id;
guint8 flags;
guint16 length;
guint32 dataval;
} param_hdr;
static value_string adspec_params[] = {
{4, "IS Hop Count"},
{6, "Path b/w estimate"},
{8, "Minimum path latency"},
{10, "Composed MTU"},
{133, "End-to-end composed value for C"},
{134, "End-to-end composed value for D"},
{135, "Since-last-reshaping point composed C"},
{136, "Since-last-reshaping point composed D"},
{ 0, NULL }
};
/* -------------------- Stuff for MPLS/TE objects -------------------- */
typedef struct {
rsvp_object base;
} label; /* array of 32-bit labels follows */
typedef struct {
rsvp_object base;
guint16 _reserved;
guint16 l3pid;
} label_request;
typedef struct {
rsvp_object base;
guint8 setup_prio;
guint8 hold_prio;
guint8 flags;
guint8 name_len;
} session_attribute; /* name follows, as string */
static const value_string proto_vals[] = { {IP_PROTO_ICMP, "ICMP"},
{IP_PROTO_IGMP, "IGMP"},
{IP_PROTO_TCP, "TCP" },
{IP_PROTO_UDP, "UDP" },
{IP_PROTO_OSPF, "OSPF"},
{0, NULL } };
/* Filter keys */
enum rsvp_filter_keys {
/* Message types */
RSVPF_MSG, /* Message type */
/* Shorthand for message types */
RSVPF_PATH,
RSVPF_RESV,
RSVPF_PATHERR,
RSVPF_RESVERR,
RSVPF_PATHTEAR,
RSVPF_RESVTEAR,
RSVPF_RCONFIRM,
RSVPF_JUNK_MSG8,
RSVPF_JUNK_MSG9,
RSVPF_RTEARCONFIRM,
/* Does the message contain an object of this type? */
RSVPF_OBJECT,
/* Object present shorthands */
RSVPF_SESSION,
RSVPF_DUMMY_1,
RSVPF_HOP,
RSVPF_INTEGRITY,
RSVPF_TIME_VALUES,
RSVPF_ERROR,
RSVPF_SCOPE,
RSVPF_STYLE,
RSVPF_FLOWSPEC,
RSVPF_FILTER_SPEC,
RSVPF_SENDER,
RSVPF_TSPEC,
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
};
static int rsvp_filter[RSVPF_MAX];
static hf_register_info rsvpf_info[] = {
/* Message type number */
{&rsvp_filter[RSVPF_MSG],
{ "Message Type", "rsvp.msg", FT_UINT8, BASE_NONE, message_type_vals, 0x0,
"" }},
/* Message type shorthands */
{&rsvp_filter[RSVPF_PATH],
{ "Path Message", "rsvp.path", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"" }},
{&rsvp_filter[RSVPF_RESV],
{ "Resv Message", "rsvp.resv", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"" }},
{&rsvp_filter[RSVPF_PATHERR],
{ "Path Error Message", "rsvp.perr", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"" }},
{&rsvp_filter[RSVPF_RESVERR],
{ "Resv Error Message", "rsvp.rerr", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"" }},
{&rsvp_filter[RSVPF_PATHTEAR],
{ "Path Tear Message", "rsvp.ptear", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"" }},
{&rsvp_filter[RSVPF_RESVTEAR],
{ "Resv Tear Message", "rsvp.rtear", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"" }},
{&rsvp_filter[RSVPF_RCONFIRM],
{ "Resv Confirm Message", "rsvp.resvconf", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"" }},
{&rsvp_filter[RSVPF_RTEARCONFIRM],
{ "Resv Tear Confirm Message", "rsvp.rtearconf", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"" }},
/* Object present */
{&rsvp_filter[RSVPF_OBJECT],
{ "", "rsvp.object", FT_UINT8, BASE_NONE, rsvp_class_vals, 0x0,
"" }},
/* Object present shorthands */
{&rsvp_filter[RSVPF_SESSION],
{ "SESSION", "rsvp.session", FT_UINT8, BASE_NONE, NULL, 0x0,
"" }},
{&rsvp_filter[RSVPF_HOP],
{ "HOP", "rsvp.hop", FT_UINT8, BASE_NONE, NULL, 0x0,
"" }},
{&rsvp_filter[RSVPF_INTEGRITY],
{ "INTEGRITY", "rsvp.integrity", FT_UINT8, BASE_NONE, NULL, 0x0,
"" }},
{&rsvp_filter[RSVPF_TIME_VALUES],
{ "TIME VALUES", "rsvp.time", FT_UINT8, BASE_NONE, NULL, 0x0,
"" }},
{&rsvp_filter[RSVPF_ERROR],
{ "ERROR", "rsvp.error", FT_UINT8, BASE_NONE, NULL, 0x0,
"" }},
{&rsvp_filter[RSVPF_SCOPE],
{ "SCOPE", "rsvp.scope", FT_UINT8, BASE_NONE, NULL, 0x0,
"" }},
{&rsvp_filter[RSVPF_STYLE],
{ "STYLE", "rsvp.style", FT_UINT8, BASE_NONE, NULL, 0x0,
"" }},
{&rsvp_filter[RSVPF_FLOWSPEC],
{ "FLOWSPEC", "rsvp.flowspec", FT_UINT8, BASE_NONE, NULL, 0x0,
"" }},
{&rsvp_filter[RSVPF_FILTER_SPEC],
{ "FILTERSPEC", "rsvp.filter", FT_UINT8, BASE_NONE, NULL, 0x0,
"" }},
{&rsvp_filter[RSVPF_SENDER],
{ "SENDER TEMPLATE", "rsvp.sender", FT_UINT8, BASE_NONE, NULL, 0x0,
"" }},
{&rsvp_filter[RSVPF_TSPEC],
{ "SENDER TSPEC", "rsvp.tspec", FT_UINT8, BASE_NONE, NULL, 0x0,
"" }},
{&rsvp_filter[RSVPF_ADSPEC],
{ "ADSPEC", "rsvp.adspec", FT_UINT8, BASE_NONE, NULL, 0x0,
"" }},
{&rsvp_filter[RSVPF_POLICY],
{ "POLICY", "rsvp.policy", FT_UINT8, BASE_NONE, NULL, 0x0,
"" }},
{&rsvp_filter[RSVPF_CONFIRM],
{ "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,
"" }},
/* Session fields */
{&rsvp_filter[RSVPF_SESSION_IP],
{ "Destination address", "rsvp.session.ip", FT_IPv4, BASE_NONE, NULL, 0x0,
"" }},
{&rsvp_filter[RSVPF_SESSION_PORT],
{ "Port number", "rsvp.session.port", FT_UINT16, BASE_NONE, NULL, 0x0,
"" }},
{&rsvp_filter[RSVPF_SESSION_PROTO],
{ "Protocol", "rsvp.session.proto", FT_UINT8, BASE_NONE, VALS(proto_vals), 0x0,
"" }},
{&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 IPv4 address", "rsvp.sender.ip", FT_IPv4, BASE_NONE, NULL, 0x0,
"" }},
{&rsvp_filter[RSVPF_SENDER_PORT],
{ "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,
"" }}
};
static inline int rsvp_class_to_filter_num(int classnum)
{
switch(classnum) {
case RSVP_CLASS_SESSION :
case RSVP_CLASS_HOP :
case RSVP_CLASS_INTEGRITY :
case RSVP_CLASS_TIME_VALUES :
case RSVP_CLASS_ERROR :
case RSVP_CLASS_SCOPE :
case RSVP_CLASS_STYLE :
case RSVP_CLASS_FLOWSPEC :
case RSVP_CLASS_FILTER_SPEC :
case RSVP_CLASS_SENDER_TEMPLATE :
case RSVP_CLASS_SENDER_TSPEC :
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 void
dissect_rsvp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
{
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 *object_type;
rsvp_header *hdr;
rsvp_object *obj;
int i, j, k, l, len, mylen;
int msg_length;
int obj_length;
int offset2;
struct e_in6_addr *ip6a;
guint32 ip_addr;
if (check_col(fd, COL_PROTOCOL))
col_set_str(fd, COL_PROTOCOL, "RSVP");
if (check_col(fd, COL_INFO))
col_clear(fd, COL_INFO);
hdr = (rsvp_header *)&pd[offset];
if (check_col(fd, COL_INFO)) {
col_add_str(fd, COL_INFO,
val_to_str(hdr->message_type, message_type_vals, "Unknown (%u)"));
}
if (tree) {
msg_length = pntohs(pd+offset+6);
ti = proto_tree_add_item(tree, proto_rsvp, NullTVB, offset, msg_length, FALSE);
rsvp_tree = proto_item_add_subtree(ti, ett_rsvp);
ti = proto_tree_add_text(rsvp_tree, NullTVB, offset,
sizeof(rsvp_header), "RSVP Header");
rsvp_header_tree = proto_item_add_subtree(ti, ett_rsvp_hdr);
proto_tree_add_text(rsvp_header_tree, NullTVB, offset, 1, "RSVP Version: %u",
(hdr->ver_flags & 0xf0)>>4);
proto_tree_add_text(rsvp_header_tree, NullTVB, offset, 1, "Flags: %02X",
hdr->ver_flags & 0xf);
proto_tree_add_uint(rsvp_header_tree, rsvp_filter[RSVPF_MSG], NullTVB,
offset+1, 1, hdr->message_type);
if (hdr->message_type <= RSVPF_RTEARCONFIRM &&
hdr->message_type != RSVPF_JUNK_MSG8 &&
hdr->message_type != RSVPF_JUNK_MSG9 ) {
proto_tree_add_boolean_hidden(rsvp_header_tree, rsvp_filter[RSVPF_MSG + hdr->message_type], NullTVB,
offset+1, 1, 1);
}
proto_tree_add_text(rsvp_header_tree, NullTVB, offset + 2 , 2, "Message Checksum");
proto_tree_add_text(rsvp_header_tree, NullTVB, offset + 4 , 1, "Sending TTL: %u",
hdr->sending_ttl);
proto_tree_add_text(rsvp_header_tree, NullTVB, offset + 6 , 2, "Message length: %d",
msg_length);
offset += sizeof(rsvp_header);
len = 0;
while (len + sizeof(rsvp_header) < msg_length) {
obj = (rsvp_object *)&pd[offset];
obj_length = pntohs(pd+offset);
if (!BYTES_ARE_IN_FRAME(offset, obj_length)) {
proto_tree_add_text(rsvp_tree, NullTVB, offset, 1,
"Further data not captured");
break;
}
object_type = match_strval(obj->class, rsvp_class_vals);
if (!object_type) object_type = "Unknown";
ti = proto_tree_add_uint_hidden(rsvp_tree, rsvp_filter[RSVPF_OBJECT], NullTVB,
offset, obj_length, obj->class);
ti = proto_tree_add_uint(rsvp_tree, rsvp_filter[rsvp_class_to_filter_num(obj->class)], NullTVB,
offset, obj_length, obj->class);
offset2 = offset + sizeof(rsvp_object);
switch(obj->class) {
case RSVP_CLASS_SESSION :
rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_session);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d",
obj_length);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1,
"Class number: %u - %s",
obj->class, object_type);
switch(obj->type) {
case 1: {
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: 1 - IPv4");
memcpy(&ip_addr, pd+offset2, 4);
proto_tree_add_ipv4(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_IP], NullTVB,
offset2, 4, ip_addr);
proto_tree_add_uint(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_PROTO], NullTVB,
offset2+4, 1, *(pd+offset2+4));
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+5, 1,
"Flags: %x", pntohs(pd+offset2+5));
proto_tree_add_uint(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_PORT], NullTVB,
offset2+6, 2, pntohs(pd+offset2+6));
break;
}
case 2: {
rsvp_session_ipv6 *sess = (rsvp_session_ipv6 *)obj;
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: 2 - IPv6");
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 4,
"Destination address: %s",
ip6_to_str(&(sess->destination)));
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+16, 1,
"Protocol: %u", sess->protocol);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+17, 1,
"Flags: %x", sess->flags);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+18, 2,
"Destination port: %u",
pntohs(pd+offset2+18));
break;
}
case 7: {
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: 7 - IPv4 LSP");
memcpy(&ip_addr, pd+offset2, 4);
proto_tree_add_ipv4(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_IP], NullTVB,
offset2, 4, ip_addr);
proto_tree_add_uint(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_TUNNEL_ID], NullTVB,
offset2+6, 2, pntohs(pd+offset2+6));
memcpy(&ip_addr, pd+offset2+8, 4);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+8, 4,
"Extended Tunnel ID: %lu (%s)",
(unsigned long)ntohl(ip_addr),
ip_to_str(pd+offset2+8));
proto_tree_add_uint_hidden(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_EXT_TUNNEL_ID], NullTVB,
offset2+8, 4, ip_addr);
break;
}
default: {
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: Unknown (%u)",
obj->type);
i = obj_length - sizeof(rsvp_object);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
"Data (%d bytes)", i);
}
}
break;
case RSVP_CLASS_HOP :
rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_hop);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d",
obj_length);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1,
"Class number: %u - %s",
obj->class, object_type);
switch(obj->type) {
case 1: {
rsvp_hop_ipv4 *hop = (rsvp_hop_ipv4 *)obj;
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: 1 - IPv4");
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 4,
"Neighbor address: %s",
ip_to_str((guint8 *) &(hop->neighbor)));
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+4, 4,
"Logical interface: %0x",
pntohl(pd+offset2+4));
break;
}
case 2: {
rsvp_hop_ipv6 *hop = (rsvp_hop_ipv6 *)obj;
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: 2 - IPv6");
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 4,
"Neighbor address: %s",
ip6_to_str(&(hop->neighbor)));
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+16, 4,
"Logical interface: %0x",
pntohl(pd+offset2+16));
break;
}
default: {
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: Unknown (%u)",
obj->type);
i = obj_length - sizeof(rsvp_object);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
"Data (%d bytes)", i);
}
}
break;
case RSVP_CLASS_TIME_VALUES :
rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_time_values);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d",
obj_length);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1,
"Class number: %u - %s",
obj->class, object_type);
switch(obj->type) {
case 1: {
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: 1");
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 4,
"Refresh interval: %u ms (%u seconds)",
pntohl(pd+offset2),
pntohl(pd+offset2)/1000);
break;
}
default: {
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: Unknown (%u)",
obj->type);
i = obj_length - sizeof(rsvp_object);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
"Data (%d bytes)", i);
break;
}
}
break;
case RSVP_CLASS_ERROR :
rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_error);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d",
obj_length);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1,
"Class number: %u - %s",
obj->class, object_type);
switch(obj->type) {
case 1: {
rsvp_error_ipv4 *err = (rsvp_error_ipv4 *)obj;
char *err_str = match_strval(err->error_code, rsvp_error_vals);
if (!err_str) err_str = "Unknown";
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: 1 - IPv4");
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 4,
"Error node: %s",
ip_to_str((guint8 *) &(err->error_node)));
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+4, 1,
"Flags: %02x", err->flags);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+5, 1,
"Error code: %u - %s", err->error_code,
err_str);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+6, 2,
"Error value: %u", pntohs(pd+offset2+6));
break;
}
case 2: {
rsvp_error_ipv6 *err = (rsvp_error_ipv6 *)obj;
char *err_str = match_strval(err->error_code, rsvp_error_vals);
if (!err_str) err_str = "Unknown";
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: 2 - IPv6");
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 4,
"Error node: %s",
ip6_to_str(&(err->error_node)));
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+16, 1,
"Flags: %02x", err->flags);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+17, 1,
"Error code: %u - %s", err->error_code,
err_str);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+18, 2,
"Error value: %u", pntohs(pd+offset2+18));
break;
}
default: {
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: Unknown (%u)",
obj->type);
i = obj_length - sizeof(rsvp_object);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
"Data (%d bytes)", i);
}
}
break;
case RSVP_CLASS_SCOPE :
mylen = obj_length;
rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_scope);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d",
obj_length);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1,
"Class number: %u - %s",
obj->class, object_type);
switch(obj->type) {
case 1: {
unsigned long ip;
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: 1 - IPv4");
while (mylen > sizeof(rsvp_object)) {
ip = pntohl(pd+offset2);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 4,
"IPv4 Address: %s",
ip_to_str((guint8 *) &ip));
offset2 += 4;
mylen -= 4;
}
break;
}
case 2: {
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: 2 - IPv6");
while (mylen>sizeof(rsvp_object)) {
ip6a = (struct e_in6_addr *)pd+offset2;
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 16,
"IPv6 Address: %s",
ip6_to_str(ip6a));
offset2 += 16;
mylen -= 16;
}
break;
}
default: {
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: Unknown (%u)",
obj->type);
i = obj_length - sizeof(rsvp_object);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
"Data (%d bytes)", i);
}
}
break;
case RSVP_CLASS_STYLE :
rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_style);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d",
obj_length);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1,
"Class number: %u - %s",
obj->class, object_type);
switch(obj->type) {
case 1: {
unsigned long ip = pntohl(pd+offset2);
char *style_str = match_strval(ip, style_vals);
if (!style_str) style_str = "Unknown";
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: 1");
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+5, 1,
"Style: %lu - %s", ip, style_str);
break;
}
default: {
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: Unknown (%u)",
obj->type);
i = obj_length - sizeof(rsvp_object);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
"Data (%d bytes)", i);
break;
}
}
break;
case RSVP_CLASS_CONFIRM :
rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_confirm);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d",
obj_length);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1,
"Class number: %u - %s",
obj->class, object_type);
switch(obj->type) {
case 1: {
rsvp_confirm_ipv4 *confirm = (rsvp_confirm_ipv4 *)obj;
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: 1 - IPv4");
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 4,
"Receiver address: %s",
ip_to_str((guint8 *) &(confirm->receiver)));
break;
}
case 2: {
rsvp_confirm_ipv6 *confirm = (rsvp_confirm_ipv6 *)obj;
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: 2 - IPv6");
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 16,
"Receiver address: %s",
ip6_to_str(&(confirm->receiver)));
break;
}
default: {
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: Unknown (%u)",
obj->type);
i = obj_length - sizeof(rsvp_object);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
"Data (%d bytes)", i);
}
}
break;
case RSVP_CLASS_SENDER_TEMPLATE :
rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_sender_template);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d",
obj_length);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1,
"Class number: %u - %s",
obj->class, object_type);
goto common_template;
case RSVP_CLASS_FILTER_SPEC :
rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_filter_spec);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d",
obj_length);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1,
"Class number: %u - %s",
obj->class, object_type);
common_template:
switch(obj->type) {
case 1: {
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: 1 - IPv4");
memcpy(&ip_addr, pd+offset2, 4);
proto_tree_add_ipv4(rsvp_object_tree, rsvp_filter[RSVPF_SENDER_IP], NullTVB,
offset2, 4, ip_addr);
proto_tree_add_uint(rsvp_object_tree, rsvp_filter[RSVPF_SENDER_PORT], NullTVB,
offset2+6, 2, pntohs(pd+offset2+6));
break;
}
case 2: {
rsvp_template_ipv6 *tem = (rsvp_template_ipv6 *)obj;
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: 2 - IPv6");
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 16,
"Source address: %s",
ip6_to_str(&(tem->source)));
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+18, 2,
"Source port: %u", pntohs(pd+offset2+18));
break;
}
case 7: {
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: 7 - IPv4 LSP");
memcpy(&ip_addr, pd+offset2, 4);
proto_tree_add_ipv4(rsvp_object_tree, rsvp_filter[RSVPF_SENDER_IP], NullTVB,
offset2, 4, ip_addr);
proto_tree_add_uint(rsvp_object_tree, rsvp_filter[RSVPF_SENDER_LSP_ID], NullTVB,
offset2+6, 2, pntohs(pd+offset2+6));
break;
}
default: {
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: Unknown (%u)",
obj->type);
i = obj_length - sizeof(rsvp_object);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
"Data (%d bytes)", i);
}
}
break;
case RSVP_CLASS_SENDER_TSPEC : {
rsvp_tspec *tspec = (rsvp_tspec *)obj;
IS_tspec *ist;
QUAL_tspec *qt;
service_hdr *sh;
char *str;
mylen = obj_length;
rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_sender_tspec);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d",
obj_length);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1,
"Class number: %u - %s",
obj->class, object_type);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1,
"Message format version: %u",
tspec->version>>4);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2,
"Data length: %u words, not including header",
pntohs(pd+offset2+2));
mylen -=4;
offset2 +=4;
while (mylen > 4) {
sh = (service_hdr *)(pd+offset2);
str = match_strval(sh->service_num, qos_vals);
if (!str) str = "Unknown";
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1,
"Service header: %u - %s",
sh->service_num, str);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2,
"Length of service %u data: %u words, "
"not including header",
sh->service_num,
ntohs(sh->length));
offset2+=4; mylen -=4;
switch(sh->service_num) {
case QOS_TSPEC :
ist = (IS_tspec *)sh;
/* Token bucket TSPEC */
str = match_strval(ist->param_id, svc_vals);
if (!str) str = "Unknown";
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1,
"Parameter %u - %s",
ist->param_id, str);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+1, 1,
"Parameter %u flags: %x",
ist->param_id, ist->flags_tspec);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2,
"Parameter %u data length: %u words, "
"not including header",
ist->param_id,
/* pntohs(pd+offset2+10)); */
ntohs(ist->parameter_length));
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+4, 4,
"Token bucket rate: %ld",
pieee_to_long(pd+offset2+4));
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+8, 4,
"Token bucket size: %ld",
pieee_to_long(pd+offset2+8));
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+12, 4,
"Peak data rate: %ld",
pieee_to_long(pd+offset2+12));
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+16, 4,
"Minimum policed unit: %u",
pntohl(pd+offset2+16));
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+20, 4,
"Maximum policed unit: %u",
pntohl(pd+offset2+20));
break;
case QOS_QUALITATIVE :
qt = (QUAL_tspec *)sh;
/* Token bucket TSPEC */
str = match_strval(qt->param_id, svc_vals);
if (!str) str = "Unknown";
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1,
"Parameter %u - %s",
qt->param_id, str);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+1, 1,
"Parameter %u flags: %x",
qt->param_id, qt->flags_tspec);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2,
"Parameter %u data length: %u words, "
"not including header",
qt->param_id,
/* pntohs(pd+offset2+10)); */
ntohs(qt->parameter_length));
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+4, 4,
"Maximum policed unit: %u",
pntohl(pd+offset2+4));
break;
}
offset2 += ntohs(sh->length)*4;
mylen -= ntohs(sh->length)*4;
}
break;
}
case RSVP_CLASS_FLOWSPEC : {
rsvp_flowspec *flowspec = (rsvp_flowspec *)obj;
IS_flowspec *isf;
QUAL_flowspec *qf;
service_hdr *sh;
int mylen;
char *str;
mylen = obj_length;
rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_flowspec);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d",
obj_length);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1,
"Class number: %u - %s",
obj->class, object_type);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1,
"Message format version: %u",
flowspec->version>>4);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2,
"Data length: %u words, not including header",
pntohs(pd+offset2+2));
mylen -=4;
offset2+=4;
while (mylen > 4) {
sh = (service_hdr *)(pd+offset2);
str = match_strval(sh->service_num, intsrv_services_str);
if (!str) str = "Unknown";
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1,
"Service header: %u - %s",
sh->service_num, str);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2,
"Length of service %u data: %u words, "
"not including header",
sh->service_num,
ntohs(sh->length));
offset2+=4; mylen -=4;
switch(sh->service_num) {
case QOS_CONTROLLED_LOAD :
case QOS_GUARANTEED :
/* Treat both these the same for now */
isf = (IS_flowspec *)sh;
str = match_strval(isf->tspec.param_id, svc_vals);
if (!str) str = "Unknown";
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1,
"Parameter %u - %s",
isf->tspec.param_id, str);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+1, 1,
"Parameter %u flags: %x",
isf->tspec.param_id, isf->tspec.flags_tspec);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2,
"Parameter %u data length: %u words, "
"not including header",
isf->tspec.param_id,
ntohs(isf->tspec.parameter_length));
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+4, 4,
"Token bucket rate: %ld",
pieee_to_long(pd+offset2+4));
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+8, 4,
"Token bucket size: %ld",
pieee_to_long(pd+offset2+8));
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+12, 4,
"Peak data rate: %ld",
pieee_to_long(pd+offset2+12));
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+16, 4,
"Minimum policed unit: %u",
pntohl(pd+offset2+16));
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+20, 4,
"Maximum policed unit: %u",
pntohl(pd+offset2+20));
if (sh->service_num!=QOS_GUARANTEED)
break;
/* Guaranteed-rate RSpec */
str = match_strval(isf->rspec.param_id, svc_vals);
if (!str) str="Unknown";
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+24, 1,
"Parameter %u - %s",
isf->rspec.param_id, str);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+25, 1,
"Parameter %u flags: %x",
isf->rspec.param_id, isf->rspec.flags_rspec);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+26, 2,
"Parameter %u data length: %u words, "
"not including header",
isf->rspec.param_id,
ntohs(isf->rspec.param2_length));
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+28, 4,
"Rate: %ld",
pieee_to_long(pd+offset2+28));
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+32, 4,
"Slack term: %u",
pntohl(pd+offset2+32));
break;
case QOS_QUALITATIVE :
qf = (QUAL_flowspec *)sh;
str = match_strval(qf->param_id, svc_vals);
if (!str) str = "Unknown";
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1,
"Parameter %u - %s",
qf->param_id, str);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+1, 1,
"Parameter %u flags: %x",
qf->param_id, qf->flags_tspec);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2,
"Parameter %u data length: %u words, "
"not including header",
qf->param_id,
ntohs(qf->parameter_length));
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+4, 4,
"Maximum policed unit: %u",
pntohl(pd+offset2+4));
break;
}
offset2 += ntohs(sh->length)*4;
mylen -= ntohs(sh->length)*4;
}
break;
}
case RSVP_CLASS_ADSPEC : {
proto_tree *adspec_tree;
service_hdr *shdr;
param_hdr *phdr;
char *str;
mylen = obj_length;
rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_adspec);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d",
obj_length);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1,
"Class number: %u - %s",
obj->class, object_type);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1,
"Message format version: %u",
(*((unsigned char *)pd+offset2))>>4);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2,
"Data length: %u words, not including header",
pntohs(pd+offset2+2));
offset2+=4;
mylen -= 4;
while (mylen > 4) {
shdr = (service_hdr *)(pd + offset2);
str = match_strval(shdr->service_num, intsrv_services_str);
ti = proto_tree_add_text(rsvp_object_tree, NullTVB, offset2,
(pntohs(&shdr->length)+1)<<2,
str?str:"Unknown");
adspec_tree = proto_item_add_subtree(ti,
ett_rsvp_adspec_subtree);
proto_tree_add_text(adspec_tree, NullTVB, offset2, 1,
"Service header %u - %s",
shdr->service_num, str);
proto_tree_add_text(adspec_tree, NullTVB, offset2+1, 1,
(shdr->break_bit&0x80)?
"Break bit set":"Break bit not set");
proto_tree_add_text(adspec_tree, NullTVB, offset2+2, 2,
"Data length: %u words, not including header",
pntohs(&shdr->length));
offset2+=4; i=(pntohs(&shdr->length)+1)<<2; mylen-=4;
while (i>4) {
phdr = (param_hdr *)(pd + offset2);
str = match_strval(phdr->id, adspec_params);
if (str) {
switch(phdr->id) {
case 4:
case 8:
case 10:
case 133:
case 134:
case 135:
case 136:
/* 32-bit unsigned integer */
proto_tree_add_text(adspec_tree, NullTVB, offset2,
(pntohs(&phdr->length)+1)<<2,
"%s - %lu (type %u, length %u)",
str,
(unsigned long)pntohl(&phdr->dataval),
phdr->id, pntohs(&phdr->length));
break;
case 6:
/* IEEE float */
proto_tree_add_text(adspec_tree, NullTVB, offset2,
(pntohs(&phdr->length)+1)<<2,
"%s - %lu (type %u, length %u)",
str,
pieee_to_long(&phdr->dataval),
phdr->id, pntohs(&phdr->length));
break;
default:
proto_tree_add_text(adspec_tree, NullTVB, offset2,
(pntohs(&phdr->length)+1)<<2,
"%s (type %u, length %u)",
str,
phdr->id, pntohs(&phdr->length));
}
} else {
proto_tree_add_text(adspec_tree, NullTVB, offset2,
(pntohs(&phdr->length)+1)<<2,
"Unknown (type %u, length %u)",
phdr->id, pntohs(&phdr->length));
}
offset2+=(pntohs(&phdr->length)+1)<<2;
i-=(pntohs(&phdr->length)+1)<<2;
mylen-=(pntohs(&phdr->length)+1)<<2;
}
}
break;
}
case RSVP_CLASS_INTEGRITY :
rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_integrity);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d",
obj_length);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1,
"Class number: %u - %s",
obj->class, object_type);
goto default_class;
case RSVP_CLASS_POLICY :
rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_policy);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d",
obj_length);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1,
"Class number: %u - %s",
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, NullTVB, offset, 2, "Length: %d",
obj_length);
proto_tree_add_text(rsvp_object_tree, NullTVB, 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, NullTVB, offset+3, 1,
"C-type: 1");
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2,
"L3PID: 0x%04x", l3pid);
break;
}
default: {
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: Unknown (%d)",
obj->type);
i = obj_length - sizeof(rsvp_object);
proto_tree_add_text(rsvp_object_tree, NullTVB, 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, NullTVB, offset, 2, "Length: %d",
obj_length);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1,
"Class number: %d - %s",
obj->class, object_type);
switch(obj->type) {
case 1: {
proto_tree_add_text(rsvp_object_tree, NullTVB, 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, NullTVB, 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, NullTVB, offset+3, 1,
"C-type: Unknown (%d)",
obj->type);
i = obj_length - sizeof(rsvp_object);
proto_tree_add_text(rsvp_object_tree, NullTVB, 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, NullTVB, offset, 2, "Length: %d",
obj_length);
proto_tree_add_text(rsvp_object_tree, NullTVB, 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, NullTVB, offset+3, 1,
"C-type: 7 - IPv4 LSP");
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1,
"Setup priority: %d", s_attr->setup_prio);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+1, 1,
"Hold priority: %d", s_attr->hold_prio);
ti2 = proto_tree_add_text(rsvp_object_tree, NullTVB, 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, NullTVB, 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, NullTVB, 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, NullTVB, 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, NullTVB, offset2+3, 1,
"Name length: %d", s_attr->name_len);
memset(s_name, 0, 64);
strncpy(s_name, &pd[offset2+4], 60);
if (s_attr->name_len>60) sprintf(&(s_name[60]), "...");
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+4, s_attr->name_len,
"Name: %s", s_name);
break;
}
default: {
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1,
"C-type: Unknown (%d)",
obj->type);
i = obj_length - sizeof(rsvp_object);
proto_tree_add_text(rsvp_object_tree, NullTVB, 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, NullTVB, offset, 2, "Length: %d",
obj_length);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1,
"Class number: %d - %s",
obj->class, object_type);
switch(obj->type) {
case 1: {
proto_tree_add_text(rsvp_object_tree, NullTVB, 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, NullTVB,
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, NullTVB, offset2+l, 1,
k ? "Loose Hop " : "Strict Hop");
proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1,
"Type: 1 (IPv4)");
proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+1, 1,
"Length: %d", pd[offset2+l+1]);
proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+2, 4,
"IPv4 hop: %s", ip_to_str(&pd[offset2+l+2]));
proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+6, 1,
"Prefix length: %d", pd[offset2+l+6]);
break;
case 2: /* IPv6 */
ti2 = proto_tree_add_text(rsvp_object_tree, NullTVB,
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, NullTVB, offset2+l, 1,
k ? "Loose Hop " : "Strict Hop");
proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1,
"Type: 2 (IPv6)");
proto_tree_add_text(rsvp_ero_subtree, NullTVB, 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, NullTVB, offset2+l+2, 16,
"IPv6 hop: %s", ip6_to_str(ip6a));
proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+18, 1,
"Prefix length: %d", pd[offset2+l+6]);
break;
case 32: /* AS */
k = pntohs(pd+offset2+l+2);
ti2 = proto_tree_add_text(rsvp_object_tree, NullTVB,
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, NullTVB, offset2+l, 1,
k ? "Loose Hop " : "Strict Hop");
proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1,
"Type: 32 (Autonomous System Number)");
proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+1, 1,
"Length: %d", pd[offset2+l+1]);
proto_tree_add_text(rsvp_ero_subtree, NullTVB, 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, NullTVB,
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, NullTVB, offset2+l, 1,
k ? "Loose Hop " : "Strict Hop");
proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1,
"Type: 64 (MPLS LSP Path Termination)");
proto_tree_add_text(rsvp_ero_subtree, NullTVB, 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, NullTVB,
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, NullTVB, offset2+l, 1,
k ? "Loose Hop " : "Strict Hop");
proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1,
"Type: %d (Unknown)", j);
proto_tree_add_text(rsvp_ero_subtree, NullTVB, 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, NullTVB, offset+3, 1,
"C-type: Unknown (%d)",
obj->type);
i = obj_length - sizeof(rsvp_object);
proto_tree_add_text(rsvp_object_tree, NullTVB, 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, NullTVB, offset, 2, "Length: %d",
obj_length);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1,
"Class number: %d - %s",
obj->class, object_type);
switch(obj->type) {
case 1: {
proto_tree_add_text(rsvp_object_tree, NullTVB, 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, NullTVB,
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, NullTVB, offset2+l, 1,
"Type: 1 (IPv4)");
proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+1, 1,
"Length: %d", pd[offset2+l+1]);
proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+2, 4,
"IPv4 hop: %s", ip_to_str(&pd[offset2+l+2]));
proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+6, 1,
"Prefix length: %d", pd[offset2+l+6]);
break;
case 2: /* IPv6 */
ti2 = proto_tree_add_text(rsvp_object_tree, NullTVB,
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, NullTVB, offset2+l, 1,
"Type: 2 (IPv6)");
proto_tree_add_text(rsvp_ero_subtree, NullTVB, 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, NullTVB, offset2+l+2, 16,
"IPv6 hop: %s", ip6_to_str(ip6a));
proto_tree_add_text(rsvp_ero_subtree, NullTVB, 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, NullTVB,
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, NullTVB, offset2+l, 1,
k ? "Loose Hop " : "Strict Hop");
proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1,
"Type: %d (Unknown)", j);
proto_tree_add_text(rsvp_ero_subtree, NullTVB, 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, NullTVB, offset+3, 1,
"C-type: Unknown (%d)",
obj->type);
i = obj_length - sizeof(rsvp_object);
proto_tree_add_text(rsvp_object_tree, NullTVB, 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, NullTVB, offset, 2, "Length: %d",
obj_length);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1,
"Class number: %u - %s",
obj->class, object_type);
default_class:
i = obj_length - sizeof(rsvp_object);
proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
"Data (%d bytes)", i);
break;
case RSVP_CLASS_NULL :
break;
}
offset += obj_length;
len += obj_length;
}
}
}
void
proto_register_rsvp(void)
{
static gint *ett[] = {
&ett_rsvp,
&ett_rsvp_hdr,
&ett_rsvp_session,
&ett_rsvp_hop,
&ett_rsvp_time_values,
&ett_rsvp_error,
&ett_rsvp_scope,
&ett_rsvp_style,
&ett_rsvp_confirm,
&ett_rsvp_sender_template,
&ett_rsvp_filter_spec,
&ett_rsvp_sender_tspec,
&ett_rsvp_flowspec,
&ett_rsvp_adspec,
&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,
};
proto_rsvp = proto_register_protocol("Resource ReserVation Protocol (RSVP)",
"RSVP", "rsvp");
proto_register_field_array(proto_rsvp, rsvpf_info, array_length(rsvpf_info));
proto_register_subtree_array(ett, array_length(ett));
}
void
proto_reg_handoff_rsvp(void)
{
old_dissector_add("ip.proto", IP_PROTO_RSVP, dissect_rsvp,
proto_rsvp);
}