Ethereal-dev: [ethereal-dev] Ethereal module for RSVP protocol

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Ashok Narayanan <ashokn@xxxxxxxxx>
Date: Fri, 11 Jun 1999 00:18:26 -0400 (EDT)
Hi, folks.

I've written an Ethereal disassembly module for the RSVP Resource
Reservation Protocol. The module supports all objects defined in
RFC2205 (IPv4 and IPv6 types), and also supports Integrated Services
objects from RFC2210. I've tested this on Linux and Solaris.

Attached are the following files

rsvp.diff - A unified diff from ethereal CVS as of 6/11/99,
12:00am. Made from within the ethereal directory.
packet-rsvp.c, packet-rsvp.h - RSVP message processing files
eth0.cap, eth1.cap - Two simple tcpdump-style captures of RSVP
messages 

Anything else I need to do to submit?

Thanks
-Ashok


-- 
--- Ashok Narayanan ----------------------------------------
IOS Network Protocols, Cisco Systems
250 Apollo Drive, Chelmsford, MA 01824
Ph: 978-244-8387


Index: Makefile.am
===================================================================
RCS file: /cvsroot/ethereal/Makefile.am,v
retrieving revision 1.30
diff -u -r1.30 Makefile.am
--- Makefile.am	1999/05/19 23:16:41	1.30
+++ Makefile.am	1999/06/11 04:00:01
@@ -62,6 +62,8 @@
 	packet-raw.c   \
 	packet-rip.c   \
 	packet-rip.h   \
+	packet-rsvp.c   \
+	packet-rsvp.h   \
 	packet-smb.c   \
 	packet-tcp.c   \
 	packet-telnet.c \
Index: Makefile.in
===================================================================
RCS file: /cvsroot/ethereal/Makefile.in,v
retrieving revision 1.36
diff -u -r1.36 Makefile.in
--- Makefile.in	1999/05/19 23:16:41	1.36
+++ Makefile.in	1999/06/11 04:00:02
@@ -80,7 +80,7 @@
 
 sysconf_DATA = manuf
 
-ethereal_SOURCES =  	alignment.h    	capture.c      	capture.h      	column.c       	column.h       	config.h       	ethereal.c     	ethereal.h     	ethertype.c    	etypes.h       	file.c         	file.h         	filter.c       	filter.h       	follow.c       	follow.h       	gtkpacket.c    	gtkpacket.h    	menu.c         	menu.h         	packet-aarp.c  	packet-arp.c   	packet-atalk.c 	packet-bootp.c 	packet-cdp.c   	packet-data.c  	packet-dns.c   	packet-dns.h   	packet-eth.c   	packet-fddi.c  	packet-ftp.c   	packet-giop.c  	packet-http.c  	packet-icmpv6.c 	packet-ip.c    	packet-ip.h    	packet-ipsec.c 	packet-ipv6.c  	packet-ipv6.h  	packet-ipx.c   	packet-ipx.h   	packet-llc.c   	packet-lpd.c   	packet-nbipx.c 	packet-nbns.c  	packet-ncp.c   	packet-ncp.h   	packet-nntp.c  	packet-null.c  	packet-osi.c   	packet-ospf.c  	packet-ospf.h  	packet-pop.c   	packet-ppp.c   	packet-raw.c   	packet-rip.c   	packet-rip.h   	packet-smb.c   	packet-tcp.c   	packet-telnet.c 	packet-tftp.c  	packet-tr.c    	packet-trmac.c 	packet-udp.c   	packet-vines.c 	packet-vines.h 	packet.c       	packet.h       	prefs.c        	prefs.h        	print.c        	print.h        	ps.c           	ps.h           	resolv.c       	resolv.h       	smb.h          	util.c         	util.h
+ethereal_SOURCES =  	alignment.h    	capture.c      	capture.h      	column.c       	column.h       	config.h       	ethereal.c     	ethereal.h     	ethertype.c    	etypes.h       	file.c         	file.h         	filter.c       	filter.h       	follow.c       	follow.h       	gtkpacket.c    	gtkpacket.h    	menu.c         	menu.h         	packet-aarp.c  	packet-arp.c   	packet-atalk.c 	packet-bootp.c 	packet-cdp.c   	packet-data.c  	packet-dns.c   	packet-dns.h   	packet-eth.c   	packet-fddi.c  	packet-ftp.c   	packet-giop.c  	packet-http.c  	packet-icmpv6.c 	packet-ip.c    	packet-ip.h    	packet-ipsec.c 	packet-ipv6.c  	packet-ipv6.h  	packet-ipx.c   	packet-ipx.h   	packet-llc.c   	packet-lpd.c   	packet-nbipx.c 	packet-nbns.c  	packet-ncp.c   	packet-ncp.h   	packet-nntp.c  	packet-null.c  	packet-osi.c   	packet-ospf.c  	packet-ospf.h  	packet-pop.c   	packet-ppp.c   	packet-raw.c   	packet-rip.c   	packet-rip.h   	packet-rsvp.c   	packet-rsvp.h   	packet-smb.c   	packet-tcp.c   	packet-telnet.c 	packet-tftp.c  	packet-tr.c    	packet-trmac.c 	packet-udp.c   	packet-vines.c 	packet-vines.h 	packet.c       	packet.h       	prefs.c        	prefs.h        	print.c        	print.h        	ps.c           	ps.h           	resolv.c       	resolv.h       	smb.h          	util.c         	util.h
 
 
 EXTRA_ethereal_SOURCES =  	packet-snmp.c		snprintf.c		snprintf.h		snprintf-imp.h
@@ -114,9 +114,10 @@
 packet-icmpv6.o packet-ip.o packet-ipsec.o packet-ipv6.o packet-ipx.o \
 packet-llc.o packet-lpd.o packet-nbipx.o packet-nbns.o packet-ncp.o \
 packet-nntp.o packet-null.o packet-osi.o packet-ospf.o packet-pop.o \
