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