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