-packet-ppp.o packet-raw.o packet-rip.o packet-smb.o packet-tcp.o \
-packet-telnet.o packet-tftp.o packet-tr.o packet-trmac.o packet-udp.o \
-packet-vines.o packet.o prefs.o print.o ps.o resolv.o util.o
+packet-ppp.o packet-raw.o packet-rip.o packet-rsvp.o packet-smb.o \
+packet-tcp.o packet-telnet.o packet-tftp.o packet-tr.o packet-trmac.o \
+packet-udp.o packet-vines.o packet.o prefs.o print.o ps.o resolv.o \
+util.o
 ethereal_LDFLAGS = 
 CFLAGS = @CFLAGS@
 COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -150,11 +151,11 @@
 .deps/packet-nbns.P .deps/packet-ncp.P .deps/packet-nntp.P \
 .deps/packet-null.P .deps/packet-osi.P .deps/packet-ospf.P \
 .deps/packet-pop.P .deps/packet-ppp.P .deps/packet-raw.P \
-.deps/packet-rip.P .deps/packet-smb.P .deps/packet-snmp.P \
-.deps/packet-tcp.P .deps/packet-telnet.P .deps/packet-tftp.P \
-.deps/packet-tr.P .deps/packet-trmac.P .deps/packet-udp.P \
-.deps/packet-vines.P .deps/packet.P .deps/prefs.P .deps/print.P \
-.deps/ps.P .deps/resolv.P .deps/snprintf.P .deps/util.P
+.deps/packet-rip.P .deps/packet-rsvp.P .deps/packet-smb.P \
+.deps/packet-snmp.P .deps/packet-tcp.P .deps/packet-telnet.P \
+.deps/packet-tftp.P .deps/packet-tr.P .deps/packet-trmac.P \
+.deps/packet-udp.P .deps/packet-vines.P .deps/packet.P .deps/prefs.P \
+.deps/print.P .deps/ps.P .deps/resolv.P .deps/snprintf.P .deps/util.P
 SOURCES = $(ethereal_SOURCES) $(EXTRA_ethereal_SOURCES)
 OBJECTS = $(ethereal_OBJECTS)
 
Index: packet-ip.c
===================================================================
RCS file: /cvsroot/ethereal/packet-ip.c,v
retrieving revision 1.23
diff -u -r1.23 packet-ip.c
--- packet-ip.c	1999/05/20 02:41:22	1.23
+++ packet-ip.c	1999/06/11 04:00:03
@@ -736,6 +736,9 @@
     case IP_PROTO_OSPF:
       dissect_ospf(pd, offset, fd, tree);
      break;
+    case IP_PROTO_RSVP:
+      dissect_rsvp(pd, offset, fd, tree);
+     break;
     case IP_PROTO_AH:
       advance = dissect_ah(pd, offset, fd, tree);
       nxt = pd[offset];
Index: packet-ip.h
===================================================================
RCS file: /cvsroot/ethereal/packet-ip.h,v
retrieving revision 1.2
diff -u -r1.2 packet-ip.h
--- packet-ip.h	1999/03/28 18:31:59	1.2
+++ packet-ip.h	1999/06/11 04:00:03
@@ -49,6 +49,7 @@
 #define IP_PROTO_IPV6		41		/* IP6 header */
 #define IP_PROTO_ROUTING	43		/* IP6 routing header */
 #define IP_PROTO_FRAGMENT	44		/* IP6 fragmentation header */
+#define IP_PROTO_RSVP           46              /* Resource ReSerVation protocol */
 #define IP_PROTO_ESP		50		/* ESP */
 #define IP_PROTO_AH		51		/* AH */
 #define IP_PROTO_ICMPV6		58		/* ICMP6 */
Index: packet.h
===================================================================
RCS file: /cvsroot/ethereal/packet.h,v
retrieving revision 1.56
diff -u -r1.56 packet.h
--- packet.h	1999/05/13 16:42:43	1.56
+++ packet.h	1999/06/11 04:00:03
@@ -236,6 +236,27 @@
 	ETT_SMB_CAPS,
 	ETT_SMB_RAWMODE,
 	ETT_SMB_AFLAGS,
+	ETT_RSVP,
+	ETT_RSVP_UNKNOWN_CLASS,	
+	ETT_RSVP_HDR,
+	ETT_RSVP_SESSION,
+	ETT_RSVP_SGROUP,
+	ETT_RSVP_HOP,
+	ETT_RSVP_INTEGRITY,
+	ETT_RSVP_TIME_VALUES,
+	ETT_RSVP_ERROR,
+	ETT_RSVP_SCOPE,
+	ETT_RSVP_STYLE,
+	ETT_RSVP_FLOWSPEC,
+	ETT_RSVP_FILTER_SPEC,
+	ETT_RSVP_SENDER_TEMPLATE,
+	ETT_RSVP_SENDER_TSPEC,
+	ETT_RSVP_ADSPEC,
+	ETT_RSVP_POLICY,
+	ETT_RSVP_CONFIRM,
+	ETT_RSVP_ADSPEC_SUBTREE1,
+	ETT_RSVP_ADSPEC_SUBTREE2,
+	ETT_RSVP_ADSPEC_SUBTREE3,
 	NUM_TREE_TYPES	/* last item number plus one */
 };
 
@@ -375,6 +396,7 @@
 void dissect_ospf(const u_char *, int, frame_data *, proto_tree *);
 void dissect_ospf_hello(const u_char *, int, frame_data *, proto_tree *);
 void dissect_rip(const u_char *, int, frame_data *, proto_tree *);
+void dissect_rsvp(const u_char *, int, frame_data *, proto_tree *);
 void dissect_snmp(const u_char *, int, frame_data *, proto_tree *);
 void dissect_tcp(const u_char *, int, frame_data *, proto_tree *);
 void dissect_tftp(const u_char *, int, frame_data *, proto_tree *);
