Updates from Ed Warnicke.
[obnox/wireshark/wip.git] / packet-rsvp.c
1 /* packet-rsvp.c
2  * Routines for RSVP packet disassembly
3  *
4  * (c) Copyright Ashok Narayanan <ashokn@cisco.com>
5  *
6  * $Id: packet-rsvp.c,v 1.28 2000/11/19 08:54:04 guy Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@zing.org>
10  * Copyright 1998 Gerald Combs
11  * 
12  * 
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  * 
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  * 
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26  */
27
28 /*
29  * NOTES
30  *
31  * This module defines routines to disassemble RSVP packets, as defined in
32  * RFC 2205. All objects from RC2205 are supported, in IPv4 and IPv6 mode.
33  * In addition, the Integrated Services traffic specification objects
34  * defined in RFC2210 are also supported. 
35  *
36  * IPv6 support is not completely tested
37  *
38  * Mar 3, 2000: Added support for MPLS/TE objects, as defined in 
39  * <draft-ietf-mpls-rsvp-lsp-tunnel-04.txt>
40  */
41
42  
43 #ifdef HAVE_CONFIG_H
44 # include "config.h"
45 #endif
46
47 #include <stdio.h>
48
49 #ifdef HAVE_UNISTD_H
50 #include <unistd.h>
51 #endif
52
53 #include <stdlib.h>
54 #include <string.h>
55
56 #ifdef HAVE_SYS_TYPES_H
57 # include <sys/types.h>
58 #endif
59
60 #ifdef HAVE_NETINET_IN_H
61 # include <netinet/in.h>
62 #endif
63
64 #include <glib.h>
65
66 #ifdef NEED_SNPRINTF_H
67 # include "snprintf.h"
68 #endif
69
70 #include "packet.h"
71 #include "packet-ip.h"
72 #include "packet-ipv6.h"
73 #include "ieee-float.h"
74
75 static int proto_rsvp = -1;
76
77 static gint ett_rsvp = -1;
78 static gint ett_rsvp_hdr = -1;
79 static gint ett_rsvp_session = -1;
80 static gint ett_rsvp_hop = -1;
81 static gint ett_rsvp_time_values = -1;
82 static gint ett_rsvp_error = -1;
83 static gint ett_rsvp_scope = -1;
84 static gint ett_rsvp_style = -1;
85 static gint ett_rsvp_confirm = -1;
86 static gint ett_rsvp_sender_template = -1;
87 static gint ett_rsvp_filter_spec = -1;
88 static gint ett_rsvp_sender_tspec = -1;
89 static gint ett_rsvp_flowspec = -1;
90 static gint ett_rsvp_adspec = -1;
91 static gint ett_rsvp_adspec_subtree = -1;
92 static gint ett_rsvp_integrity = -1;
93 static gint ett_rsvp_policy = -1;
94 static gint ett_rsvp_label = -1;
95 static gint ett_rsvp_label_request = -1;
96 static gint ett_rsvp_session_attribute = -1;
97 static gint ett_rsvp_session_attribute_flags = -1;
98 static gint ett_rsvp_explicit_route = -1;
99 static gint ett_rsvp_explicit_route_subobj = -1;
100 static gint ett_rsvp_record_route = -1;
101 static gint ett_rsvp_record_route_subobj = -1;
102 static gint ett_rsvp_unknown_class = -1;
103
104
105 /*
106  * RSVP message types
107  */
108 typedef enum {
109     RSVP_MSG_PATH=1, RSVP_MSG_RESV, RSVP_MSG_PERR, RSVP_MSG_RERR,
110     RSVP_MSG_PTEAR, RSVP_MSG_RTEAR, RSVP_MSG_CONFIRM, 
111     RSVP_MSG_RTEAR_CONFIRM=10
112 } rsvp_message_types;
113
114 static value_string message_type_vals[] = { 
115     {RSVP_MSG_PATH, "PATH Message"},
116     {RSVP_MSG_RESV, "RESV Message"},
117     {RSVP_MSG_PERR, "PATH ERROR Message"},
118     {RSVP_MSG_RERR, "RESV ERROR Message"},
119     {RSVP_MSG_PTEAR, "PATH TEAR Message"},
120     {RSVP_MSG_RTEAR, "RESV TEAR Message"},
121     {RSVP_MSG_CONFIRM, "CONFIRM Message"},
122     {RSVP_MSG_RTEAR_CONFIRM, "RESV TEAR CONFIRM Message"}
123 };
124
125 /* 
126  * RSVP classes
127  */
128 #define MAX_RSVP_CLASS 15
129
130 enum rsvp_classes {
131     RSVP_CLASS_NULL=0,
132     RSVP_CLASS_SESSION,
133
134     RSVP_CLASS_HOP=3,
135     RSVP_CLASS_INTEGRITY,
136     RSVP_CLASS_TIME_VALUES,
137     RSVP_CLASS_ERROR,
138     RSVP_CLASS_SCOPE,
139     RSVP_CLASS_STYLE,
140     RSVP_CLASS_FLOWSPEC,
141     RSVP_CLASS_FILTER_SPEC,
142     RSVP_CLASS_SENDER_TEMPLATE,
143     RSVP_CLASS_SENDER_TSPEC,
144     RSVP_CLASS_ADSPEC,
145     RSVP_CLASS_POLICY,
146     RSVP_CLASS_CONFIRM,
147     RSVP_CLASS_LABEL,
148
149     RSVP_CLASS_LABEL_REQUEST=19,
150     RSVP_CLASS_EXPLICIT_ROUTE,
151     RSVP_CLASS_RECORD_ROUTE,
152
153     RSVP_CLASS_SESSION_ATTRIBUTE=207,
154 };
155
156 static value_string rsvp_class_vals[] = { 
157     {RSVP_CLASS_NULL, "NULL object"},
158     {RSVP_CLASS_SESSION, "SESSION object"},
159     {RSVP_CLASS_HOP, "HOP object"},
160     {RSVP_CLASS_INTEGRITY, "INTEGRITY object"},
161     {RSVP_CLASS_TIME_VALUES, "TIME VALUES object"},
162     {RSVP_CLASS_ERROR, "ERROR object"},
163     {RSVP_CLASS_SCOPE, "SCOPE object"},
164     {RSVP_CLASS_STYLE, "STYLE object"},
165     {RSVP_CLASS_FLOWSPEC, "FLOWSPEC object"},
166     {RSVP_CLASS_FILTER_SPEC, "FILTER SPEC object"},
167     {RSVP_CLASS_SENDER_TEMPLATE, "SENDER TEMPLATE object"},
168     {RSVP_CLASS_SENDER_TSPEC, "SENDER TSPEC object"},
169     {RSVP_CLASS_ADSPEC, "ADSPEC object"},
170     {RSVP_CLASS_POLICY, "POLICY object"},
171     {RSVP_CLASS_CONFIRM, "CONFIRM object"},
172     {RSVP_CLASS_LABEL, "LABEL object"},
173     {RSVP_CLASS_LABEL_REQUEST, "LABEL REQUEST object"},
174     {RSVP_CLASS_EXPLICIT_ROUTE, "EXPLICIT ROUTE object"},
175     {RSVP_CLASS_RECORD_ROUTE, "RECORD ROUTE object"},
176     {RSVP_CLASS_SESSION_ATTRIBUTE, "SESSION ATTRIBUTE object"},
177 };
178
179 /*
180  * RSVP error values
181  */
182 enum rsvp_error_types {
183     RSVP_ERROR_CONFIRM = 0,
184     RSVP_ERROR_ADMISSION,
185     RSVP_ERROR_POLICY,
186     RSVP_ERROR_NO_PATH,
187     RSVP_ERROR_NO_SENDER,
188     RSVP_ERROR_CONFLICT_RESV_STYLE,
189     RSVP_ERROR_UNKNOWN_RESV_STYLE,
190     RSVP_ERROR_CONFLICT_DEST_PORTS,
191     RSVP_ERROR_CONFLICT_SRC_PORTS,
192     RSVP_ERROR_PREEMPTED=12,
193     RSVP_ERROR_UNKNOWN_CLASS,
194     RSVP_ERROR_UNKNOWN_C_TYPE,
195     RSVP_ERROR_TRAFFIC = 21,
196     RSVP_ERROR_TRAFFIC_SYSTEM,
197     RSVP_ERROR_SYSTEM
198 };
199
200 static value_string rsvp_error_vals[] = {
201     {RSVP_ERROR_CONFIRM, "Confirmation"},
202     {RSVP_ERROR_ADMISSION, "Admission Control Failure "},
203     {RSVP_ERROR_POLICY, "Policy Control Failure"},
204     {RSVP_ERROR_NO_PATH, "No PATH information for this RESV message"},
205     {RSVP_ERROR_NO_SENDER, "No sender information for this RESV message"},
206     {RSVP_ERROR_CONFLICT_RESV_STYLE, "Conflicting reservation styles"},
207     {RSVP_ERROR_UNKNOWN_RESV_STYLE, "Unknown reservation style"},
208     {RSVP_ERROR_CONFLICT_DEST_PORTS, "Conflicting destination ports"},
209     {RSVP_ERROR_CONFLICT_SRC_PORTS, "Conflicting source ports"},
210     {RSVP_ERROR_PREEMPTED, "Service preempted"},
211     {RSVP_ERROR_UNKNOWN_CLASS, "Unknown object class"},
212     {RSVP_ERROR_UNKNOWN_C_TYPE, "Unknown object C-type"},
213     {RSVP_ERROR_TRAFFIC, "Traffic Control Error"},
214     {RSVP_ERROR_TRAFFIC_SYSTEM, "Traffic Control System Error"}
215 };
216
217 /*
218  * Defines the reservation style plus style-specific information that
219  * is not a FLOWSPEC or FILTER_SPEC object, in a RESV message.
220  */
221 #define RSVP_DISTINCT (1 << 3)
222 #define RSVP_SHARED (2 << 3)
223 #define RSVP_SHARING_MASK (RSVP_DISTINCT | RSVP_SHARED)
224
225 #define RSVP_SCOPE_WILD 1
226 #define RSVP_SCOPE_EXPLICIT 2
227 #define RSVP_SCOPE_MASK 0x07
228
229 #define RSVP_WF (RSVP_SHARED | RSVP_SCOPE_WILD)
230 #define RSVP_FF (RSVP_DISTINCT | RSVP_SCOPE_EXPLICIT)
231 #define RSVP_SE (RSVP_SHARED | RSVP_SCOPE_EXPLICIT)
232
233 static value_string style_vals[] = {
234     { RSVP_WF, "Wildcard Filter" },
235     { RSVP_FF, "Fixed Filter" },
236     { RSVP_SE, "Shared-Explicit" }
237 };
238
239 /*------------------------------*
240  * Object definitions
241  *------------------------------*/
242
243 /*
244  * Base RSVP object
245  */
246 typedef struct {
247     guint16 length;
248     guint8 class;       
249     guint8 type;
250     /* Data follows, as a sequence of bytes */
251 } rsvp_object;
252
253 /*
254  * RSVP message header
255  */
256
257 typedef struct {
258     guint8    ver_flags;                /* RSVP Version & flags */
259     guint8    message_type;             /* type of message */
260     guint16   cksum;                    /* IP Checksum */
261     guint8    sending_ttl;              /* ttl of message */
262     guint8    reserved_byte;            /* reserved */
263     guint16   rsvp_length;              /* length of RSVP data */
264     /* Objects follow, as a sequence of "rsvp_object"s */
265 } rsvp_header;
266
267 /*
268  * NULL object 
269 */
270 typedef struct {
271     rsvp_object base;
272 } rsvp_null;
273
274 /*
275  * SESSION object
276  */
277 typedef struct {
278     rsvp_object base;
279     guint32 destination;
280     guint8 protocol;
281     guint8 flags;
282     guint16 port;
283 } rsvp_session_ipv4;
284
285 typedef struct {
286     rsvp_object base;
287     struct e_in6_addr destination;
288     guint8 protocol;
289     guint8 flags;
290     guint16 port;
291 } rsvp_session_ipv6;
292
293 /*
294  * HOP object
295  * Can be a PHOP or a NHOP
296  */
297 typedef struct {
298     rsvp_object base;
299     guint32 neighbor;
300     guint32 lif_handle;
301 } rsvp_hop_ipv4;
302
303 typedef struct {
304     rsvp_object base;
305     struct e_in6_addr neighbor;
306     guint32 lif_handle;
307 } rsvp_hop_ipv6;
308
309 /*
310  * TIME_VALUES object
311  */
312 typedef struct {
313     rsvp_object base;
314     gint32 refresh_ms;
315 } rsvp_time_values;
316
317 /*
318  * ERROR object
319  */
320 typedef struct {
321     rsvp_object base;
322     guint32 error_node;
323     guint8 flags;
324     guint8 error_code;
325     guint16 error_value;
326 } rsvp_error_ipv4;
327
328 typedef struct {
329     rsvp_object base;
330     struct e_in6_addr error_node;
331     guint8 flags;
332     guint8 error_code;
333     guint16 error_value;
334 } rsvp_error_ipv6;
335
336 /*
337  * CONFIRM object
338  */
339 typedef struct {
340     rsvp_object base;
341     guint32 receiver;
342 } rsvp_confirm_ipv4;
343
344 typedef struct {
345     rsvp_object base;
346     struct e_in6_addr receiver;
347 } rsvp_confirm_ipv6;
348
349 /*
350  * SCOPE object
351  */
352 typedef struct {
353     rsvp_object base;
354     /* Source follows, as a sequence of 32-bit integers */
355 } rsvp_scope;
356
357 /*
358  * STYLE object
359  */
360 typedef struct {
361     rsvp_object base;
362     guint32 reservation_type;
363 } rsvp_style;
364
365 /*
366  * Defines a subset of session data packets that should receive the
367  * desired QoS (specified by an FLOWSPEC object), in a RESV message.
368  */
369 typedef struct {
370     rsvp_object base;
371     guint32 source;                     /* source sending data */
372     guint16 unused;
373     guint16 udp_source_port;            /* port number */
374 } rsvp_filter_ipv4;
375
376 /*
377  * Contains a sender IP address and perhaps some additional
378  * demultiplexing information to identify a sender, in a PATH
379  * message.
380  */
381 typedef struct {
382     rsvp_object base;
383     guint32 source;                     /* source sending data */
384     guint16 __reserved;
385     guint16 source_port;                /* port number */
386 } rsvp_template_ipv4;
387
388 typedef struct {
389     rsvp_object base;
390     struct e_in6_addr source;           /* source sending data */
391     guint16 __reserved;
392     guint16 source_port;                /* port number */
393 } rsvp_template_ipv6;
394
395 /*
396  * Defines a desired QoS, in a RESV message.
397  */
398 enum    qos_service_type {
399     QOS_QUALITATIVE =     128,          /* Qualitative service */
400     QOS_CONTROLLED_LOAD=    5,          /* Controlled Load Service */
401     QOS_GUARANTEED =        2,          /* Guaranteed service */
402     QOS_TSPEC =             1           /* Traffic specification */
403     };
404
405 static value_string qos_vals[] = {
406     { QOS_QUALITATIVE, "Qualitative QoS" },
407     { QOS_CONTROLLED_LOAD, "Controlled-load QoS" },
408     { QOS_GUARANTEED, "Guaranteed rate QoS" },
409     { QOS_TSPEC, "Traffic specification" },
410 };
411
412 static value_string svc_vals[] = {
413     { 127, "Token bucket TSpec" },
414     { 128, "Qualitative TSpec" },
415     { 130, "Guaranteed-rate RSpec" }
416 };
417
418 enum rsvp_spec_types { INTSRV = 2 };
419
420 enum intsrv_services {
421         INTSRV_GENERAL = 1,
422         INTSRV_GTD = 2,
423         INTSRV_CLOAD = 5,
424         INTSRV_QUALITATIVE = 128
425 };
426
427 static value_string intsrv_services_str[] = { 
428     {INTSRV_GENERAL, "Default General Parameters"},
429     {INTSRV_GTD, "Guaranteed"},
430     {INTSRV_CLOAD, "Controlled Load"},
431     {INTSRV_QUALITATIVE, "Qualitative"},
432 };
433
434 enum intsrv_field_name {
435         INTSRV_NON_IS_HOPS = 1, INTSRV_COMPOSED_NON_IS_HOPS,
436         INTSRV_IS_HOPS, INTSRV_COMPOSED_IS_HOPS,
437         INTSRV_PATH_BANDWIDTH, INTSRV_MIN_PATH_BANDWIDTH,
438         INTSRV_IF_LATENCY, INTSRV_PATH_LATENCY,
439         INTSRV_MTU, INTSRV_COMPOSED_MTU,
440
441         INTSRV_TOKEN_BUCKET_TSPEC = 127,
442         INTSRV_QUALITATIVE_TSPEC = 128,
443         INTSRV_GTD_RSPEC = 130,
444
445         INTSRV_DELAY = 131,     /* Gtd Parameter C - Max Delay Bound - bytes */
446         INTSRV_MAX_JITTER,      /* Gtd Parameter D - Max Jitter */
447         INTSRV_E2E_DELAY,       /* Gtd Parameter Ctot */
448         INTSRV_E2E_MAX_JITTER,  /* Gtd Parameter Dtot */
449         INTSRV_SHP_DELAY,       /* Gtd Parameter Csum */
450         INTSRV_SHP_MAX_JITTER   /* Gtd Parameter Dsum */
451 };
452
453 /*
454  * Subobjects for Integrated Services
455  */
456
457 typedef struct {
458     guint8 service_num;
459     guint8 break_bit;
460     guint16 length;
461 } service_hdr;
462
463 typedef struct {                                        
464     service_hdr svchdr;
465
466     guint8      param_id;
467     guint8      flags_tspec;
468     guint16     parameter_length;
469
470     guint32     rate;
471     guint32     depth;
472     guint32     peak;
473     guint32     min_unit;
474     guint32     max_unit;
475 } IS_tspec; /* RFC2210 */
476
477 typedef struct {
478     service_hdr svchdr;
479     
480     guint8      param_id;
481     guint8      flags_tspec;
482     guint16     parameter_length;
483
484     guint32     max_unit;
485 } QUAL_tspec; /* Qualitative */
486
487 typedef struct {
488     rsvp_object base;
489     guint8      version;        
490     guint8      __reserved_;
491     guint16     length_in_words;
492
493     /* Data follows, as a sequence of bytes */
494 } rsvp_tspec;
495
496 typedef struct {
497     guint8      param_id;
498     guint8      flags_rspec;
499     guint16     param2_length;
500     guint32     requested_rate;
501     guint32     slack;
502 } IS_rspec;
503
504 typedef struct {
505     IS_tspec tspec;
506     IS_rspec rspec;
507 } IS_flowspec; /* RFC 2210 */
508
509 typedef struct {
510     service_hdr svchdr;
511     
512     guint8      param_id;
513     guint8      flags_tspec;
514     guint16     parameter_length;
515
516     guint32     max_unit;
517 } QUAL_flowspec; /* Qualitative */
518
519
520 typedef struct {
521     rsvp_object base;
522     guint8      version;        
523     guint8      __reserved_;
524     guint16     length_in_words;
525
526     /* Data follows, as a sequence of bytes */
527 } rsvp_flowspec;
528                                         
529
530 typedef struct {
531     guint8 id;
532     guint8 flags;
533     guint16 length;
534     guint32 dataval;
535 } param_hdr;
536     
537 static value_string adspec_params[] = { 
538     {4, "IS Hop Count"},
539     {6, "Path b/w estimate"},
540     {8, "Minimum path latency"},
541     {10, "Composed MTU"},
542     {133, "End-to-end composed value for C"},
543     {134, "End-to-end composed value for D"},
544     {135, "Since-last-reshaping point composed C"},
545     {136, "Since-last-reshaping point composed D"},
546 };
547
548 /* -------------------- Stuff for MPLS/TE objects -------------------- */
549
550 typedef struct {
551     rsvp_object base;
552 } label;                /* array of 32-bit labels follows */
553
554 typedef struct {
555     rsvp_object base;
556     guint16 _reserved;
557     guint16 l3pid;
558 } label_request;
559
560 typedef struct {
561     rsvp_object base;
562     guint8 setup_prio;
563     guint8 hold_prio;
564     guint8 flags;
565     guint8 name_len;
566 } session_attribute;    /* name follows, as string */
567
568 static const value_string proto_vals[] = { {IP_PROTO_ICMP, "ICMP"},
569                                            {IP_PROTO_IGMP, "IGMP"},
570                                            {IP_PROTO_TCP,  "TCP" },
571                                            {IP_PROTO_UDP,  "UDP" },
572                                            {IP_PROTO_OSPF, "OSPF"},
573                                            {0,             NULL  } };
574
575 /* Filter keys */
576 enum rsvp_filter_keys {
577
578     /* Message types */
579     RSVPF_MSG,          /* Message type */
580     /* Shorthand for message types */
581     RSVPF_PATH,
582     RSVPF_RESV,
583     RSVPF_PATHERR,
584     RSVPF_RESVERR,
585     RSVPF_PATHTEAR,
586     RSVPF_RESVTEAR,
587     RSVPF_RCONFIRM,
588     RSVPF_JUNK_MSG8,
589     RSVPF_JUNK_MSG9,
590     RSVPF_RTEARCONFIRM,
591
592     /* Does the message contain an object of this type? */
593     RSVPF_OBJECT,
594     /* Object present shorthands */
595     RSVPF_SESSION,
596     RSVPF_DUMMY_1,
597     RSVPF_HOP,
598     RSVPF_INTEGRITY,
599     RSVPF_TIME_VALUES,
600     RSVPF_ERROR,
601     RSVPF_SCOPE,
602     RSVPF_STYLE,
603     RSVPF_FLOWSPEC,
604     RSVPF_FILTER_SPEC,
605     RSVPF_SENDER,
606     RSVPF_TSPEC,
607     RSVPF_ADSPEC,
608     RSVPF_POLICY,
609     RSVPF_CONFIRM,
610     RSVPF_LABEL,
611     RSVPF_DUMMY_2,
612     RSVPF_DUMMY_3,
613     RSVPF_LABEL_REQUEST,
614     RSVPF_EXPLICIT_ROUTE,
615     RSVPF_RECORD_ROUTE,
616
617     RSVPF_SESSION_ATTRIBUTE,
618
619     RSVPF_UNKNOWN_OBJ, 
620
621     /* Session object */
622     RSVPF_SESSION_IP,
623     RSVPF_SESSION_PROTO,
624     RSVPF_SESSION_PORT,
625     RSVPF_SESSION_TUNNEL_ID,
626     RSVPF_SESSION_EXT_TUNNEL_ID,
627
628     /* Sender template */
629     RSVPF_SENDER_IP,
630     RSVPF_SENDER_PORT,
631     RSVPF_SENDER_LSP_ID,
632
633     /* Sentinel */
634     RSVPF_MAX
635 };
636
637 static int rsvp_filter[RSVPF_MAX];
638
639 static hf_register_info rsvpf_info[] = {
640
641     /* Message type number */
642     {&rsvp_filter[RSVPF_MSG], 
643      { "Message Type", "rsvp.msg", FT_UINT8, BASE_NONE, message_type_vals, 0x0,
644         "" }},
645
646     /* Message type shorthands */
647     {&rsvp_filter[RSVPF_PATH], 
648      { "Path Message", "rsvp.path", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
649         "" }},
650
651     {&rsvp_filter[RSVPF_RESV], 
652      { "Resv Message", "rsvp.resv", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
653         "" }},
654
655     {&rsvp_filter[RSVPF_PATHERR], 
656      { "Path Error Message", "rsvp.perr", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
657         "" }},
658
659     {&rsvp_filter[RSVPF_RESVERR], 
660      { "Resv Error Message", "rsvp.rerr", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
661         "" }},
662
663     {&rsvp_filter[RSVPF_PATHTEAR], 
664      { "Path Tear Message", "rsvp.ptear", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
665         "" }},
666
667     {&rsvp_filter[RSVPF_RESVTEAR], 
668      { "Resv Tear Message", "rsvp.rtear", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
669         "" }},
670
671     {&rsvp_filter[RSVPF_RCONFIRM], 
672      { "Resv Confirm Message", "rsvp.resvconf", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
673         "" }},
674
675     {&rsvp_filter[RSVPF_RTEARCONFIRM], 
676      { "Resv Tear Confirm Message", "rsvp.rtearconf", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
677         "" }},
678
679     /* Object present */
680     {&rsvp_filter[RSVPF_OBJECT], 
681      { "", "rsvp.object", FT_UINT8, BASE_NONE, rsvp_class_vals, 0x0,
682         "" }},
683
684     /* Object present shorthands */
685     {&rsvp_filter[RSVPF_SESSION], 
686      { "SESSION", "rsvp.session", FT_UINT8, BASE_NONE, NULL, 0x0,
687         "" }},
688
689     {&rsvp_filter[RSVPF_HOP], 
690      { "HOP", "rsvp.hop", FT_UINT8, BASE_NONE, NULL, 0x0,
691         "" }},
692
693     {&rsvp_filter[RSVPF_INTEGRITY], 
694      { "INTEGRITY", "rsvp.integrity", FT_UINT8, BASE_NONE, NULL, 0x0,
695         "" }},
696
697     {&rsvp_filter[RSVPF_TIME_VALUES], 
698      { "TIME VALUES", "rsvp.time", FT_UINT8, BASE_NONE, NULL, 0x0,
699         "" }},
700
701     {&rsvp_filter[RSVPF_ERROR], 
702      { "ERROR", "rsvp.error", FT_UINT8, BASE_NONE, NULL, 0x0,
703         "" }},
704
705     {&rsvp_filter[RSVPF_SCOPE], 
706      { "SCOPE", "rsvp.scope", FT_UINT8, BASE_NONE, NULL, 0x0,
707         "" }},
708
709     {&rsvp_filter[RSVPF_STYLE], 
710      { "STYLE", "rsvp.style", FT_UINT8, BASE_NONE, NULL, 0x0,
711         "" }},
712
713     {&rsvp_filter[RSVPF_FLOWSPEC], 
714      { "FLOWSPEC", "rsvp.flowspec", FT_UINT8, BASE_NONE, NULL, 0x0,
715         "" }},
716
717     {&rsvp_filter[RSVPF_FILTER_SPEC], 
718      { "FILTERSPEC", "rsvp.filter", FT_UINT8, BASE_NONE, NULL, 0x0,
719         "" }},
720
721     {&rsvp_filter[RSVPF_SENDER], 
722      { "SENDER TEMPLATE", "rsvp.sender", FT_UINT8, BASE_NONE, NULL, 0x0,
723         "" }},
724
725     {&rsvp_filter[RSVPF_TSPEC], 
726      { "SENDER TSPEC", "rsvp.tspec", FT_UINT8, BASE_NONE, NULL, 0x0,
727         "" }},
728
729     {&rsvp_filter[RSVPF_ADSPEC], 
730      { "ADSPEC", "rsvp.adspec", FT_UINT8, BASE_NONE, NULL, 0x0,
731         "" }},
732
733     {&rsvp_filter[RSVPF_POLICY], 
734      { "POLICY", "rsvp.policy", FT_UINT8, BASE_NONE, NULL, 0x0,
735         "" }},
736
737     {&rsvp_filter[RSVPF_CONFIRM], 
738      { "CONFIRM", "rsvp.confirm", FT_UINT8, BASE_NONE, NULL, 0x0,
739         "" }},
740
741     {&rsvp_filter[RSVPF_LABEL], 
742      { "LABEL", "rsvp.label", FT_UINT8, BASE_NONE, NULL, 0x0,
743         "" }},
744
745     {&rsvp_filter[RSVPF_LABEL_REQUEST], 
746      { "LABEL REQUEST", "rsvp.label_request", FT_UINT8, BASE_NONE, NULL, 0x0,
747         "" }},
748
749     {&rsvp_filter[RSVPF_SESSION_ATTRIBUTE], 
750      { "SESSION ATTRIBUTE", "rsvp.session_attribute", FT_UINT8, BASE_NONE, NULL, 0x0,
751         "" }},
752
753     {&rsvp_filter[RSVPF_EXPLICIT_ROUTE], 
754      { "EXPLICIT ROUTE", "rsvp.explicit_route", FT_UINT8, BASE_NONE, NULL, 0x0,
755         "" }},
756
757     {&rsvp_filter[RSVPF_RECORD_ROUTE], 
758      { "RECORD ROUTE", "rsvp.record_route", FT_UINT8, BASE_NONE, NULL, 0x0,
759         "" }},
760
761     {&rsvp_filter[RSVPF_UNKNOWN_OBJ], 
762      { "Unknown object", "rsvp.obj_unknown", FT_UINT8, BASE_NONE, NULL, 0x0,
763         "" }},
764
765     /* Session fields */
766     {&rsvp_filter[RSVPF_SESSION_IP], 
767      { "Destination address", "rsvp.session.ip", FT_IPv4, BASE_NONE, NULL, 0x0,
768         "" }},
769
770     {&rsvp_filter[RSVPF_SESSION_PORT], 
771      { "Port number", "rsvp.session.port", FT_UINT16, BASE_NONE, NULL, 0x0,
772         "" }},
773
774     {&rsvp_filter[RSVPF_SESSION_PROTO], 
775      { "Protocol", "rsvp.session.proto", FT_UINT8, BASE_NONE, VALS(proto_vals), 0x0,
776         "" }},
777
778     {&rsvp_filter[RSVPF_SESSION_TUNNEL_ID], 
779      { "Tunnel ID", "rsvp.session.tunnel_id", FT_UINT16, BASE_NONE, NULL, 0x0,
780         "" }},
781
782     {&rsvp_filter[RSVPF_SESSION_EXT_TUNNEL_ID], 
783      { "Extended tunnel ID", "rsvp.session.ext_tunnel_id", FT_UINT32, BASE_NONE, NULL, 0x0,
784         "" }},
785
786     /* Sender template/Filterspec fields */
787     {&rsvp_filter[RSVPF_SENDER_IP], 
788      { "Sender IPv4 address", "rsvp.sender.ip", FT_IPv4, BASE_NONE, NULL, 0x0,
789         "" }},
790
791     {&rsvp_filter[RSVPF_SENDER_PORT], 
792      { "Sender port number", "rsvp.sender.port", FT_UINT16, BASE_NONE, NULL, 0x0,
793        "" }},
794
795     {&rsvp_filter[RSVPF_SENDER_LSP_ID], 
796      { "Sender LSP ID", "rsvp.sender.lsp_id", FT_UINT16, BASE_NONE, NULL, 0x0,
797         "" }}
798 };
799
800 static inline int rsvp_class_to_filter_num(int classnum)
801 {
802     switch(classnum) {
803     case RSVP_CLASS_SESSION :
804     case RSVP_CLASS_HOP :
805     case RSVP_CLASS_INTEGRITY :
806     case RSVP_CLASS_TIME_VALUES :
807     case RSVP_CLASS_ERROR :
808     case RSVP_CLASS_SCOPE :
809     case RSVP_CLASS_STYLE :
810     case RSVP_CLASS_FLOWSPEC :
811     case RSVP_CLASS_FILTER_SPEC :
812     case RSVP_CLASS_SENDER_TEMPLATE :
813     case RSVP_CLASS_SENDER_TSPEC :
814     case RSVP_CLASS_ADSPEC :
815     case RSVP_CLASS_POLICY :
816     case RSVP_CLASS_CONFIRM :
817     case RSVP_CLASS_LABEL :
818     case RSVP_CLASS_LABEL_REQUEST :
819     case RSVP_CLASS_EXPLICIT_ROUTE :
820     case RSVP_CLASS_RECORD_ROUTE :
821         return classnum + RSVPF_OBJECT;
822         break;
823
824     case RSVP_CLASS_SESSION_ATTRIBUTE :
825         return RSVPF_SESSION_ATTRIBUTE;
826         
827     default:
828         return RSVPF_UNKNOWN_OBJ;
829     }
830 }
831
832 static void 
833 dissect_rsvp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) 
834 {
835     proto_tree *rsvp_tree = NULL, *ti, *ti2; 
836     proto_tree *rsvp_header_tree;
837     proto_tree *rsvp_object_tree;
838     proto_tree *rsvp_sa_flags_tree;
839     proto_tree *rsvp_ero_subtree;
840     char *packet_type, *object_type;
841     rsvp_header *hdr;
842     rsvp_object *obj;
843     int i, j, k, l, len, mylen;
844     int msg_length;
845     int obj_length;
846     int offset2;
847     struct e_in6_addr *ip6a;
848     guint32 ip_addr;
849
850     OLD_CHECK_DISPLAY_AS_DATA(proto_rsvp, pd, offset, fd, tree);
851
852     hdr = (rsvp_header *)&pd[offset];
853     packet_type = match_strval(hdr->message_type, message_type_vals);
854     if (check_col(fd, COL_PROTOCOL))
855         col_set_str(fd, COL_PROTOCOL, "RSVP");
856     if (check_col(fd, COL_INFO)) {
857         if (packet_type != NULL)
858             col_add_str(fd, COL_INFO, packet_type); 
859         else
860             col_add_fstr(fd, COL_INFO, "Unknown (%u)", hdr->message_type); 
861     }
862
863     if (tree) {
864         msg_length = pntohs(pd+offset+6);
865         ti = proto_tree_add_item(tree, proto_rsvp, NullTVB, offset, msg_length, FALSE);
866         rsvp_tree = proto_item_add_subtree(ti, ett_rsvp);
867
868         ti = proto_tree_add_text(rsvp_tree, NullTVB, offset, 
869                                  sizeof(rsvp_header), "RSVP Header"); 
870         rsvp_header_tree = proto_item_add_subtree(ti, ett_rsvp_hdr);
871
872         proto_tree_add_text(rsvp_header_tree, NullTVB, offset, 1, "RSVP Version: %u", 
873                             (hdr->ver_flags & 0xf0)>>4);  
874         proto_tree_add_text(rsvp_header_tree, NullTVB, offset, 1, "Flags: %02X",
875                             hdr->ver_flags & 0xf);  
876         proto_tree_add_uint(rsvp_header_tree, rsvp_filter[RSVPF_MSG], NullTVB, 
877                             offset+1, 1, hdr->message_type);
878         if (hdr->message_type <= RSVPF_RTEARCONFIRM &&
879                         hdr->message_type != RSVPF_JUNK_MSG8 &&
880                         hdr->message_type != RSVPF_JUNK_MSG9 ) {
881                proto_tree_add_boolean_hidden(rsvp_header_tree, rsvp_filter[RSVPF_MSG + hdr->message_type], NullTVB, 
882                                    offset+1, 1, 1);
883         }
884         proto_tree_add_text(rsvp_header_tree, NullTVB, offset + 2 , 2, "Message Checksum");
885         proto_tree_add_text(rsvp_header_tree, NullTVB, offset + 4 , 1, "Sending TTL: %u",
886                             hdr->sending_ttl);
887         proto_tree_add_text(rsvp_header_tree, NullTVB, offset + 6 , 2, "Message length: %d",
888                             msg_length);
889
890         offset += sizeof(rsvp_header);
891         len = 0;
892         while (len + sizeof(rsvp_header) < msg_length) {
893             obj = (rsvp_object *)&pd[offset];
894             obj_length = pntohs(pd+offset);
895             if (!BYTES_ARE_IN_FRAME(offset, obj_length)) {
896                 proto_tree_add_text(rsvp_tree, NullTVB, offset, 1, 
897                                     "Further data not captured");
898                 break;
899             }
900             
901             object_type = match_strval(obj->class, rsvp_class_vals);
902             if (!object_type) object_type = "Unknown";
903             ti = proto_tree_add_uint_hidden(rsvp_tree, rsvp_filter[RSVPF_OBJECT], NullTVB, 
904                                             offset, obj_length, obj->class);
905             ti = proto_tree_add_uint(rsvp_tree, rsvp_filter[rsvp_class_to_filter_num(obj->class)], NullTVB, 
906                                      offset, obj_length, obj->class);
907
908             offset2 = offset + sizeof(rsvp_object);
909
910             switch(obj->class) {
911
912             case RSVP_CLASS_SESSION :           
913                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_session);
914                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
915                                     obj_length);
916                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
917                                     "Class number: %u - %s", 
918                                     obj->class, object_type);
919                 switch(obj->type) {
920                 case 1: {
921                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
922                                         "C-type: 1 - IPv4");
923                     memcpy(&ip_addr, pd+offset2, 4);
924                     proto_tree_add_ipv4(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_IP], NullTVB, 
925                                         offset2, 4, ip_addr);
926
927                     proto_tree_add_uint(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_PROTO], NullTVB, 
928                                         offset2+4, 1, *(pd+offset2+4));
929                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+5, 1,
930                                         "Flags: %x", pntohs(pd+offset2+5));
931                     proto_tree_add_uint(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_PORT], NullTVB, 
932                                         offset2+6, 2, pntohs(pd+offset2+6));
933                     break;
934                 }
935
936                 case 2: {
937                     rsvp_session_ipv6 *sess = (rsvp_session_ipv6 *)obj;
938                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
939                                         "C-type: 2 - IPv6");
940                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 4, 
941                                         "Destination address: %s", 
942                                         ip6_to_str(&(sess->destination)));
943                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+16, 1,
944                                         "Protocol: %u", sess->protocol);
945                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+17, 1,
946                                         "Flags: %x", sess->flags);
947                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+18, 2,
948                                         "Destination port: %u", 
949                                         pntohs(pd+offset2+18));
950                     break;
951                 }
952                 
953                 case 7: {
954                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
955                                         "C-type: 7 - IPv4 LSP");
956                     memcpy(&ip_addr, pd+offset2, 4);
957                     proto_tree_add_ipv4(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_IP], NullTVB, 
958                                         offset2, 4, ip_addr);
959
960                     proto_tree_add_uint(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_TUNNEL_ID], NullTVB, 
961                                         offset2+6, 2, pntohs(pd+offset2+6));
962
963                     memcpy(&ip_addr, pd+offset2+8, 4);
964                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+8, 4, 
965                                         "Extended Tunnel ID: %lu (%s)", 
966                                         (unsigned long)ntohl(ip_addr),
967                                         ip_to_str(pd+offset2+8));
968                     proto_tree_add_uint_hidden(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_EXT_TUNNEL_ID], NullTVB, 
969                                         offset2+8, 4, ip_addr);
970                     break;
971                 }
972
973                 default: {
974                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
975                                         "C-type: Unknown (%u)",
976                                         obj->type);
977                     i = obj_length - sizeof(rsvp_object);
978                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
979                                         "Data (%d bytes)", i);
980                 }
981                 }
982                 break;
983                 
984             case RSVP_CLASS_HOP :               
985                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_hop);
986                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
987                                     obj_length);
988                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
989                                     "Class number: %u - %s", 
990                                     obj->class, object_type);
991                 switch(obj->type) {
992                 case 1: {
993                     rsvp_hop_ipv4 *hop = (rsvp_hop_ipv4 *)obj;
994                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
995                                         "C-type: 1 - IPv4");
996                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 4, 
997                                         "Neighbor address: %s", 
998                                         ip_to_str((guint8 *) &(hop->neighbor)));
999                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+4, 4,
1000                                         "Logical interface: %0x", 
1001                                         pntohl(pd+offset2+4));
1002                     break;
1003                 }
1004
1005                 case 2: {
1006                     rsvp_hop_ipv6 *hop = (rsvp_hop_ipv6 *)obj;
1007                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1008                                         "C-type: 2 - IPv6");
1009                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 4, 
1010                                         "Neighbor address: %s", 
1011                                         ip6_to_str(&(hop->neighbor)));
1012                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+16, 4,
1013                                         "Logical interface: %0x", 
1014                                         pntohl(pd+offset2+16));
1015                     break;
1016                 }
1017                 
1018                 default: {
1019                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1020                                         "C-type: Unknown (%u)",
1021                                         obj->type);
1022                     i = obj_length - sizeof(rsvp_object);
1023                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1024                                         "Data (%d bytes)", i);
1025                 }
1026                 }
1027                 break;
1028                 
1029             case RSVP_CLASS_TIME_VALUES : 
1030                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_time_values);
1031                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1032                                     obj_length);
1033                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1034                                     "Class number: %u - %s", 
1035                                     obj->class, object_type);
1036                 switch(obj->type) {
1037                 case 1: {
1038                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1039                                         "C-type: 1");
1040                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 4, 
1041                                         "Refresh interval: %u ms (%u seconds)",
1042                                         pntohl(pd+offset2),
1043                                         pntohl(pd+offset2)/1000);
1044                     break;
1045                 }
1046
1047                 default: {
1048                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1049                                         "C-type: Unknown (%u)",
1050                                         obj->type);
1051                     i = obj_length - sizeof(rsvp_object);
1052                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1053                                         "Data (%d bytes)", i);
1054                     break;
1055                 }
1056                 }
1057                 break;
1058
1059             case RSVP_CLASS_ERROR :
1060                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_error);
1061                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1062                                     obj_length);
1063                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1064                                     "Class number: %u - %s", 
1065                                     obj->class, object_type);
1066                 switch(obj->type) {
1067                 case 1: {
1068                     rsvp_error_ipv4 *err = (rsvp_error_ipv4 *)obj;
1069                     char *err_str = match_strval(err->error_code, rsvp_error_vals);
1070                     if (!err_str) err_str = "Unknown";
1071
1072                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1073                                         "C-type: 1 - IPv4");
1074                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 4, 
1075                                         "Error node: %s",
1076                                         ip_to_str((guint8 *) &(err->error_node)));
1077                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+4, 1,
1078                                         "Flags: %02x", err->flags);
1079                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+5, 1,
1080                                         "Error code: %u - %s", err->error_code,
1081                                         err_str);
1082                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+6, 2,
1083                                         "Error value: %u", pntohs(pd+offset2+6));
1084                     
1085                     break;
1086                 }
1087
1088                 case 2: {
1089                     rsvp_error_ipv6 *err = (rsvp_error_ipv6 *)obj;
1090                     char *err_str = match_strval(err->error_code, rsvp_error_vals);
1091                     if (!err_str) err_str = "Unknown";
1092                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1093                                         "C-type: 2 - IPv6");
1094                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 4, 
1095                                         "Error node: %s",
1096                                         ip6_to_str(&(err->error_node)));
1097                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+16, 1,
1098                                         "Flags: %02x", err->flags);
1099                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+17, 1,
1100                                         "Error code: %u - %s", err->error_code,
1101                                         err_str);
1102                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+18, 2,
1103                                         "Error value: %u", pntohs(pd+offset2+18));
1104                     
1105                     break;
1106                 }
1107                 
1108                 default: {
1109                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1110                                         "C-type: Unknown (%u)",
1111                                         obj->type);
1112                     i = obj_length - sizeof(rsvp_object);
1113                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1114                                         "Data (%d bytes)", i);
1115                 }
1116                 }
1117                 break;
1118                 
1119
1120             case RSVP_CLASS_SCOPE : 
1121                 mylen = obj_length;
1122                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_scope);
1123                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1124                                     obj_length);
1125                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1126                                     "Class number: %u - %s", 
1127                                     obj->class, object_type);
1128                 switch(obj->type) {
1129                 case 1: {
1130                     unsigned long ip;
1131                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1132                                         "C-type: 1 - IPv4");
1133                     while (mylen > sizeof(rsvp_object)) {
1134                         ip = pntohl(pd+offset2);
1135                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 4, 
1136                                             "IPv4 Address: %s",
1137                                             ip_to_str((guint8 *) &ip));
1138                         offset2 += 4;
1139                         mylen -= 4;
1140                     }
1141                     break;
1142                 }
1143
1144                 case 2: {
1145                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1146                                         "C-type: 2 - IPv6");
1147                     while (mylen>sizeof(rsvp_object)) {
1148                         ip6a = (struct e_in6_addr *)pd+offset2;
1149                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 16, 
1150                                             "IPv6 Address: %s",
1151                                             ip6_to_str(ip6a));
1152                         offset2 += 16;
1153                         mylen -= 16;
1154                     }
1155                     break;
1156                 }
1157                 
1158                 default: {
1159                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1160                                         "C-type: Unknown (%u)",
1161                                         obj->type);
1162                     i = obj_length - sizeof(rsvp_object);
1163                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1164                                         "Data (%d bytes)", i);
1165                 }
1166                 }
1167                 break;
1168                 
1169             case RSVP_CLASS_STYLE : 
1170                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_style);
1171                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1172                                     obj_length);
1173                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1174                                     "Class number: %u - %s", 
1175                                     obj->class, object_type);
1176                 switch(obj->type) {
1177                 case 1: {
1178                     unsigned long ip = pntohl(pd+offset2);
1179                     char *style_str = match_strval(ip, style_vals);
1180                     if (!style_str) style_str = "Unknown";
1181                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1182                                         "C-type: 1");
1183                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+5, 1,
1184                                         "Style: %lu - %s", ip, style_str);
1185                     break;
1186                 }
1187
1188                 default: {
1189                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1190                                         "C-type: Unknown (%u)",
1191                                         obj->type);
1192                     i = obj_length - sizeof(rsvp_object);
1193                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1194                                         "Data (%d bytes)", i);
1195                     break;
1196                 }
1197                 }
1198                 break;
1199             
1200             case RSVP_CLASS_CONFIRM :           
1201                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_confirm);
1202                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1203                                     obj_length);
1204                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1205                                     "Class number: %u - %s", 
1206                                     obj->class, object_type);
1207                 switch(obj->type) {
1208                 case 1: {
1209                     rsvp_confirm_ipv4 *confirm = (rsvp_confirm_ipv4 *)obj;
1210                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1211                                         "C-type: 1 - IPv4");
1212                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 4, 
1213                                         "Receiver address: %s", 
1214                                         ip_to_str((guint8 *) &(confirm->receiver)));
1215                     break;
1216                 }
1217
1218                 case 2: {
1219                     rsvp_confirm_ipv6 *confirm = (rsvp_confirm_ipv6 *)obj;
1220                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1221                                         "C-type: 2 - IPv6");
1222                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 16, 
1223                                         "Receiver address: %s", 
1224                                         ip6_to_str(&(confirm->receiver)));
1225                     break;
1226                 }
1227
1228                 default: {
1229                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1230                                         "C-type: Unknown (%u)",
1231                                         obj->type);
1232                     i = obj_length - sizeof(rsvp_object);
1233                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1234                                         "Data (%d bytes)", i);
1235                 }
1236                 }
1237                 break;
1238
1239             case RSVP_CLASS_SENDER_TEMPLATE :
1240                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_sender_template);
1241                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1242                                     obj_length);
1243                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1244                                     "Class number: %u - %s", 
1245                                     obj->class, object_type);
1246                 goto common_template;
1247             case RSVP_CLASS_FILTER_SPEC :
1248                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_filter_spec);
1249                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1250                                     obj_length);
1251                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1252                                     "Class number: %u - %s", 
1253                                     obj->class, object_type);
1254             common_template:
1255                 switch(obj->type) {
1256                 case 1: {
1257                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1258                                         "C-type: 1 - IPv4");
1259                     memcpy(&ip_addr, pd+offset2, 4);
1260                     proto_tree_add_ipv4(rsvp_object_tree, rsvp_filter[RSVPF_SENDER_IP], NullTVB, 
1261                                         offset2, 4, ip_addr);
1262
1263                     proto_tree_add_uint(rsvp_object_tree, rsvp_filter[RSVPF_SENDER_PORT], NullTVB, 
1264                                         offset2+6, 2, pntohs(pd+offset2+6));
1265                     break;
1266                 }
1267
1268                 case 2: {
1269                     rsvp_template_ipv6 *tem = (rsvp_template_ipv6 *)obj;
1270                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1271                                         "C-type: 2 - IPv6");
1272                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 16, 
1273                                         "Source address: %s", 
1274                                         ip6_to_str(&(tem->source)));
1275                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+18, 2,
1276                                         "Source port: %u", pntohs(pd+offset2+18));
1277                     break;
1278                 }
1279                 
1280                 case 7: {
1281                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1282                                         "C-type: 7 - IPv4 LSP");
1283                     memcpy(&ip_addr, pd+offset2, 4);
1284                     proto_tree_add_ipv4(rsvp_object_tree, rsvp_filter[RSVPF_SENDER_IP], NullTVB, 
1285                                         offset2, 4, ip_addr);
1286
1287                     proto_tree_add_uint(rsvp_object_tree, rsvp_filter[RSVPF_SENDER_LSP_ID], NullTVB, 
1288                                         offset2+6, 2, pntohs(pd+offset2+6));
1289                     break;
1290                 }
1291
1292                 default: {
1293                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1294                                         "C-type: Unknown (%u)",
1295                                         obj->type);
1296                     i = obj_length - sizeof(rsvp_object);
1297                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1298                                         "Data (%d bytes)", i);
1299                 }
1300                 }
1301                 break;
1302
1303             case RSVP_CLASS_SENDER_TSPEC : {
1304                 rsvp_tspec *tspec = (rsvp_tspec *)obj;
1305                 IS_tspec *ist;
1306                 QUAL_tspec *qt;
1307                 service_hdr  *sh;
1308                 char *str;
1309
1310                 mylen = obj_length;
1311                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_sender_tspec);
1312                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1313                                     obj_length);
1314                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1315                                     "Class number: %u - %s", 
1316                                     obj->class, object_type);
1317
1318                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1, 
1319                                     "Message format version: %u", 
1320                                     tspec->version>>4);
1321                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2, 
1322                                     "Data length: %u words, not including header", 
1323                                     pntohs(pd+offset2+2));
1324
1325                 mylen -=4;
1326                 offset2 +=4;
1327                 while (mylen > 4) {
1328                     sh = (service_hdr *)(pd+offset2);
1329                     str = match_strval(sh->service_num, qos_vals);
1330                     if (!str) str = "Unknown";
1331
1332                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1, 
1333                                         "Service header: %u - %s", 
1334                                         sh->service_num, str);
1335                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2, 
1336                                         "Length of service %u data: %u words, " 
1337                                         "not including header", 
1338                                         sh->service_num,
1339                                         ntohs(sh->length));
1340
1341                     offset2+=4; mylen -=4; 
1342
1343                     switch(sh->service_num) {
1344                         
1345                     case QOS_TSPEC :
1346                         ist = (IS_tspec *)sh;
1347
1348                         /* Token bucket TSPEC */
1349                         str = match_strval(ist->param_id, svc_vals);
1350                         if (!str) str = "Unknown";
1351                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1, 
1352                                             "Parameter %u - %s", 
1353                                             ist->param_id, str);
1354                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+1, 1, 
1355                                             "Parameter %u flags: %x", 
1356                                             ist->param_id, ist->flags_tspec);
1357                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2, 
1358                                             "Parameter %u data length: %u words, " 
1359                                             "not including header",
1360                                             ist->param_id,
1361                                             /* pntohs(pd+offset2+10)); */
1362                                             ntohs(ist->parameter_length));
1363                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+4, 4, 
1364                                             "Token bucket rate: %ld", 
1365                                             pieee_to_long(pd+offset2+4));
1366                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+8, 4, 
1367                                             "Token bucket size: %ld", 
1368                                             pieee_to_long(pd+offset2+8));
1369                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+12, 4, 
1370                                             "Peak data rate: %ld", 
1371                                             pieee_to_long(pd+offset2+12));
1372                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+16, 4, 
1373                                             "Minimum policed unit: %u", 
1374                                             pntohl(pd+offset2+16));
1375                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+20, 4, 
1376                                             "Maximum policed unit: %u", 
1377                                             pntohl(pd+offset2+20));
1378
1379                         break;
1380
1381                     case QOS_QUALITATIVE :
1382                         qt = (QUAL_tspec *)sh;
1383
1384                         /* Token bucket TSPEC */
1385                         str = match_strval(qt->param_id, svc_vals);
1386                         if (!str) str = "Unknown";
1387                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1, 
1388                                             "Parameter %u - %s", 
1389                                             qt->param_id, str);
1390                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+1, 1, 
1391                                             "Parameter %u flags: %x", 
1392                                             qt->param_id, qt->flags_tspec);
1393                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2, 
1394                                             "Parameter %u data length: %u words, " 
1395                                             "not including header",
1396                                             qt->param_id,
1397                                             /* pntohs(pd+offset2+10)); */
1398                                             ntohs(qt->parameter_length));
1399                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+4, 4, 
1400                                             "Maximum policed unit: %u", 
1401                                             pntohl(pd+offset2+4));
1402
1403                         break;
1404
1405                     }
1406                     offset2 += ntohs(sh->length)*4; 
1407                     mylen -= ntohs(sh->length)*4;
1408                 }
1409                     
1410                 break;
1411             }
1412
1413             case RSVP_CLASS_FLOWSPEC : {
1414                 rsvp_flowspec *flowspec = (rsvp_flowspec *)obj;
1415                 IS_flowspec *isf;
1416                 QUAL_flowspec *qf;
1417                 service_hdr *sh;
1418                 int mylen;
1419
1420                 char *str;
1421
1422                 mylen = obj_length;
1423                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_flowspec);
1424                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1425                                     obj_length);
1426                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1427                                     "Class number: %u - %s", 
1428                                     obj->class, object_type);
1429
1430                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1, 
1431                                     "Message format version: %u", 
1432                                     flowspec->version>>4);
1433                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2, 
1434                                     "Data length: %u words, not including header", 
1435                                     pntohs(pd+offset2+2));
1436
1437                 mylen -=4;
1438                 offset2+=4;
1439                 while (mylen > 4) {
1440                     sh = (service_hdr *)(pd+offset2);
1441                     str = match_strval(sh->service_num, intsrv_services_str);
1442                     if (!str) str = "Unknown";
1443
1444                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1, 
1445                                         "Service header: %u - %s", 
1446                                         sh->service_num, str);
1447                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2, 
1448                                         "Length of service %u data: %u words, " 
1449                                         "not including header", 
1450                                         sh->service_num,
1451                                         ntohs(sh->length));
1452
1453                     offset2+=4; mylen -=4; 
1454
1455                     switch(sh->service_num) {
1456
1457                     case QOS_CONTROLLED_LOAD :
1458                     case QOS_GUARANTEED :
1459                         /* Treat both these the same for now */
1460                         isf = (IS_flowspec *)sh;
1461
1462                         str = match_strval(isf->tspec.param_id, svc_vals);
1463                         if (!str) str = "Unknown";
1464                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1, 
1465                                             "Parameter %u - %s", 
1466                                             isf->tspec.param_id, str);
1467                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+1, 1, 
1468                                             "Parameter %u flags: %x", 
1469                                             isf->tspec.param_id, isf->tspec.flags_tspec);
1470                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2, 
1471                                             "Parameter %u data length: %u words, " 
1472                                             "not including header",
1473                                             isf->tspec.param_id,
1474                                             ntohs(isf->tspec.parameter_length));
1475                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+4, 4, 
1476                                             "Token bucket rate: %ld", 
1477                                             pieee_to_long(pd+offset2+4));
1478                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+8, 4, 
1479                                             "Token bucket size: %ld", 
1480                                             pieee_to_long(pd+offset2+8));
1481                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+12, 4, 
1482                                             "Peak data rate: %ld", 
1483                                             pieee_to_long(pd+offset2+12));
1484                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+16, 4, 
1485                                             "Minimum policed unit: %u", 
1486                                             pntohl(pd+offset2+16));
1487                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+20, 4, 
1488                                             "Maximum policed unit: %u", 
1489                                             pntohl(pd+offset2+20));
1490                         if (sh->service_num!=QOS_GUARANTEED)
1491                             break;
1492                         
1493                         /* Guaranteed-rate RSpec */
1494                         str = match_strval(isf->rspec.param_id, svc_vals);
1495                         if (!str) str="Unknown";
1496                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+24, 1, 
1497                                             "Parameter %u - %s", 
1498                                             isf->rspec.param_id, str);
1499                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+25, 1, 
1500                                             "Parameter %u flags: %x", 
1501                                             isf->rspec.param_id, isf->rspec.flags_rspec);
1502                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+26, 2, 
1503                                             "Parameter %u data length: %u words, " 
1504                                             "not including header",
1505                                             isf->rspec.param_id,
1506                                             ntohs(isf->rspec.param2_length));
1507
1508                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+28, 4, 
1509                                             "Rate: %ld", 
1510                                             pieee_to_long(pd+offset2+28));
1511                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+32, 4, 
1512                                             "Slack term: %u", 
1513                                             pntohl(pd+offset2+32));
1514                         break;
1515
1516                     case QOS_QUALITATIVE :
1517                         qf = (QUAL_flowspec *)sh;
1518
1519                         str = match_strval(qf->param_id, svc_vals);
1520                         if (!str) str = "Unknown";
1521                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1, 
1522                                             "Parameter %u - %s", 
1523                                             qf->param_id, str);
1524                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+1, 1, 
1525                                             "Parameter %u flags: %x", 
1526                                             qf->param_id, qf->flags_tspec);
1527                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2, 
1528                                             "Parameter %u data length: %u words, " 
1529                                             "not including header",
1530                                             qf->param_id,
1531                                             ntohs(qf->parameter_length));
1532                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+4, 4, 
1533                                             "Maximum policed unit: %u", 
1534                                             pntohl(pd+offset2+4));
1535                         
1536                         break;
1537                     }
1538                     offset2 += ntohs(sh->length)*4;
1539                     mylen -= ntohs(sh->length)*4;
1540                 }
1541
1542                 break;
1543             }
1544
1545             case RSVP_CLASS_ADSPEC : {
1546                 proto_tree *adspec_tree;
1547                 service_hdr *shdr;
1548                 param_hdr *phdr; 
1549
1550                 char *str;
1551
1552                 mylen = obj_length;
1553                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_adspec);
1554                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1555                                     obj_length);
1556                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1557                                     "Class number: %u - %s", 
1558                                     obj->class, object_type);
1559                 
1560                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1, 
1561                                     "Message format version: %u", 
1562                                     (*((unsigned char *)pd+offset2))>>4);
1563                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2, 
1564                                     "Data length: %u words, not including header", 
1565                                     pntohs(pd+offset2+2));
1566                 offset2+=4;
1567                 mylen -= 4;
1568                 while (mylen > 4) {
1569                     shdr = (service_hdr *)(pd + offset2);
1570                     str = match_strval(shdr->service_num, intsrv_services_str);
1571
1572                     ti = proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 
1573                                              (pntohs(&shdr->length)+1)<<2,
1574                                              str?str:"Unknown");
1575                     adspec_tree = proto_item_add_subtree(ti,
1576                                                          ett_rsvp_adspec_subtree);
1577                     proto_tree_add_text(adspec_tree, NullTVB, offset2, 1,
1578                                         "Service header %u - %s",
1579                                         shdr->service_num, str);
1580                     proto_tree_add_text(adspec_tree, NullTVB, offset2+1, 1,
1581                                         (shdr->break_bit&0x80)?
1582                                         "Break bit set":"Break bit not set");
1583                     proto_tree_add_text(adspec_tree, NullTVB, offset2+2, 2, 
1584                                         "Data length: %u words, not including header", 
1585                                         pntohs(&shdr->length));
1586                     offset2+=4; i=(pntohs(&shdr->length)+1)<<2; mylen-=4;
1587                     while (i>4) {
1588                         phdr = (param_hdr *)(pd + offset2);
1589                         str = match_strval(phdr->id, adspec_params);
1590                         if (str) {
1591                             switch(phdr->id) {
1592                             case 4:
1593                             case 8:
1594                             case 10:
1595                             case 133:
1596                             case 134:
1597                             case 135:
1598                             case 136:
1599                                 /* 32-bit unsigned integer */
1600                                 proto_tree_add_text(adspec_tree, NullTVB, offset2, 
1601                                                     (pntohs(&phdr->length)+1)<<2,
1602                                                     "%s - %lu (type %u, length %u)",
1603                                                     str, 
1604                                                     (unsigned long)pntohl(&phdr->dataval), 
1605                                                     phdr->id, pntohs(&phdr->length));
1606                                 break;
1607                                 
1608                             case 6:
1609                                 /* IEEE float */
1610                                 proto_tree_add_text(adspec_tree, NullTVB, offset2, 
1611                                                     (pntohs(&phdr->length)+1)<<2,
1612                                                     "%s - %lu (type %u, length %u)",
1613                                                     str, 
1614                                                     pieee_to_long(&phdr->dataval), 
1615                                                     phdr->id, pntohs(&phdr->length));
1616                                 break;
1617                             default: 
1618                                 proto_tree_add_text(adspec_tree, NullTVB, offset2, 
1619                                                     (pntohs(&phdr->length)+1)<<2,
1620                                                     "%s (type %u, length %u)",
1621                                                     str, 
1622                                                     phdr->id, pntohs(&phdr->length));
1623                             }
1624                         } else {
1625                             proto_tree_add_text(adspec_tree, NullTVB, offset2, 
1626                                                 (pntohs(&phdr->length)+1)<<2,
1627                                                 "Unknown (type %u, length %u)",
1628                                                 phdr->id, pntohs(&phdr->length));
1629                         }
1630                         offset2+=(pntohs(&phdr->length)+1)<<2;
1631                         i-=(pntohs(&phdr->length)+1)<<2;
1632                         mylen-=(pntohs(&phdr->length)+1)<<2;
1633                     }
1634                 }
1635                 break;
1636             }
1637
1638             case RSVP_CLASS_INTEGRITY :
1639                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_integrity);
1640                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1641                                     obj_length);
1642                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1643                                     "Class number: %u - %s", 
1644                                     obj->class, object_type);
1645                 goto default_class;
1646
1647             case RSVP_CLASS_POLICY :
1648                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_policy);
1649                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1650                                     obj_length);
1651                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1652                                     "Class number: %u - %s", 
1653                                     obj->class, object_type);
1654                 goto default_class;
1655
1656             case RSVP_CLASS_LABEL_REQUEST : 
1657                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_label_request);
1658                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1659                                     obj_length);
1660                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1661                                     "Class number: %d - %s", 
1662                                     obj->class, object_type);
1663                 switch(obj->type) {
1664                 case 1: {
1665                     unsigned short l3pid = pntohs(pd+offset2+2);
1666                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1667                                         "C-type: 1");
1668                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2,
1669                                         "L3PID: 0x%04x", l3pid);
1670                     break;
1671                 }
1672
1673                 default: {
1674                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1675                                         "C-type: Unknown (%d)",
1676                                         obj->type);
1677                     i = obj_length - sizeof(rsvp_object);
1678                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1679                                         "Data (%d bytes)", i);
1680                     break;
1681                 }
1682                 }
1683                 break;
1684             
1685             case RSVP_CLASS_LABEL : 
1686                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_label);
1687                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1688                                     obj_length);
1689                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1690                                     "Class number: %d - %s", 
1691                                     obj->class, object_type);
1692                 switch(obj->type) {
1693                 case 1: {
1694                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1695                                         "C-type: 1");
1696                     for (i=1, l = 0; l < obj_length - 4; l+=4, i++)
1697                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+l, 4, 
1698                                             "Label %d: %d %s", 
1699                                             i, pntohl(pd+offset2+l), 
1700                                             l == obj_length - 8 ? 
1701                                             "(Top label)" : "");
1702                     break;
1703                 }
1704
1705                 default: {
1706                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1707                                         "C-type: Unknown (%d)",
1708                                         obj->type);
1709                     i = obj_length - sizeof(rsvp_object);
1710                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1711                                         "Data (%d bytes)", i);
1712                     break;
1713                 }
1714                 }
1715                 break;
1716             
1717             case RSVP_CLASS_SESSION_ATTRIBUTE : 
1718                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_session_attribute);
1719                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1720                                     obj_length);
1721                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1722                                     "Class number: %d - %s", 
1723                                     obj->class, object_type);
1724                 switch(obj->type) {
1725                 case 7: {
1726                     char s_name[64];
1727                     session_attribute *s_attr = (session_attribute *)&pd[offset];
1728                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1729                                         "C-type: 7 - IPv4 LSP");
1730                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1,
1731                                         "Setup priority: %d", s_attr->setup_prio);
1732                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+1, 1,
1733                                         "Hold priority: %d", s_attr->hold_prio);
1734                     ti2 = proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 1,
1735                                               "Flags: %0x", s_attr->flags);
1736                     rsvp_sa_flags_tree = proto_item_add_subtree(ti2, 
1737                                                                 ett_rsvp_session_attribute_flags);
1738                     proto_tree_add_text(rsvp_sa_flags_tree, NullTVB, offset2+2, 1, 
1739                                         ".......%d: Local protection: %s", 
1740                                         s_attr->flags & 0x1 ? 1 : 0,
1741                                         s_attr->flags & 0x1 ? "Set" : "Not set");
1742                     proto_tree_add_text(rsvp_sa_flags_tree, NullTVB, offset2+2, 1, 
1743                                         "......%d.: Merging permitted: %s", 
1744                                         s_attr->flags & 0x2 ? 1 : 0,
1745                                         s_attr->flags & 0x2 ? "Set" : "Not set");
1746                     proto_tree_add_text(rsvp_sa_flags_tree, NullTVB, offset2+2, 1, 
1747                                         ".....%d..: Ingress note may reroute: %s", 
1748                                         s_attr->flags & 0x4 ? 1 : 0,
1749                                         s_attr->flags & 0x4 ? "Set" : "Not set");
1750                     
1751                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+3, 1,
1752                                         "Name length: %d", s_attr->name_len);
1753                     memset(s_name, 0, 64);
1754                     strncpy(s_name, &pd[offset2+4], 60);
1755                     if (s_attr->name_len>60) sprintf(&(s_name[60]), "...");
1756                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+4, s_attr->name_len,
1757                                         "Name: %s", s_name);
1758                     break;
1759                 }
1760
1761                 default: {
1762                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1763                                         "C-type: Unknown (%d)",
1764                                         obj->type);
1765                     i = obj_length - sizeof(rsvp_object);
1766                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1767                                         "Data (%d bytes)", i);
1768                     break;
1769                 }
1770                 }
1771                 break;
1772
1773             case RSVP_CLASS_EXPLICIT_ROUTE : 
1774                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_explicit_route);
1775                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1776                                     obj_length);
1777                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1778                                     "Class number: %d - %s", 
1779                                     obj->class, object_type);
1780                 switch(obj->type) {
1781                 case 1: {
1782                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1783                                         "C-type: 1");
1784                     for (i=1, l = 0; l < obj_length - 4; i++) {
1785                         j = ((unsigned char)pd[offset2+l]) & 0x7f;
1786                         switch(j) {
1787                         case 1: /* IPv4 */
1788                             k = ((unsigned char)pd[offset2+l]) & 0x80;
1789                             ti2 = proto_tree_add_text(rsvp_object_tree, NullTVB, 
1790                                                       offset2+l, 8,
1791                                                       "IPv4 Subobject - %s, %s",
1792                                                       ip_to_str(&pd[offset2+l+2]), 
1793                                                       k ? "Loose" : "Strict");
1794                             rsvp_ero_subtree = 
1795                                 proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); 
1796                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1797                                                 k ? "Loose Hop " : "Strict Hop");
1798                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1799                                                 "Type: 1 (IPv4)");
1800                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+1, 1, 
1801                                                 "Length: %d", pd[offset2+l+1]);
1802                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+2, 4, 
1803                                                 "IPv4 hop: %s", ip_to_str(&pd[offset2+l+2]));
1804                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+6, 1, 
1805                                                 "Prefix length: %d", pd[offset2+l+6]);
1806                             break;
1807
1808                         case 2: /* IPv6 */
1809                             ti2 = proto_tree_add_text(rsvp_object_tree, NullTVB, 
1810                                                       offset2+l, 20,
1811                                                       "IPv6 Subobject");
1812                             rsvp_ero_subtree = 
1813                                 proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); 
1814                             k = ((unsigned char)pd[offset2+l]) & 0x80;
1815                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1816                                                 k ? "Loose Hop " : "Strict Hop");
1817                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1818                                                 "Type: 2 (IPv6)");
1819                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+1, 1, 
1820                                                 "Length: %d", pd[offset2+l+1]);
1821                             ip6a = (struct e_in6_addr *)pd+offset2+l+2;
1822                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+2, 16, 
1823                                                 "IPv6 hop: %s", ip6_to_str(ip6a));
1824                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+18, 1, 
1825                                                 "Prefix length: %d", pd[offset2+l+6]);
1826                             break;
1827
1828                         case 32: /* AS */
1829                             k = pntohs(offset2+l+2);
1830                             ti2 = proto_tree_add_text(rsvp_object_tree, NullTVB, 
1831                                                       offset2+l, 4,
1832                                                       "Autonomous System %d", k);
1833                             rsvp_ero_subtree = 
1834                                 proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); 
1835                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1836                                                 k ? "Loose Hop " : "Strict Hop");
1837                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1838                                                 "Type: 32 (Autonomous System Number)");
1839                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+1, 1, 
1840                                                 "Length: %d", pd[offset2+l+1]);
1841                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+2, 2, 
1842                                                 "Autonomous System %d", k);
1843                             break;
1844
1845                         case 64: /* Path Term */
1846                             k = ((unsigned char)pd[offset2+l]) & 0x80;
1847                             ti2 = proto_tree_add_text(rsvp_object_tree, NullTVB, 
1848                                                       offset2+l, 4,
1849                                                       "LSP Path Termination");
1850                             rsvp_ero_subtree = 
1851                                 proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); 
1852                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1853                                                 k ? "Loose Hop " : "Strict Hop");
1854                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1855                                                 "Type: 64 (MPLS LSP Path Termination)");
1856                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+1, 1, 
1857                                                 "Length: %d", pd[offset2+l+1]);
1858                             break;
1859
1860                         default: /* Unknown subobject */
1861                             k = ((unsigned char)pd[offset2+l]) & 0x80;
1862                             ti2 = proto_tree_add_text(rsvp_object_tree, NullTVB, 
1863                                                       offset2+l, pd[offset2+l+1],
1864                                                       "Unknown subobject: %d", j);
1865                             rsvp_ero_subtree = 
1866                                 proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); 
1867                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1868                                                 k ? "Loose Hop " : "Strict Hop");
1869                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1870                                                 "Type: %d (Unknown)", j);
1871                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+1, 1, 
1872                                                 "Length: %d", pd[offset2+l+1]);
1873
1874                         }
1875
1876                         l += ((unsigned char)pd[offset2+l+1]);
1877                     }
1878                     break;
1879                 }
1880                 default: {
1881                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1882                                         "C-type: Unknown (%d)",
1883                                         obj->type);
1884                     i = obj_length - sizeof(rsvp_object);
1885                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1886                                         "Data (%d bytes)", i);
1887                     break;
1888                 }
1889                 }
1890                 break;
1891             
1892
1893             case RSVP_CLASS_RECORD_ROUTE : 
1894                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_record_route);
1895                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1896                                     obj_length);
1897                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1898                                     "Class number: %d - %s", 
1899                                     obj->class, object_type);
1900                 switch(obj->type) {
1901                 case 1: {
1902                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1903                                         "C-type: 1");
1904                     for (i=1, l = 0; l < obj_length - 4; i++) {
1905                         j = (unsigned char)pd[offset2+l];
1906                         switch(j) {
1907                         case 1: /* IPv4 */
1908                             ti2 = proto_tree_add_text(rsvp_object_tree, NullTVB, 
1909                                                       offset2+l, 8,
1910                                                       "IPv4 Subobject - %s",
1911                                                       ip_to_str(&pd[offset2+l+2]));
1912                             rsvp_ero_subtree = 
1913                                 proto_item_add_subtree(ti2, ett_rsvp_record_route_subobj); 
1914                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1915                                                 "Type: 1 (IPv4)");
1916                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+1, 1, 
1917                                                 "Length: %d", pd[offset2+l+1]);
1918                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+2, 4, 
1919                                                 "IPv4 hop: %s", ip_to_str(&pd[offset2+l+2]));
1920                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+6, 1, 
1921                                                 "Prefix length: %d", pd[offset2+l+6]);
1922                             break;
1923
1924                         case 2: /* IPv6 */
1925                             ti2 = proto_tree_add_text(rsvp_object_tree, NullTVB, 
1926                                                       offset2+l, 20,
1927                                                       "IPv6 Subobject");
1928                             rsvp_ero_subtree = 
1929                                 proto_item_add_subtree(ti2, ett_rsvp_record_route_subobj); 
1930                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1931                                                 "Type: 2 (IPv6)");
1932                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+1, 1, 
1933                                                 "Length: %d", pd[offset2+l+1]);
1934                             ip6a = (struct e_in6_addr *)pd+offset2+l+2;
1935                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+2, 16, 
1936                                                 "IPv6 hop: %s", ip6_to_str(ip6a));
1937                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+18, 1, 
1938                                                 "Prefix length: %d", pd[offset2+l+6]);
1939                             break;
1940
1941                         default: /* Unknown subobject */
1942                             k = ((unsigned char)pd[offset2+l]) & 0x80;
1943                             ti2 = proto_tree_add_text(rsvp_object_tree, NullTVB, 
1944                                                       offset2+l, pd[offset2+l+1],
1945                                                       "Unknown subobject: %d", j);
1946                             rsvp_ero_subtree = 
1947                                 proto_item_add_subtree(ti2, ett_rsvp_record_route_subobj); 
1948                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1949                                                 k ? "Loose Hop " : "Strict Hop");
1950                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1951                                                 "Type: %d (Unknown)", j);
1952                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+1, 1, 
1953                                                 "Length: %d", pd[offset2+l+1]);
1954
1955                         }
1956
1957                         l += ((unsigned char)pd[offset2+l+1]);
1958                     }
1959                     break;
1960                 }
1961                 
1962                 default: {
1963                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1964                                         "C-type: Unknown (%d)",
1965                                         obj->type);
1966                     i = obj_length - sizeof(rsvp_object);
1967                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1968                                         "Data (%d bytes)", i);
1969                     break;
1970                 }
1971                 }
1972                 break;
1973             
1974             default :
1975                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_unknown_class);
1976                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1977                                     obj_length);
1978                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1979                                     "Class number: %u - %s", 
1980                                     obj->class, object_type);
1981             default_class:
1982                 i = obj_length - sizeof(rsvp_object);
1983                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1984                                     "Data (%d bytes)", i);
1985                 break;
1986
1987             case RSVP_CLASS_NULL :
1988                 break;
1989
1990             }  
1991             
1992             offset += obj_length;
1993             len += obj_length;
1994         }
1995     }
1996 }
1997
1998 void
1999 proto_register_rsvp(void)
2000 {
2001         static gint *ett[] = {
2002                 &ett_rsvp,
2003                 &ett_rsvp_hdr,
2004                 &ett_rsvp_session,
2005                 &ett_rsvp_hop,
2006                 &ett_rsvp_time_values,
2007                 &ett_rsvp_error,
2008                 &ett_rsvp_scope,
2009                 &ett_rsvp_style,
2010                 &ett_rsvp_confirm,
2011                 &ett_rsvp_sender_template,
2012                 &ett_rsvp_filter_spec,
2013                 &ett_rsvp_sender_tspec,
2014                 &ett_rsvp_flowspec,
2015                 &ett_rsvp_adspec,
2016                 &ett_rsvp_adspec_subtree,
2017                 &ett_rsvp_integrity,
2018                 &ett_rsvp_policy,
2019                 &ett_rsvp_label,
2020                 &ett_rsvp_label_request,
2021                 &ett_rsvp_session_attribute,
2022                 &ett_rsvp_session_attribute_flags,
2023                 &ett_rsvp_explicit_route,
2024                 &ett_rsvp_explicit_route_subobj,
2025                 &ett_rsvp_record_route,
2026                 &ett_rsvp_record_route_subobj,
2027                 &ett_rsvp_unknown_class,
2028         };
2029
2030         proto_rsvp = proto_register_protocol("Resource ReserVation Protocol (RSVP)", "rsvp");
2031         proto_register_field_array(proto_rsvp, rsvpf_info, array_length(rsvpf_info));
2032         proto_register_subtree_array(ett, array_length(ett));
2033 }
2034
2035 void
2036 proto_reg_handoff_rsvp(void)
2037 {
2038         old_dissector_add("ip.proto", IP_PROTO_RSVP, dissect_rsvp);
2039 }