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