/**********************************************************************
 *
 * packet-rsvp.h
 *
 * (C) Ashok Narayanan <ashokn@xxxxxxxxx>
 *
 * $Id:$
 *
 * For license details, see the COPYING file with this distribution
 *
 **********************************************************************/

#ifndef PACKET_RSVP_H
#define PACKET_RSVP_H

/*
 * 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"}
};

/* 
 * 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
};

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 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"}
};

/*
 * 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" }
};

/*
 * Defines a desired QoS, in a RESV message.
 */
enum    qos_service_type {
    QOS_CONTROLLED_LOAD=    5,		/* Controlled Load Service */
    QOS_GUARANTEED =        2,		/* Guaranteed service */
    QOS_DEFAULT		 =  1,		/* Default general parameters */
    QOS_TSPEC =             0,		/* Traffic specification */
    QOS_UNSPECIFIED =	    -1		/* unspecified */
    };

static value_string qos_vals[] = {
    { QOS_CONTROLLED_LOAD, "Controlled-load QoS" },
    { QOS_GUARANTEED, "Guaranteed rate QoS" },
    { QOS_DEFAULT, "Default general parameters" },
    { QOS_UNSPECIFIED, "Unspecified QoS" },
    { QOS_TSPEC, "Traffic specification" },
};

static value_string svc_vals[] = {
    { 127, "Token bucket TSpec" },
    { 130, "Guaranteed-rate RSpec" }
};

enum rsvp_spec_types { INTSRV = 2 };

enum intsrv_services {
	INTSRV_GENERAL = 1,
	INTSRV_GTD = 2,
	INTSRV_CLOAD = 5
};

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_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 */
};

/*------------------------------*
 * Object definitions
 *------------------------------*/

/*
 * Base RSVP object
 */
typedef struct {
    unsigned short length;
    unsigned char class;	
    unsigned char type;
    unsigned char data[0];
} rsvp_object;

/*
 * RSVP message header
 */

typedef struct {
    unsigned char    ver_flags;			/* RSVP Version & flags */
    unsigned char    message_type;		/* type of message */
    unsigned short   cksum;			/* IP Checksum */
    unsigned char    sending_ttl;		/* ttl of message */
    unsigned char    reserved_byte;		/* reserved */
    unsigned short   rsvp_length;		/* length of RSVP data */
    rsvp_object rsvp_first_object[0];
} rsvp_header;

/*
 * NULL object 
*/
typedef struct {
    rsvp_object base;
} rsvp_null;

/*
 * SESSION object
 */
typedef struct {
    rsvp_object base;
    unsigned long destination;
    unsigned char protocol;
    unsigned char flags;
    unsigned short port;
} rsvp_session_ipv4;

typedef struct {
    rsvp_object base;
    struct e_in6_addr destination;
    unsigned char protocol;
    unsigned char flags;
    unsigned short port;
} rsvp_session_ipv6;

/*
 * HOP object
 * Can be a PHOP or a NHOP
 */
typedef struct {
    rsvp_object base;
    unsigned long neighbor;
    unsigned long lif_handle;
} rsvp_hop_ipv4;

typedef struct {
    rsvp_object base;
    struct e_in6_addr neighbor;
    unsigned long lif_handle;
} rsvp_hop_ipv6;

/*
 * TIME_VALUES object
 */
typedef struct {
    rsvp_object base;
    long refresh_ms;
} rsvp_time_values;

/*
 * ERROR object
 */
typedef struct {
    rsvp_object base;
    unsigned long error_node;
    unsigned char flags;
    unsigned char error_code;
    unsigned short error_value;
} rsvp_error_ipv4;

typedef struct {
    rsvp_object base;
    struct e_in6_addr error_node;
    unsigned char flags;
    unsigned char error_code;
    unsigned short error_value;
} rsvp_error_ipv6;

/*
 * CONFIRM object
 */
typedef struct {
    rsvp_object base;
    unsigned long receiver;
} rsvp_confirm_ipv4;

typedef struct {
    rsvp_object base;
    struct e_in6_addr receiver;
} rsvp_confirm_ipv6;

/*
 * SCOPE object
 */
typedef struct {
    rsvp_object base;
    unsigned long source[0];
} rsvp_scope;

/*
 * STYLE object
 */
typedef struct {
    rsvp_object base;
    unsigned long 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;
    unsigned long source;			/* source sending data */
    unsigned short unused;
    unsigned short 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;
    unsigned long source;			/* source sending data */
    unsigned short __reserved;
    unsigned short source_port;		/* port number */
} rsvp_template_ipv4;

typedef struct {
    rsvp_object base;
    struct e_in6_addr source;			/* source sending data */
    unsigned short __reserved;
    unsigned short source_port;		/* port number */
} rsvp_template_ipv6;

/*
 * Subobjects for Integrated Services
 */

typedef struct {
    rsvp_object base;
    unsigned char	version;	
    unsigned char 	__reserved_;
    unsigned short	length_in_words;
					
    unsigned char	service_header;
    unsigned char	_reserved;
    unsigned short	service_length;	
    unsigned char	param_id;
    unsigned char	flags_tspec;
    unsigned short	parameter_length;

    unsigned long	rate;
    unsigned long	depth;
    unsigned long	peak;
    unsigned long	min_unit;
    unsigned long	max_unit;
} IS_tspec; /* RFC2210 */

typedef struct {
    rsvp_object base;
    unsigned char	version;	
    unsigned char 	__reserved_;
    unsigned short	length_in_words;
					
    unsigned char	service_header;
    unsigned char	_reserved;
    unsigned short	service_length;	
    unsigned char	param_id;
    unsigned char	flags_tspec;
    unsigned short	parameter_length;

    unsigned long	rate;
    unsigned long	depth;
    unsigned long	peak;
    unsigned long	min_unit;
    unsigned long	max_unit;

    unsigned char	param_id_rspec;
    unsigned char	flags_rspec;
    unsigned short	param2_length;
    unsigned long	requested_rate;
    unsigned long	slack;
} IS_flowspec; /* RFC 2210 */

/*
 * ADSPEC objects */

typedef struct {
    unsigned char service_num;
    unsigned char break_bit;
    unsigned short length;
} service_hdr;

static value_string adspec_services[] = { 
    {1, "Default General Parameters"},
    {2, "Guaranteed"},
    {5, "Controlled Load"},
};

typedef struct {
    unsigned char id;
    unsigned char flags;
    unsigned short length;
    unsigned long 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"},
};



#endif
/* packet-rsvp.c
 * Routines for RSVP packet disassembly
 *
 * (c) Copyright Ashok Narayanan <ashokn@xxxxxxxxx>
 *
 * $Id:$
 *
 * Ethereal - Network traffic analyzer
 * By Gerald Combs <gerald@xxxxxxxx>
 * 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
 */

 
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <stdio.h>
#include <unistd.h>
#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

#ifdef NEED_SNPRINTF_H
# ifdef HAVE_STDARG_H
#  include <stdarg.h>
# else
#  include <varargs.h>
# endif
# include "snprintf.h"
#endif

#include <glib.h>
#include "packet.h"
#include "packet-ipv6.h"
#include "packet-rsvp.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 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_header_tree;
    proto_tree *rsvp_object_tree;
    char *packet_type, *object_type;
    rsvp_header *hdr;
    rsvp_object *obj;
    int i, len, mylen;
    int msg_length;
    int obj_length;
    int offset2;

    hdr = (rsvp_header *)&pd[offset];
    packet_type = match_strval(hdr->message_type, message_type_vals);
    if (check_col(fd, COL_PROTOCOL))
        col_add_str(fd, COL_PROTOCOL, "RSVP");
    if (check_col(fd, COL_INFO)) {
        if (packet_type != NULL)
            col_add_str(fd, COL_INFO, packet_type); 
        else
            col_add_fstr(fd, COL_INFO, "Unknown (%d)", hdr->message_type); 
    }

    if (tree) {
	msg_length = pntohs(pd+offset+6);
	ti = proto_tree_add_item(tree, offset, msg_length, 
			      "Resource ReserVation Protocol (RSVP)"); 
	rsvp_tree = proto_tree_new(); 
	proto_item_add_subtree(ti, rsvp_tree, ETT_RSVP);

	ti = proto_tree_add_item(rsvp_tree, offset, 
			      sizeof(rsvp_header), "RSVP Header"); 
	rsvp_header_tree = proto_tree_new();
	proto_item_add_subtree(ti, rsvp_header_tree, ETT_RSVP_HDR);

        proto_tree_add_item(rsvp_header_tree, offset, 1, "RSVP Version: %d", 
			 (hdr->ver_flags & 0xf0)>>4);  
	proto_tree_add_item(rsvp_header_tree, offset, 1, "Flags: %02X",
			 hdr->ver_flags & 0xf);  
	proto_tree_add_item(rsvp_header_tree, offset+1, 1, "Message Type: %d - %s",
			 hdr->message_type, 
			 packet_type?packet_type:"Unknown");
	proto_tree_add_item(rsvp_header_tree, offset + 2 , 2, "Message Checksum");
	proto_tree_add_item(rsvp_header_tree, offset + 4 , 1, "Sending TTL: %d",
			 hdr->sending_ttl);
	proto_tree_add_item(rsvp_header_tree, 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 (offset + obj_length > fd->cap_len) {
		proto_tree_add_item(rsvp_tree, 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_item(rsvp_tree, offset, 
				  obj_length, 
				  "%s (%d)", object_type, obj->class);
	    rsvp_object_tree = proto_tree_new();

	    offset2 = offset + sizeof(rsvp_object);

	    switch(obj->class) {

	    case RSVP_CLASS_SESSION : 		
		proto_item_add_subtree(ti, rsvp_object_tree, ETT_RSVP_SESSION);
		proto_tree_add_item(rsvp_object_tree, offset, 2, "Length: %d", 
				    obj_length);
		proto_tree_add_item(rsvp_object_tree, offset+2, 1, 
				    "Class number: %d - %s", 
				    obj->class, object_type);
		switch(obj->type) {
		case 1: {
		    rsvp_session_ipv4 *sess = (rsvp_session_ipv4 *)obj;
		    proto_tree_add_item(rsvp_object_tree, offset+3, 1, 
					"C-type: 1 - IPv4");
		    proto_tree_add_item(rsvp_object_tree, offset2, 4, 
					"Destination address: %s", 
					ip_to_str((guint8 *) &(sess->destination)));
		    proto_tree_add_item(rsvp_object_tree, offset2+4, 1,
					"Protocol: %d", sess->protocol);
		    proto_tree_add_item(rsvp_object_tree, offset2+5, 1,
					"Flags: %d", sess->flags);
		    proto_tree_add_item(rsvp_object_tree, offset2+6, 2,
					"Destination port: %d", 
					pntohs(pd+offset2+6));
		    break;
		}

		case 2: {
		    rsvp_session_ipv6 *sess = (rsvp_session_ipv6 *)obj;
		    proto_tree_add_item(rsvp_object_tree, offset+3, 1, 
					"C-type: 2 - IPv6");
		    proto_tree_add_item(rsvp_object_tree, offset2, 4, 
					"Destination address: %s", 
					ip6_to_str(&(sess->destination)));
		    proto_tree_add_item(rsvp_object_tree, offset2+16, 1,
					"Protocol: %d", sess->protocol);
		    proto_tree_add_item(rsvp_object_tree, offset2+17, 1,
					"Flags: %d", sess->flags);
		    proto_tree_add_item(rsvp_object_tree, offset2+18, 2,
					"Destination port: %d", 
					pntohs(pd+offset2+18));
		    break;
		}
		
		default: {
		    proto_tree_add_item(rsvp_object_tree, offset+3, 1, 
					"C-type: Unknown (%d)",
					obj->type);
		    i = obj_length - sizeof(rsvp_object);
		    proto_tree_add_item(rsvp_object_tree, offset2, i,
					"Data (%d bytes)", i);
		}
		}
		break;
		
	    case RSVP_CLASS_HOP :		
		proto_item_add_subtree(ti, rsvp_object_tree, ETT_RSVP_HOP);
		proto_tree_add_item(rsvp_object_tree, offset, 2, "Length: %d", 
				    obj_length);
		proto_tree_add_item(rsvp_object_tree, offset+2, 1, 
				    "Class number: %d - %s", 
				    obj->class, object_type);
		switch(obj->type) {
		case 1: {
		    rsvp_hop_ipv4 *hop = (rsvp_hop_ipv4 *)obj;
		    proto_tree_add_item(rsvp_object_tree, offset+3, 1, 
					"C-type: 1 - IPv4");
		    proto_tree_add_item(rsvp_object_tree, offset2, 4, 
					"Neighbor address: %s", 
					ip_to_str((guint8 *) &(hop->neighbor)));
		    proto_tree_add_item(rsvp_object_tree, offset2+4, 4,
					"Logical interface: %0x", 
					pntohl(pd+offset2+4));
		    break;
		}

		case 2: {
		    rsvp_hop_ipv6 *hop = (rsvp_hop_ipv6 *)obj;
		    proto_tree_add_item(rsvp_object_tree, offset+3, 1, 
					"C-type: 2 - IPv6");
		    proto_tree_add_item(rsvp_object_tree, offset2, 4, 
					"Neighbor address: %s", 
					ip6_to_str(&(hop->neighbor)));
		    proto_tree_add_item(rsvp_object_tree, offset2+16, 4,
					"Logical interface: %0x", 
					pntohl(pd+offset2+16));
		    break;
		}
		
		default: {
		    proto_tree_add_item(rsvp_object_tree, offset+3, 1, 
					"C-type: Unknown (%d)",
					obj->type);
		    i = obj_length - sizeof(rsvp_object);
		    proto_tree_add_item(rsvp_object_tree, offset2, i,
					"Data (%d bytes)", i);
		}
		}
		break;
		
	    case RSVP_CLASS_TIME_VALUES : 
		proto_item_add_subtree(ti, rsvp_object_tree, ETT_RSVP_TIME_VALUES);
		proto_tree_add_item(rsvp_object_tree, offset, 2, "Length: %d", 
				    obj_length);
		proto_tree_add_item(rsvp_object_tree, offset+2, 1, 
				    "Class number: %d - %s", 
				    obj->class, object_type);
		switch(obj->type) {
		case 1: {
		    proto_tree_add_item(rsvp_object_tree, offset+3, 1, 
					"C-type: 1");
		    proto_tree_add_item(rsvp_object_tree, offset2, 4, 
					"Refresh interval: %u ms (%u seconds)",
					pntohl(pd+offset2),
					pntohl(pd+offset2)/1000);
		    break;
		}

		default: {
		    proto_tree_add_item(rsvp_object_tree, offset+3, 1, 
					"C-type: Unknown (%d)",
					obj->type);
		    i = obj_length - sizeof(rsvp_object);
		    proto_tree_add_item(rsvp_object_tree, offset2, i,
					"Data (%d bytes)", i);
		    break;
		}
		}
		break;

	    case RSVP_CLASS_ERROR :
		proto_item_add_subtree(ti, rsvp_object_tree, ETT_RSVP_ERROR);
		proto_tree_add_item(rsvp_object_tree, offset, 2, "Length: %d", 
				    obj_length);
		proto_tree_add_item(rsvp_object_tree, offset+2, 1, 
				    "Class number: %d - %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_item(rsvp_object_tree, offset+3, 1, 
					"C-type: 1 - IPv4");
		    proto_tree_add_item(rsvp_object_tree, offset2, 4, 
					"Error node: %s",
					ip_to_str((guint8 *) &(err->error_node)));
		    proto_tree_add_item(rsvp_object_tree, offset2+4, 1,
					"Flags: %02x", err->flags);
		    proto_tree_add_item(rsvp_object_tree, offset2+5, 1,
					"Error code: %d - %s", err->error_code,
					err_str);
		    proto_tree_add_item(rsvp_object_tree, offset2+6, 2,
					"Error value: %d", 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_item(rsvp_object_tree, offset+3, 1, 
					"C-type: 2 - IPv6");
		    proto_tree_add_item(rsvp_object_tree, offset2, 4, 
					"Error node: %s",
					ip6_to_str(&(err->error_node)));
		    proto_tree_add_item(rsvp_object_tree, offset2+16, 1,
					"Flags: %02x", err->flags);
		    proto_tree_add_item(rsvp_object_tree, offset2+17, 1,
					"Error code: %d - %s", err->error_code,
					err_str);
		    proto_tree_add_item(rsvp_object_tree, offset2+18, 2,
					"Error value: %d", pntohs(pd+offset2+18));
		    
		    break;
		}
		
		default: {
		    proto_tree_add_item(rsvp_object_tree, offset+3, 1, 
					"C-type: Unknown (%d)",
					obj->type);
		    i = obj_length - sizeof(rsvp_object);
		    proto_tree_add_item(rsvp_object_tree, offset2, i,
					"Data (%d bytes)", i);
		}
		}
		break;
		

	    case RSVP_CLASS_SCOPE : 
		mylen = obj_length;
		proto_item_add_subtree(ti, rsvp_object_tree, ETT_RSVP_SCOPE);
		proto_tree_add_item(rsvp_object_tree, offset, 2, "Length: %d", 
				    obj_length);
		proto_tree_add_item(rsvp_object_tree, offset+2, 1, 
				    "Class number: %d - %s", 
				    obj->class, object_type);
		switch(obj->type) {
		case 1: {
		    unsigned long ip;
		    proto_tree_add_item(rsvp_object_tree, offset+3, 1, 
					"C-type: 1 - IPv4");
		    while (mylen > sizeof(rsvp_object)) {
			ip = pntohl(pd+offset2);
			proto_tree_add_item(rsvp_object_tree, offset2, 4, 
					    "IPv4 Address: %s",
					    ip_to_str((guint8 *) &ip));
			offset2 += 4;
			mylen -= 4;
		    }
		    break;
		}

		case 2: {
		    struct e_in6_addr *ip;
		    proto_tree_add_item(rsvp_object_tree, offset+3, 1, 
					"C-type: 2 - IPv6");
		    while (mylen>sizeof(rsvp_object)) {
			ip = (struct e_in6_addr *)pd+offset2;
			proto_tree_add_item(rsvp_object_tree, offset2, 16, 
					    "IPv6 Address: %s",
					    ip6_to_str(ip));
			offset2 += 16;
			mylen -= 16;
		    }
		    break;
		}
		
		default: {
		    proto_tree_add_item(rsvp_object_tree, offset+3, 1, 
					"C-type: Unknown (%d)",
					obj->type);
		    i = obj_length - sizeof(rsvp_object);
		    proto_tree_add_item(rsvp_object_tree, offset2, i,
					"Data (%d bytes)", i);
		}
		}
		break;
		
	    case RSVP_CLASS_STYLE : 
		proto_item_add_subtree(ti, rsvp_object_tree, ETT_RSVP_STYLE);
		proto_tree_add_item(rsvp_object_tree, offset, 2, "Length: %d", 
				    obj_length);
		proto_tree_add_item(rsvp_object_tree, offset+2, 1, 
				    "Class number: %d - %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_item(rsvp_object_tree, offset+3, 1, 
					"C-type: 1");
		    proto_tree_add_item(rsvp_object_tree, offset2+5, 1,
					"Style: %ld - %s", ip, style_str);
		    break;
		}

		default: {
		    proto_tree_add_item(rsvp_object_tree, offset+3, 1, 
					"C-type: Unknown (%d)",
					obj->type);
		    i = obj_length - sizeof(rsvp_object);
		    proto_tree_add_item(rsvp_object_tree, offset2, i,
					"Data (%d bytes)", i);
		    break;
		}
		}
		break;
	    
	    case RSVP_CLASS_CONFIRM :		
		proto_item_add_subtree(ti, rsvp_object_tree, ETT_RSVP_CONFIRM);
		proto_tree_add_item(rsvp_object_tree, offset, 2, "Length: %d", 
				    obj_length);
		proto_tree_add_item(rsvp_object_tree, offset+2, 1, 
				    "Class number: %d - %s", 
				    obj->class, object_type);
		switch(obj->type) {
		case 1: {
		    rsvp_confirm_ipv4 *confirm = (rsvp_confirm_ipv4 *)obj;
		    proto_tree_add_item(rsvp_object_tree, offset+3, 1, 
					"C-type: 1 - IPv4");
		    proto_tree_add_item(rsvp_object_tree, 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_item(rsvp_object_tree, offset+3, 1, 
					"C-type: 2 - IPv6");
		    proto_tree_add_item(rsvp_object_tree, offset2, 16, 
					"Receiver address: %s", 
					ip6_to_str(&(confirm->receiver)));
		    break;
		}

		default: {
		    proto_tree_add_item(rsvp_object_tree, offset+3, 1, 
					"C-type: Unknown (%d)",
					obj->type);
		    i = obj_length - sizeof(rsvp_object);
		    proto_tree_add_item(rsvp_object_tree, offset2, i,
					"Data (%d bytes)", i);
		}
		}
		break;

	    case RSVP_CLASS_SENDER_TEMPLATE :
		proto_item_add_subtree(ti, rsvp_object_tree, ETT_RSVP_SENDER_TEMPLATE);
		proto_tree_add_item(rsvp_object_tree, offset, 2, "Length: %d", 
				    obj_length);
		proto_tree_add_item(rsvp_object_tree, offset+2, 1, 
				    "Class number: %d - %s", 
				    obj->class, object_type);
		goto common_template;
	    case RSVP_CLASS_FILTER_SPEC :
		proto_item_add_subtree(ti, rsvp_object_tree, ETT_RSVP_FILTER_SPEC);
		proto_tree_add_item(rsvp_object_tree, offset, 2, "Length: %d", 
				    obj_length);
		proto_tree_add_item(rsvp_object_tree, offset+2, 1, 
				    "Class number: %d - %s", 
				    obj->class, object_type);
	    common_template:
		switch(obj->type) {
		case 1: {
		    rsvp_template_ipv4 *tem = (rsvp_template_ipv4 *)obj;
		    proto_tree_add_item(rsvp_object_tree, offset+3, 1, 
					"C-type: 1 - IPv4");
		    proto_tree_add_item(rsvp_object_tree, offset2, 4, 
					"Source address: %s", 
					ip_to_str((guint8 *) &(tem->source)));
		    proto_tree_add_item(rsvp_object_tree, offset2+6, 2,
					"Source port: %d", pntohs(pd+offset2+6));
		    break;
		}

		case 2: {
		    rsvp_template_ipv6 *tem = (rsvp_template_ipv6 *)obj;
		    proto_tree_add_item(rsvp_object_tree, offset+3, 1, 
					"C-type: 2 - IPv6");
		    proto_tree_add_item(rsvp_object_tree, offset2, 16, 
					"Source address: %s", 
					ip6_to_str(&(tem->source)));
		    proto_tree_add_item(rsvp_object_tree, offset2+18, 2,
					"Source port: %d", pntohs(pd+offset2+18));
		    break;
		}
		
		default: {
		    proto_tree_add_item(rsvp_object_tree, offset+3, 1, 
					"C-type: Unknown (%d)",
					obj->type);
		    i = obj_length - sizeof(rsvp_object);
		    proto_tree_add_item(rsvp_object_tree, offset2, i,
					"Data (%d bytes)", i);
		}
		}
		break;

	    case RSVP_CLASS_SENDER_TSPEC : {
		IS_tspec *tspec = (IS_tspec *)obj;

		proto_item_add_subtree(ti, rsvp_object_tree, 
				       ETT_RSVP_SENDER_TSPEC);
		proto_tree_add_item(rsvp_object_tree, offset, 2, "Length: %d", 
				    obj_length);
		proto_tree_add_item(rsvp_object_tree, offset+2, 1, 
				    "Class number: %d - %s", 
				    obj->class, object_type);

		proto_tree_add_item(rsvp_object_tree, offset2, 1, 
				 "Message format version: %d", 
				 tspec->version>>4);
		proto_tree_add_item(rsvp_object_tree, offset2+2, 2, 
				 "Data length: %d words, not including header", 
				 pntohs(pd+offset2+2));
		proto_tree_add_item(rsvp_object_tree, offset2+4, 1, 
				 "Service header: %d - %s", 
				 tspec->service_header,
				 tspec->service_header==1 ? 
				 "Default/global information (INTSRV_GENERAL)" : 
				 "Unknown");
		proto_tree_add_item(rsvp_object_tree, offset2+6, 2, 
				 "Length of service %d data: %d words, " 
				 "not including header", 
				 tspec->service_header,
				 pntohs(pd+offset2+6)>>12);

		/* Token bucket TSPEC */
		proto_tree_add_item(rsvp_object_tree, offset2+8, 1, 
				    "Parameter ID: %d - %s", 
				    tspec->param_id,
				    tspec->param_id==127 ? "Token Bucket TSpec" :
				    "Unknown");
		proto_tree_add_item(rsvp_object_tree, offset2+9, 1, 
				    "Parameter %d flags: %d", 
				    tspec->param_id, tspec->flags_tspec);
		proto_tree_add_item(rsvp_object_tree, offset2+10, 2, 
				    "Length of parameter %d data: %d words, " 
				    "not including header",
				    tspec->param_id,
				    pntohs(pd+offset2+10));
		proto_tree_add_item(rsvp_object_tree, offset2+12, 4, 
				    "Token bucket rate: %ld", 
				    ieee_to_long(pd+offset2+12));
		proto_tree_add_item(rsvp_object_tree, offset2+16, 4, 
				    "Token bucket size: %ld", 
				    ieee_to_long(pd+offset2+16));
		proto_tree_add_item(rsvp_object_tree, offset2+20, 4, 
				    "Peak data rate: %ld", 
				    ieee_to_long(pd+offset2+20));
		proto_tree_add_item(rsvp_object_tree, offset2+24, 4, 
				    "Minimum policed unit: %d", 
				    pntohl(pd+offset2+24));
		proto_tree_add_item(rsvp_object_tree, offset2+28, 4, 
				    "Maximum policed unit: %d", 
				    pntohl(pd+offset2+28));
		    
		break;
	    }

	    case RSVP_CLASS_FLOWSPEC : {
		IS_flowspec *flowspec = (IS_flowspec *)obj;
		char *qos_str = match_strval(flowspec->service_header, qos_vals);
		char *is_param_str = match_strval(flowspec->param_id, svc_vals);

		proto_item_add_subtree(ti, rsvp_object_tree, 
				       ETT_RSVP_FLOWSPEC);
		proto_tree_add_item(rsvp_object_tree, offset, 2, "Length: %d", 
				    obj_length);
		proto_tree_add_item(rsvp_object_tree, offset+2, 1, 
				    "Class number: %d - %s", 
				    obj->class, object_type);
		if (!qos_str) qos_str = "Unknown";
		if (!is_param_str) is_param_str="Unknown";

		proto_tree_add_item(rsvp_object_tree, offset2, 1, 
				 "Message format version: %d", 
				 flowspec->version>>4);
		proto_tree_add_item(rsvp_object_tree, offset2+2, 2, 
				 "Data length: %d words, not including header", 
				 pntohs(pd+offset2+2));
		proto_tree_add_item(rsvp_object_tree, offset2+4, 1, 
				 "Service header: %d - %s", 
				 flowspec->service_header, qos_str);
		proto_tree_add_item(rsvp_object_tree, offset2+6, 2, 
				 "Length of service %d data: %d words, " 
				 "not including header", 
				 flowspec->service_header,
				 pntohs(pd+offset2+6)>>12);
		proto_tree_add_item(rsvp_object_tree, offset2+8, 1, 
				 "Parameter ID: %d - %s", 
				 flowspec->param_id, is_param_str);
		proto_tree_add_item(rsvp_object_tree, offset2+9, 1, 
				 "Parameter %d flags: %d", 
				 flowspec->param_id, flowspec->flags_tspec);
		proto_tree_add_item(rsvp_object_tree, offset2+10, 2, 
				 "Length of parameter %d data: %d words, " 
				 "not including header",
				 flowspec->param_id,
				 pntohs(pd+offset2+10));
		proto_tree_add_item(rsvp_object_tree, offset2+12, 4, 
				 "Token bucket rate: %ld", 
				 ieee_to_long(pd+offset2+12));
		proto_tree_add_item(rsvp_object_tree, offset2+16, 4, 
				 "Token bucket size: %ld", 
				 ieee_to_long(pd+offset2+16));
		proto_tree_add_item(rsvp_object_tree, offset2+20, 4, 
				 "Peak data rate: %ld", 
				 ieee_to_long(pd+offset2+20));
		proto_tree_add_item(rsvp_object_tree, offset2+24, 4, 
				 "Minimum policed unit: %d", 
				 pntohl(pd+offset2+24));
		proto_tree_add_item(rsvp_object_tree, offset2+28, 4, 
				 "Maximum policed unit: %d", 
				 pntohl(pd+offset2+28));
		if (flowspec->service_header!=QOS_GUARANTEED)
		    break;

		/* Guaranteed-rate RSpec */
		is_param_str = match_strval(flowspec->param_id_rspec, svc_vals);
		if (!is_param_str) is_param_str="Unknown";
		proto_tree_add_item(rsvp_object_tree, offset2+32, 1, 
				 "Parameter ID: %d - %s", 
				 flowspec->param_id, is_param_str);
		proto_tree_add_item(rsvp_object_tree, offset2+33, 1, 
				 "Parameter %d flags: %d", 
				 flowspec->param_id, flowspec->flags_rspec);
		proto_tree_add_item(rsvp_object_tree, offset2+34, 2, 
				 "Length of parameter %d data: %d words, " 
				 "not including header",
				 flowspec->param_id,
				 pntohs(pd+offset2+34));
		proto_tree_add_item(rsvp_object_tree, offset2+36, 4, 
				 "Rate: %ld", 
				 ieee_to_long(pd+offset2+36));
		proto_tree_add_item(rsvp_object_tree, offset2+40, 4, 
				 "Slack term: %d", 
				 pntohl(pd+offset2+40));

		break;
	    }

	    case RSVP_CLASS_ADSPEC : {
		proto_tree *adspec_tree;
		service_hdr *shdr;
		param_hdr *phdr; 

		char *str;
		int tree_num;

		mylen = obj_length;
		proto_item_add_subtree(ti, rsvp_object_tree, ETT_RSVP_ADSPEC);
		proto_tree_add_item(rsvp_object_tree, offset, 2, "Length: %d", 
				    obj_length);
		proto_tree_add_item(rsvp_object_tree, offset+2, 1, 
				    "Class number: %d - %s", 
				    obj->class, object_type);
		
		proto_tree_add_item(rsvp_object_tree, offset2, 1, 
				    "Message format version: %d", 
				    (*((unsigned char *)pd+offset2))>>4);
		proto_tree_add_item(rsvp_object_tree, offset2+2, 2, 
				    "Data length: %d words, not including header", 
				    pntohs(pd+offset2+2));
		offset2+=4;
		tree_num=ETT_RSVP_ADSPEC_SUBTREE1;
		mylen -= 4;
		while (mylen > 4) {
		    shdr = (service_hdr *)(pd + offset2);
		    str = match_strval(shdr->service_num, adspec_services);

		    ti = proto_tree_add_item(rsvp_object_tree, offset2, 
					     (pntohs(&shdr->length)+1)<<2,
					     str?str:"Unknown");
		    adspec_tree = proto_tree_new();
		    proto_item_add_subtree(ti, adspec_tree, tree_num++);
		    proto_tree_add_item(adspec_tree, offset2, 1,
					"Service header %d - %s",
					shdr->service_num, str);
		    proto_tree_add_item(adspec_tree, offset2+1, 1,
					(shdr->break_bit&0x80)?
					"Break bit set":"Break bit not set");
		    proto_tree_add_item(adspec_tree, offset2+2, 2, 
					"Data length: %d 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_item(adspec_tree, offset2, 
						    (pntohs(&phdr->length)+1)<<2,
						    "%s - %lu (type %d, length %d)",
						    str, 
						    (unsigned long)pntohl(&phdr->dataval), 
						    phdr->id, pntohs(&phdr->length));
				break;
				
			    case 6:
				/* IEEE float */
				proto_tree_add_item(adspec_tree, offset2, 
						    (pntohs(&phdr->length)+1)<<2,
						    "%s - %lu (type %d, length %d)",
						    str, 
						    ieee_to_long(&phdr->dataval), 
						    phdr->id, pntohs(&phdr->length));
				break;
			    default: 
				proto_tree_add_item(adspec_tree, offset2, 
						    (pntohs(&phdr->length)+1)<<2,
						    "%s (type %d, length %d)",
						    str, 
						    phdr->id, pntohs(&phdr->length));
			    }
			} else {
			    proto_tree_add_item(adspec_tree, offset2, 
						(pntohs(&phdr->length)+1)<<2,
						"Unknown (type %d, length %d)",
						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 :
		proto_item_add_subtree(ti, rsvp_object_tree, ETT_RSVP_INTEGRITY);
		proto_tree_add_item(rsvp_object_tree, offset, 2, "Length: %d", 
				    obj_length);
		proto_tree_add_item(rsvp_object_tree, offset+2, 1, 
				    "Class number: %d - %s", 
				    obj->class, object_type);
		goto default_class;

	    case RSVP_CLASS_POLICY :
		proto_item_add_subtree(ti, rsvp_object_tree, ETT_RSVP_POLICY);
		proto_tree_add_item(rsvp_object_tree, offset, 2, "Length: %d", 
				    obj_length);
		proto_tree_add_item(rsvp_object_tree, offset+2, 1, 
				    "Class number: %d - %s", 
				    obj->class, object_type);
		goto default_class;

	    default :
		proto_item_add_subtree(ti, rsvp_object_tree, ETT_RSVP_UNKNOWN_CLASS);
		proto_tree_add_item(rsvp_object_tree, offset, 2, "Length: %d", 
				    obj_length);
		proto_tree_add_item(rsvp_object_tree, offset+2, 1, 
				    "Class number: %d - %s", 
				    obj->class, object_type);
	    default_class:
		i = obj_length - sizeof(rsvp_object);
		proto_tree_add_item(rsvp_object_tree, offset2, i,
				 "Data (%d bytes)", i);
		break;

	    case RSVP_CLASS_NULL :
		break;

	    }  
	    
	    offset += obj_length;
	    len += obj_length;
	}
    }
}

Attachment: eth0.cap
Description: Binary data

Attachment: eth1.cap
Description: Binary data