Fix up the "ethereal-dev" address to refer to "ethereal.com" rather than
[obnox/wireshark/wip.git] / packet-rsvp.c
1 /* packet-rsvp.c
2  * Routines for RSVP packet disassembly
3  *
4  * (c) Copyright Ashok Narayanan <ashokn@cisco.com>
5  *
6  * $Id: packet-rsvp.c,v 1.31 2001/01/09 06:31:41 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 *packet_type, *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     OLD_CHECK_DISPLAY_AS_DATA(proto_rsvp, pd, offset, fd, tree);
859
860     hdr = (rsvp_header *)&pd[offset];
861     packet_type = match_strval(hdr->message_type, message_type_vals);
862     if (check_col(fd, COL_PROTOCOL))
863         col_set_str(fd, COL_PROTOCOL, "RSVP");
864     if (check_col(fd, COL_INFO)) {
865         if (packet_type != NULL)
866             col_add_str(fd, COL_INFO, packet_type); 
867         else
868             col_add_fstr(fd, COL_INFO, "Unknown (%u)", hdr->message_type); 
869     }
870
871     if (tree) {
872         msg_length = pntohs(pd+offset+6);
873         ti = proto_tree_add_item(tree, proto_rsvp, NullTVB, offset, msg_length, FALSE);
874         rsvp_tree = proto_item_add_subtree(ti, ett_rsvp);
875
876         ti = proto_tree_add_text(rsvp_tree, NullTVB, offset, 
877                                  sizeof(rsvp_header), "RSVP Header"); 
878         rsvp_header_tree = proto_item_add_subtree(ti, ett_rsvp_hdr);
879
880         proto_tree_add_text(rsvp_header_tree, NullTVB, offset, 1, "RSVP Version: %u", 
881                             (hdr->ver_flags & 0xf0)>>4);  
882         proto_tree_add_text(rsvp_header_tree, NullTVB, offset, 1, "Flags: %02X",
883                             hdr->ver_flags & 0xf);  
884         proto_tree_add_uint(rsvp_header_tree, rsvp_filter[RSVPF_MSG], NullTVB, 
885                             offset+1, 1, hdr->message_type);
886         if (hdr->message_type <= RSVPF_RTEARCONFIRM &&
887                         hdr->message_type != RSVPF_JUNK_MSG8 &&
888                         hdr->message_type != RSVPF_JUNK_MSG9 ) {
889                proto_tree_add_boolean_hidden(rsvp_header_tree, rsvp_filter[RSVPF_MSG + hdr->message_type], NullTVB, 
890                                    offset+1, 1, 1);
891         }
892         proto_tree_add_text(rsvp_header_tree, NullTVB, offset + 2 , 2, "Message Checksum");
893         proto_tree_add_text(rsvp_header_tree, NullTVB, offset + 4 , 1, "Sending TTL: %u",
894                             hdr->sending_ttl);
895         proto_tree_add_text(rsvp_header_tree, NullTVB, offset + 6 , 2, "Message length: %d",
896                             msg_length);
897
898         offset += sizeof(rsvp_header);
899         len = 0;
900         while (len + sizeof(rsvp_header) < msg_length) {
901             obj = (rsvp_object *)&pd[offset];
902             obj_length = pntohs(pd+offset);
903             if (!BYTES_ARE_IN_FRAME(offset, obj_length)) {
904                 proto_tree_add_text(rsvp_tree, NullTVB, offset, 1, 
905                                     "Further data not captured");
906                 break;
907             }
908             
909             object_type = match_strval(obj->class, rsvp_class_vals);
910             if (!object_type) object_type = "Unknown";
911             ti = proto_tree_add_uint_hidden(rsvp_tree, rsvp_filter[RSVPF_OBJECT], NullTVB, 
912                                             offset, obj_length, obj->class);
913             ti = proto_tree_add_uint(rsvp_tree, rsvp_filter[rsvp_class_to_filter_num(obj->class)], NullTVB, 
914                                      offset, obj_length, obj->class);
915
916             offset2 = offset + sizeof(rsvp_object);
917
918             switch(obj->class) {
919
920             case RSVP_CLASS_SESSION :           
921                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_session);
922                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
923                                     obj_length);
924                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
925                                     "Class number: %u - %s", 
926                                     obj->class, object_type);
927                 switch(obj->type) {
928                 case 1: {
929                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
930                                         "C-type: 1 - IPv4");
931                     memcpy(&ip_addr, pd+offset2, 4);
932                     proto_tree_add_ipv4(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_IP], NullTVB, 
933                                         offset2, 4, ip_addr);
934
935                     proto_tree_add_uint(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_PROTO], NullTVB, 
936                                         offset2+4, 1, *(pd+offset2+4));
937                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+5, 1,
938                                         "Flags: %x", pntohs(pd+offset2+5));
939                     proto_tree_add_uint(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_PORT], NullTVB, 
940                                         offset2+6, 2, pntohs(pd+offset2+6));
941                     break;
942                 }
943
944                 case 2: {
945                     rsvp_session_ipv6 *sess = (rsvp_session_ipv6 *)obj;
946                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
947                                         "C-type: 2 - IPv6");
948                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 4, 
949                                         "Destination address: %s", 
950                                         ip6_to_str(&(sess->destination)));
951                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+16, 1,
952                                         "Protocol: %u", sess->protocol);
953                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+17, 1,
954                                         "Flags: %x", sess->flags);
955                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+18, 2,
956                                         "Destination port: %u", 
957                                         pntohs(pd+offset2+18));
958                     break;
959                 }
960                 
961                 case 7: {
962                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
963                                         "C-type: 7 - IPv4 LSP");
964                     memcpy(&ip_addr, pd+offset2, 4);
965                     proto_tree_add_ipv4(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_IP], NullTVB, 
966                                         offset2, 4, ip_addr);
967
968                     proto_tree_add_uint(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_TUNNEL_ID], NullTVB, 
969                                         offset2+6, 2, pntohs(pd+offset2+6));
970
971                     memcpy(&ip_addr, pd+offset2+8, 4);
972                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+8, 4, 
973                                         "Extended Tunnel ID: %lu (%s)", 
974                                         (unsigned long)ntohl(ip_addr),
975                                         ip_to_str(pd+offset2+8));
976                     proto_tree_add_uint_hidden(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_EXT_TUNNEL_ID], NullTVB, 
977                                         offset2+8, 4, ip_addr);
978                     break;
979                 }
980
981                 default: {
982                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
983                                         "C-type: Unknown (%u)",
984                                         obj->type);
985                     i = obj_length - sizeof(rsvp_object);
986                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
987                                         "Data (%d bytes)", i);
988                 }
989                 }
990                 break;
991                 
992             case RSVP_CLASS_HOP :               
993                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_hop);
994                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
995                                     obj_length);
996                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
997                                     "Class number: %u - %s", 
998                                     obj->class, object_type);
999                 switch(obj->type) {
1000                 case 1: {
1001                     rsvp_hop_ipv4 *hop = (rsvp_hop_ipv4 *)obj;
1002                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1003                                         "C-type: 1 - IPv4");
1004                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 4, 
1005                                         "Neighbor address: %s", 
1006                                         ip_to_str((guint8 *) &(hop->neighbor)));
1007                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+4, 4,
1008                                         "Logical interface: %0x", 
1009                                         pntohl(pd+offset2+4));
1010                     break;
1011                 }
1012
1013                 case 2: {
1014                     rsvp_hop_ipv6 *hop = (rsvp_hop_ipv6 *)obj;
1015                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1016                                         "C-type: 2 - IPv6");
1017                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 4, 
1018                                         "Neighbor address: %s", 
1019                                         ip6_to_str(&(hop->neighbor)));
1020                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+16, 4,
1021                                         "Logical interface: %0x", 
1022                                         pntohl(pd+offset2+16));
1023                     break;
1024                 }
1025                 
1026                 default: {
1027                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1028                                         "C-type: Unknown (%u)",
1029                                         obj->type);
1030                     i = obj_length - sizeof(rsvp_object);
1031                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1032                                         "Data (%d bytes)", i);
1033                 }
1034                 }
1035                 break;
1036                 
1037             case RSVP_CLASS_TIME_VALUES : 
1038                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_time_values);
1039                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1040                                     obj_length);
1041                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1042                                     "Class number: %u - %s", 
1043                                     obj->class, object_type);
1044                 switch(obj->type) {
1045                 case 1: {
1046                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1047                                         "C-type: 1");
1048                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 4, 
1049                                         "Refresh interval: %u ms (%u seconds)",
1050                                         pntohl(pd+offset2),
1051                                         pntohl(pd+offset2)/1000);
1052                     break;
1053                 }
1054
1055                 default: {
1056                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1057                                         "C-type: Unknown (%u)",
1058                                         obj->type);
1059                     i = obj_length - sizeof(rsvp_object);
1060                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1061                                         "Data (%d bytes)", i);
1062                     break;
1063                 }
1064                 }
1065                 break;
1066
1067             case RSVP_CLASS_ERROR :
1068                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_error);
1069                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1070                                     obj_length);
1071                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1072                                     "Class number: %u - %s", 
1073                                     obj->class, object_type);
1074                 switch(obj->type) {
1075                 case 1: {
1076                     rsvp_error_ipv4 *err = (rsvp_error_ipv4 *)obj;
1077                     char *err_str = match_strval(err->error_code, rsvp_error_vals);
1078                     if (!err_str) err_str = "Unknown";
1079
1080                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1081                                         "C-type: 1 - IPv4");
1082                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 4, 
1083                                         "Error node: %s",
1084                                         ip_to_str((guint8 *) &(err->error_node)));
1085                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+4, 1,
1086                                         "Flags: %02x", err->flags);
1087                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+5, 1,
1088                                         "Error code: %u - %s", err->error_code,
1089                                         err_str);
1090                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+6, 2,
1091                                         "Error value: %u", pntohs(pd+offset2+6));
1092                     
1093                     break;
1094                 }
1095
1096                 case 2: {
1097                     rsvp_error_ipv6 *err = (rsvp_error_ipv6 *)obj;
1098                     char *err_str = match_strval(err->error_code, rsvp_error_vals);
1099                     if (!err_str) err_str = "Unknown";
1100                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1101                                         "C-type: 2 - IPv6");
1102                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 4, 
1103                                         "Error node: %s",
1104                                         ip6_to_str(&(err->error_node)));
1105                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+16, 1,
1106                                         "Flags: %02x", err->flags);
1107                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+17, 1,
1108                                         "Error code: %u - %s", err->error_code,
1109                                         err_str);
1110                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+18, 2,
1111                                         "Error value: %u", pntohs(pd+offset2+18));
1112                     
1113                     break;
1114                 }
1115                 
1116                 default: {
1117                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1118                                         "C-type: Unknown (%u)",
1119                                         obj->type);
1120                     i = obj_length - sizeof(rsvp_object);
1121                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1122                                         "Data (%d bytes)", i);
1123                 }
1124                 }
1125                 break;
1126                 
1127
1128             case RSVP_CLASS_SCOPE : 
1129                 mylen = obj_length;
1130                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_scope);
1131                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1132                                     obj_length);
1133                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1134                                     "Class number: %u - %s", 
1135                                     obj->class, object_type);
1136                 switch(obj->type) {
1137                 case 1: {
1138                     unsigned long ip;
1139                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1140                                         "C-type: 1 - IPv4");
1141                     while (mylen > sizeof(rsvp_object)) {
1142                         ip = pntohl(pd+offset2);
1143                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 4, 
1144                                             "IPv4 Address: %s",
1145                                             ip_to_str((guint8 *) &ip));
1146                         offset2 += 4;
1147                         mylen -= 4;
1148                     }
1149                     break;
1150                 }
1151
1152                 case 2: {
1153                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1154                                         "C-type: 2 - IPv6");
1155                     while (mylen>sizeof(rsvp_object)) {
1156                         ip6a = (struct e_in6_addr *)pd+offset2;
1157                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 16, 
1158                                             "IPv6 Address: %s",
1159                                             ip6_to_str(ip6a));
1160                         offset2 += 16;
1161                         mylen -= 16;
1162                     }
1163                     break;
1164                 }
1165                 
1166                 default: {
1167                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1168                                         "C-type: Unknown (%u)",
1169                                         obj->type);
1170                     i = obj_length - sizeof(rsvp_object);
1171                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1172                                         "Data (%d bytes)", i);
1173                 }
1174                 }
1175                 break;
1176                 
1177             case RSVP_CLASS_STYLE : 
1178                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_style);
1179                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1180                                     obj_length);
1181                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1182                                     "Class number: %u - %s", 
1183                                     obj->class, object_type);
1184                 switch(obj->type) {
1185                 case 1: {
1186                     unsigned long ip = pntohl(pd+offset2);
1187                     char *style_str = match_strval(ip, style_vals);
1188                     if (!style_str) style_str = "Unknown";
1189                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1190                                         "C-type: 1");
1191                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+5, 1,
1192                                         "Style: %lu - %s", ip, style_str);
1193                     break;
1194                 }
1195
1196                 default: {
1197                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1198                                         "C-type: Unknown (%u)",
1199                                         obj->type);
1200                     i = obj_length - sizeof(rsvp_object);
1201                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1202                                         "Data (%d bytes)", i);
1203                     break;
1204                 }
1205                 }
1206                 break;
1207             
1208             case RSVP_CLASS_CONFIRM :           
1209                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_confirm);
1210                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1211                                     obj_length);
1212                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1213                                     "Class number: %u - %s", 
1214                                     obj->class, object_type);
1215                 switch(obj->type) {
1216                 case 1: {
1217                     rsvp_confirm_ipv4 *confirm = (rsvp_confirm_ipv4 *)obj;
1218                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1219                                         "C-type: 1 - IPv4");
1220                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 4, 
1221                                         "Receiver address: %s", 
1222                                         ip_to_str((guint8 *) &(confirm->receiver)));
1223                     break;
1224                 }
1225
1226                 case 2: {
1227                     rsvp_confirm_ipv6 *confirm = (rsvp_confirm_ipv6 *)obj;
1228                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1229                                         "C-type: 2 - IPv6");
1230                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 16, 
1231                                         "Receiver address: %s", 
1232                                         ip6_to_str(&(confirm->receiver)));
1233                     break;
1234                 }
1235
1236                 default: {
1237                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1238                                         "C-type: Unknown (%u)",
1239                                         obj->type);
1240                     i = obj_length - sizeof(rsvp_object);
1241                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1242                                         "Data (%d bytes)", i);
1243                 }
1244                 }
1245                 break;
1246
1247             case RSVP_CLASS_SENDER_TEMPLATE :
1248                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_sender_template);
1249                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1250                                     obj_length);
1251                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1252                                     "Class number: %u - %s", 
1253                                     obj->class, object_type);
1254                 goto common_template;
1255             case RSVP_CLASS_FILTER_SPEC :
1256                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_filter_spec);
1257                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1258                                     obj_length);
1259                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1260                                     "Class number: %u - %s", 
1261                                     obj->class, object_type);
1262             common_template:
1263                 switch(obj->type) {
1264                 case 1: {
1265                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1266                                         "C-type: 1 - IPv4");
1267                     memcpy(&ip_addr, pd+offset2, 4);
1268                     proto_tree_add_ipv4(rsvp_object_tree, rsvp_filter[RSVPF_SENDER_IP], NullTVB, 
1269                                         offset2, 4, ip_addr);
1270
1271                     proto_tree_add_uint(rsvp_object_tree, rsvp_filter[RSVPF_SENDER_PORT], NullTVB, 
1272                                         offset2+6, 2, pntohs(pd+offset2+6));
1273                     break;
1274                 }
1275
1276                 case 2: {
1277                     rsvp_template_ipv6 *tem = (rsvp_template_ipv6 *)obj;
1278                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1279                                         "C-type: 2 - IPv6");
1280                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 16, 
1281                                         "Source address: %s", 
1282                                         ip6_to_str(&(tem->source)));
1283                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+18, 2,
1284                                         "Source port: %u", pntohs(pd+offset2+18));
1285                     break;
1286                 }
1287                 
1288                 case 7: {
1289                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1290                                         "C-type: 7 - IPv4 LSP");
1291                     memcpy(&ip_addr, pd+offset2, 4);
1292                     proto_tree_add_ipv4(rsvp_object_tree, rsvp_filter[RSVPF_SENDER_IP], NullTVB, 
1293                                         offset2, 4, ip_addr);
1294
1295                     proto_tree_add_uint(rsvp_object_tree, rsvp_filter[RSVPF_SENDER_LSP_ID], NullTVB, 
1296                                         offset2+6, 2, pntohs(pd+offset2+6));
1297                     break;
1298                 }
1299
1300                 default: {
1301                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1302                                         "C-type: Unknown (%u)",
1303                                         obj->type);
1304                     i = obj_length - sizeof(rsvp_object);
1305                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1306                                         "Data (%d bytes)", i);
1307                 }
1308                 }
1309                 break;
1310
1311             case RSVP_CLASS_SENDER_TSPEC : {
1312                 rsvp_tspec *tspec = (rsvp_tspec *)obj;
1313                 IS_tspec *ist;
1314                 QUAL_tspec *qt;
1315                 service_hdr  *sh;
1316                 char *str;
1317
1318                 mylen = obj_length;
1319                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_sender_tspec);
1320                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1321                                     obj_length);
1322                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1323                                     "Class number: %u - %s", 
1324                                     obj->class, object_type);
1325
1326                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1, 
1327                                     "Message format version: %u", 
1328                                     tspec->version>>4);
1329                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2, 
1330                                     "Data length: %u words, not including header", 
1331                                     pntohs(pd+offset2+2));
1332
1333                 mylen -=4;
1334                 offset2 +=4;
1335                 while (mylen > 4) {
1336                     sh = (service_hdr *)(pd+offset2);
1337                     str = match_strval(sh->service_num, qos_vals);
1338                     if (!str) str = "Unknown";
1339
1340                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1, 
1341                                         "Service header: %u - %s", 
1342                                         sh->service_num, str);
1343                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2, 
1344                                         "Length of service %u data: %u words, " 
1345                                         "not including header", 
1346                                         sh->service_num,
1347                                         ntohs(sh->length));
1348
1349                     offset2+=4; mylen -=4; 
1350
1351                     switch(sh->service_num) {
1352                         
1353                     case QOS_TSPEC :
1354                         ist = (IS_tspec *)sh;
1355
1356                         /* Token bucket TSPEC */
1357                         str = match_strval(ist->param_id, svc_vals);
1358                         if (!str) str = "Unknown";
1359                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1, 
1360                                             "Parameter %u - %s", 
1361                                             ist->param_id, str);
1362                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+1, 1, 
1363                                             "Parameter %u flags: %x", 
1364                                             ist->param_id, ist->flags_tspec);
1365                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2, 
1366                                             "Parameter %u data length: %u words, " 
1367                                             "not including header",
1368                                             ist->param_id,
1369                                             /* pntohs(pd+offset2+10)); */
1370                                             ntohs(ist->parameter_length));
1371                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+4, 4, 
1372                                             "Token bucket rate: %ld", 
1373                                             pieee_to_long(pd+offset2+4));
1374                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+8, 4, 
1375                                             "Token bucket size: %ld", 
1376                                             pieee_to_long(pd+offset2+8));
1377                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+12, 4, 
1378                                             "Peak data rate: %ld", 
1379                                             pieee_to_long(pd+offset2+12));
1380                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+16, 4, 
1381                                             "Minimum policed unit: %u", 
1382                                             pntohl(pd+offset2+16));
1383                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+20, 4, 
1384                                             "Maximum policed unit: %u", 
1385                                             pntohl(pd+offset2+20));
1386
1387                         break;
1388
1389                     case QOS_QUALITATIVE :
1390                         qt = (QUAL_tspec *)sh;
1391
1392                         /* Token bucket TSPEC */
1393                         str = match_strval(qt->param_id, svc_vals);
1394                         if (!str) str = "Unknown";
1395                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1, 
1396                                             "Parameter %u - %s", 
1397                                             qt->param_id, str);
1398                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+1, 1, 
1399                                             "Parameter %u flags: %x", 
1400                                             qt->param_id, qt->flags_tspec);
1401                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2, 
1402                                             "Parameter %u data length: %u words, " 
1403                                             "not including header",
1404                                             qt->param_id,
1405                                             /* pntohs(pd+offset2+10)); */
1406                                             ntohs(qt->parameter_length));
1407                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+4, 4, 
1408                                             "Maximum policed unit: %u", 
1409                                             pntohl(pd+offset2+4));
1410
1411                         break;
1412
1413                     }
1414                     offset2 += ntohs(sh->length)*4; 
1415                     mylen -= ntohs(sh->length)*4;
1416                 }
1417                     
1418                 break;
1419             }
1420
1421             case RSVP_CLASS_FLOWSPEC : {
1422                 rsvp_flowspec *flowspec = (rsvp_flowspec *)obj;
1423                 IS_flowspec *isf;
1424                 QUAL_flowspec *qf;
1425                 service_hdr *sh;
1426                 int mylen;
1427
1428                 char *str;
1429
1430                 mylen = obj_length;
1431                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_flowspec);
1432                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1433                                     obj_length);
1434                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1435                                     "Class number: %u - %s", 
1436                                     obj->class, object_type);
1437
1438                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1, 
1439                                     "Message format version: %u", 
1440                                     flowspec->version>>4);
1441                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2, 
1442                                     "Data length: %u words, not including header", 
1443                                     pntohs(pd+offset2+2));
1444
1445                 mylen -=4;
1446                 offset2+=4;
1447                 while (mylen > 4) {
1448                     sh = (service_hdr *)(pd+offset2);
1449                     str = match_strval(sh->service_num, intsrv_services_str);
1450                     if (!str) str = "Unknown";
1451
1452                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1, 
1453                                         "Service header: %u - %s", 
1454                                         sh->service_num, str);
1455                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2, 
1456                                         "Length of service %u data: %u words, " 
1457                                         "not including header", 
1458                                         sh->service_num,
1459                                         ntohs(sh->length));
1460
1461                     offset2+=4; mylen -=4; 
1462
1463                     switch(sh->service_num) {
1464
1465                     case QOS_CONTROLLED_LOAD :
1466                     case QOS_GUARANTEED :
1467                         /* Treat both these the same for now */
1468                         isf = (IS_flowspec *)sh;
1469
1470                         str = match_strval(isf->tspec.param_id, svc_vals);
1471                         if (!str) str = "Unknown";
1472                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1, 
1473                                             "Parameter %u - %s", 
1474                                             isf->tspec.param_id, str);
1475                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+1, 1, 
1476                                             "Parameter %u flags: %x", 
1477                                             isf->tspec.param_id, isf->tspec.flags_tspec);
1478                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2, 
1479                                             "Parameter %u data length: %u words, " 
1480                                             "not including header",
1481                                             isf->tspec.param_id,
1482                                             ntohs(isf->tspec.parameter_length));
1483                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+4, 4, 
1484                                             "Token bucket rate: %ld", 
1485                                             pieee_to_long(pd+offset2+4));
1486                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+8, 4, 
1487                                             "Token bucket size: %ld", 
1488                                             pieee_to_long(pd+offset2+8));
1489                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+12, 4, 
1490                                             "Peak data rate: %ld", 
1491                                             pieee_to_long(pd+offset2+12));
1492                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+16, 4, 
1493                                             "Minimum policed unit: %u", 
1494                                             pntohl(pd+offset2+16));
1495                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+20, 4, 
1496                                             "Maximum policed unit: %u", 
1497                                             pntohl(pd+offset2+20));
1498                         if (sh->service_num!=QOS_GUARANTEED)
1499                             break;
1500                         
1501                         /* Guaranteed-rate RSpec */
1502                         str = match_strval(isf->rspec.param_id, svc_vals);
1503                         if (!str) str="Unknown";
1504                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+24, 1, 
1505                                             "Parameter %u - %s", 
1506                                             isf->rspec.param_id, str);
1507                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+25, 1, 
1508                                             "Parameter %u flags: %x", 
1509                                             isf->rspec.param_id, isf->rspec.flags_rspec);
1510                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+26, 2, 
1511                                             "Parameter %u data length: %u words, " 
1512                                             "not including header",
1513                                             isf->rspec.param_id,
1514                                             ntohs(isf->rspec.param2_length));
1515
1516                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+28, 4, 
1517                                             "Rate: %ld", 
1518                                             pieee_to_long(pd+offset2+28));
1519                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+32, 4, 
1520                                             "Slack term: %u", 
1521                                             pntohl(pd+offset2+32));
1522                         break;
1523
1524                     case QOS_QUALITATIVE :
1525                         qf = (QUAL_flowspec *)sh;
1526
1527                         str = match_strval(qf->param_id, svc_vals);
1528                         if (!str) str = "Unknown";
1529                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1, 
1530                                             "Parameter %u - %s", 
1531                                             qf->param_id, str);
1532                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+1, 1, 
1533                                             "Parameter %u flags: %x", 
1534                                             qf->param_id, qf->flags_tspec);
1535                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2, 
1536                                             "Parameter %u data length: %u words, " 
1537                                             "not including header",
1538                                             qf->param_id,
1539                                             ntohs(qf->parameter_length));
1540                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+4, 4, 
1541                                             "Maximum policed unit: %u", 
1542                                             pntohl(pd+offset2+4));
1543                         
1544                         break;
1545                     }
1546                     offset2 += ntohs(sh->length)*4;
1547                     mylen -= ntohs(sh->length)*4;
1548                 }
1549
1550                 break;
1551             }
1552
1553             case RSVP_CLASS_ADSPEC : {
1554                 proto_tree *adspec_tree;
1555                 service_hdr *shdr;
1556                 param_hdr *phdr; 
1557
1558                 char *str;
1559
1560                 mylen = obj_length;
1561                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_adspec);
1562                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1563                                     obj_length);
1564                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1565                                     "Class number: %u - %s", 
1566                                     obj->class, object_type);
1567                 
1568                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1, 
1569                                     "Message format version: %u", 
1570                                     (*((unsigned char *)pd+offset2))>>4);
1571                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2, 
1572                                     "Data length: %u words, not including header", 
1573                                     pntohs(pd+offset2+2));
1574                 offset2+=4;
1575                 mylen -= 4;
1576                 while (mylen > 4) {
1577                     shdr = (service_hdr *)(pd + offset2);
1578                     str = match_strval(shdr->service_num, intsrv_services_str);
1579
1580                     ti = proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 
1581                                              (pntohs(&shdr->length)+1)<<2,
1582                                              str?str:"Unknown");
1583                     adspec_tree = proto_item_add_subtree(ti,
1584                                                          ett_rsvp_adspec_subtree);
1585                     proto_tree_add_text(adspec_tree, NullTVB, offset2, 1,
1586                                         "Service header %u - %s",
1587                                         shdr->service_num, str);
1588                     proto_tree_add_text(adspec_tree, NullTVB, offset2+1, 1,
1589                                         (shdr->break_bit&0x80)?
1590                                         "Break bit set":"Break bit not set");
1591                     proto_tree_add_text(adspec_tree, NullTVB, offset2+2, 2, 
1592                                         "Data length: %u words, not including header", 
1593                                         pntohs(&shdr->length));
1594                     offset2+=4; i=(pntohs(&shdr->length)+1)<<2; mylen-=4;
1595                     while (i>4) {
1596                         phdr = (param_hdr *)(pd + offset2);
1597                         str = match_strval(phdr->id, adspec_params);
1598                         if (str) {
1599                             switch(phdr->id) {
1600                             case 4:
1601                             case 8:
1602                             case 10:
1603                             case 133:
1604                             case 134:
1605                             case 135:
1606                             case 136:
1607                                 /* 32-bit unsigned integer */
1608                                 proto_tree_add_text(adspec_tree, NullTVB, offset2, 
1609                                                     (pntohs(&phdr->length)+1)<<2,
1610                                                     "%s - %lu (type %u, length %u)",
1611                                                     str, 
1612                                                     (unsigned long)pntohl(&phdr->dataval), 
1613                                                     phdr->id, pntohs(&phdr->length));
1614                                 break;
1615                                 
1616                             case 6:
1617                                 /* IEEE float */
1618                                 proto_tree_add_text(adspec_tree, NullTVB, offset2, 
1619                                                     (pntohs(&phdr->length)+1)<<2,
1620                                                     "%s - %lu (type %u, length %u)",
1621                                                     str, 
1622                                                     pieee_to_long(&phdr->dataval), 
1623                                                     phdr->id, pntohs(&phdr->length));
1624                                 break;
1625                             default: 
1626                                 proto_tree_add_text(adspec_tree, NullTVB, offset2, 
1627                                                     (pntohs(&phdr->length)+1)<<2,
1628                                                     "%s (type %u, length %u)",
1629                                                     str, 
1630                                                     phdr->id, pntohs(&phdr->length));
1631                             }
1632                         } else {
1633                             proto_tree_add_text(adspec_tree, NullTVB, offset2, 
1634                                                 (pntohs(&phdr->length)+1)<<2,
1635                                                 "Unknown (type %u, length %u)",
1636                                                 phdr->id, pntohs(&phdr->length));
1637                         }
1638                         offset2+=(pntohs(&phdr->length)+1)<<2;
1639                         i-=(pntohs(&phdr->length)+1)<<2;
1640                         mylen-=(pntohs(&phdr->length)+1)<<2;
1641                     }
1642                 }
1643                 break;
1644             }
1645
1646             case RSVP_CLASS_INTEGRITY :
1647                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_integrity);
1648                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1649                                     obj_length);
1650                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1651                                     "Class number: %u - %s", 
1652                                     obj->class, object_type);
1653                 goto default_class;
1654
1655             case RSVP_CLASS_POLICY :
1656                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_policy);
1657                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1658                                     obj_length);
1659                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1660                                     "Class number: %u - %s", 
1661                                     obj->class, object_type);
1662                 goto default_class;
1663
1664             case RSVP_CLASS_LABEL_REQUEST : 
1665                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_label_request);
1666                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1667                                     obj_length);
1668                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1669                                     "Class number: %d - %s", 
1670                                     obj->class, object_type);
1671                 switch(obj->type) {
1672                 case 1: {
1673                     unsigned short l3pid = pntohs(pd+offset2+2);
1674                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1675                                         "C-type: 1");
1676                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 2,
1677                                         "L3PID: 0x%04x", l3pid);
1678                     break;
1679                 }
1680
1681                 default: {
1682                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1683                                         "C-type: Unknown (%d)",
1684                                         obj->type);
1685                     i = obj_length - sizeof(rsvp_object);
1686                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1687                                         "Data (%d bytes)", i);
1688                     break;
1689                 }
1690                 }
1691                 break;
1692             
1693             case RSVP_CLASS_LABEL : 
1694                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_label);
1695                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1696                                     obj_length);
1697                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1698                                     "Class number: %d - %s", 
1699                                     obj->class, object_type);
1700                 switch(obj->type) {
1701                 case 1: {
1702                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1703                                         "C-type: 1");
1704                     for (i=1, l = 0; l < obj_length - 4; l+=4, i++)
1705                         proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+l, 4, 
1706                                             "Label %d: %d %s", 
1707                                             i, pntohl(pd+offset2+l), 
1708                                             l == obj_length - 8 ? 
1709                                             "(Top label)" : "");
1710                     break;
1711                 }
1712
1713                 default: {
1714                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1715                                         "C-type: Unknown (%d)",
1716                                         obj->type);
1717                     i = obj_length - sizeof(rsvp_object);
1718                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1719                                         "Data (%d bytes)", i);
1720                     break;
1721                 }
1722                 }
1723                 break;
1724             
1725             case RSVP_CLASS_SESSION_ATTRIBUTE : 
1726                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_session_attribute);
1727                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1728                                     obj_length);
1729                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1730                                     "Class number: %d - %s", 
1731                                     obj->class, object_type);
1732                 switch(obj->type) {
1733                 case 7: {
1734                     char s_name[64];
1735                     session_attribute *s_attr = (session_attribute *)&pd[offset];
1736                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1737                                         "C-type: 7 - IPv4 LSP");
1738                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, 1,
1739                                         "Setup priority: %d", s_attr->setup_prio);
1740                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+1, 1,
1741                                         "Hold priority: %d", s_attr->hold_prio);
1742                     ti2 = proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+2, 1,
1743                                               "Flags: %0x", s_attr->flags);
1744                     rsvp_sa_flags_tree = proto_item_add_subtree(ti2, 
1745                                                                 ett_rsvp_session_attribute_flags);
1746                     proto_tree_add_text(rsvp_sa_flags_tree, NullTVB, offset2+2, 1, 
1747                                         ".......%d: Local protection: %s", 
1748                                         s_attr->flags & 0x1 ? 1 : 0,
1749                                         s_attr->flags & 0x1 ? "Set" : "Not set");
1750                     proto_tree_add_text(rsvp_sa_flags_tree, NullTVB, offset2+2, 1, 
1751                                         "......%d.: Merging permitted: %s", 
1752                                         s_attr->flags & 0x2 ? 1 : 0,
1753                                         s_attr->flags & 0x2 ? "Set" : "Not set");
1754                     proto_tree_add_text(rsvp_sa_flags_tree, NullTVB, offset2+2, 1, 
1755                                         ".....%d..: Ingress note may reroute: %s", 
1756                                         s_attr->flags & 0x4 ? 1 : 0,
1757                                         s_attr->flags & 0x4 ? "Set" : "Not set");
1758                     
1759                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+3, 1,
1760                                         "Name length: %d", s_attr->name_len);
1761                     memset(s_name, 0, 64);
1762                     strncpy(s_name, &pd[offset2+4], 60);
1763                     if (s_attr->name_len>60) sprintf(&(s_name[60]), "...");
1764                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2+4, s_attr->name_len,
1765                                         "Name: %s", s_name);
1766                     break;
1767                 }
1768
1769                 default: {
1770                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1771                                         "C-type: Unknown (%d)",
1772                                         obj->type);
1773                     i = obj_length - sizeof(rsvp_object);
1774                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1775                                         "Data (%d bytes)", i);
1776                     break;
1777                 }
1778                 }
1779                 break;
1780
1781             case RSVP_CLASS_EXPLICIT_ROUTE : 
1782                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_explicit_route);
1783                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1784                                     obj_length);
1785                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1786                                     "Class number: %d - %s", 
1787                                     obj->class, object_type);
1788                 switch(obj->type) {
1789                 case 1: {
1790                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1791                                         "C-type: 1");
1792                     for (i=1, l = 0; l < obj_length - 4; i++) {
1793                         j = ((unsigned char)pd[offset2+l]) & 0x7f;
1794                         switch(j) {
1795                         case 1: /* IPv4 */
1796                             k = ((unsigned char)pd[offset2+l]) & 0x80;
1797                             ti2 = proto_tree_add_text(rsvp_object_tree, NullTVB, 
1798                                                       offset2+l, 8,
1799                                                       "IPv4 Subobject - %s, %s",
1800                                                       ip_to_str(&pd[offset2+l+2]), 
1801                                                       k ? "Loose" : "Strict");
1802                             rsvp_ero_subtree = 
1803                                 proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); 
1804                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1805                                                 k ? "Loose Hop " : "Strict Hop");
1806                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1807                                                 "Type: 1 (IPv4)");
1808                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+1, 1, 
1809                                                 "Length: %d", pd[offset2+l+1]);
1810                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+2, 4, 
1811                                                 "IPv4 hop: %s", ip_to_str(&pd[offset2+l+2]));
1812                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+6, 1, 
1813                                                 "Prefix length: %d", pd[offset2+l+6]);
1814                             break;
1815
1816                         case 2: /* IPv6 */
1817                             ti2 = proto_tree_add_text(rsvp_object_tree, NullTVB, 
1818                                                       offset2+l, 20,
1819                                                       "IPv6 Subobject");
1820                             rsvp_ero_subtree = 
1821                                 proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); 
1822                             k = ((unsigned char)pd[offset2+l]) & 0x80;
1823                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1824                                                 k ? "Loose Hop " : "Strict Hop");
1825                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1826                                                 "Type: 2 (IPv6)");
1827                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+1, 1, 
1828                                                 "Length: %d", pd[offset2+l+1]);
1829                             ip6a = (struct e_in6_addr *)pd+offset2+l+2;
1830                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+2, 16, 
1831                                                 "IPv6 hop: %s", ip6_to_str(ip6a));
1832                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+18, 1, 
1833                                                 "Prefix length: %d", pd[offset2+l+6]);
1834                             break;
1835
1836                         case 32: /* AS */
1837                             k = pntohs(offset2+l+2);
1838                             ti2 = proto_tree_add_text(rsvp_object_tree, NullTVB, 
1839                                                       offset2+l, 4,
1840                                                       "Autonomous System %d", k);
1841                             rsvp_ero_subtree = 
1842                                 proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); 
1843                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1844                                                 k ? "Loose Hop " : "Strict Hop");
1845                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1846                                                 "Type: 32 (Autonomous System Number)");
1847                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+1, 1, 
1848                                                 "Length: %d", pd[offset2+l+1]);
1849                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+2, 2, 
1850                                                 "Autonomous System %d", k);
1851                             break;
1852
1853                         case 64: /* Path Term */
1854                             k = ((unsigned char)pd[offset2+l]) & 0x80;
1855                             ti2 = proto_tree_add_text(rsvp_object_tree, NullTVB, 
1856                                                       offset2+l, 4,
1857                                                       "LSP Path Termination");
1858                             rsvp_ero_subtree = 
1859                                 proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); 
1860                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1861                                                 k ? "Loose Hop " : "Strict Hop");
1862                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1863                                                 "Type: 64 (MPLS LSP Path Termination)");
1864                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+1, 1, 
1865                                                 "Length: %d", pd[offset2+l+1]);
1866                             break;
1867
1868                         default: /* Unknown subobject */
1869                             k = ((unsigned char)pd[offset2+l]) & 0x80;
1870                             ti2 = proto_tree_add_text(rsvp_object_tree, NullTVB, 
1871                                                       offset2+l, pd[offset2+l+1],
1872                                                       "Unknown subobject: %d", j);
1873                             rsvp_ero_subtree = 
1874                                 proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); 
1875                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1876                                                 k ? "Loose Hop " : "Strict Hop");
1877                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1878                                                 "Type: %d (Unknown)", j);
1879                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+1, 1, 
1880                                                 "Length: %d", pd[offset2+l+1]);
1881
1882                         }
1883
1884                         l += ((unsigned char)pd[offset2+l+1]);
1885                     }
1886                     break;
1887                 }
1888                 default: {
1889                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1890                                         "C-type: Unknown (%d)",
1891                                         obj->type);
1892                     i = obj_length - sizeof(rsvp_object);
1893                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1894                                         "Data (%d bytes)", i);
1895                     break;
1896                 }
1897                 }
1898                 break;
1899             
1900
1901             case RSVP_CLASS_RECORD_ROUTE : 
1902                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_record_route);
1903                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1904                                     obj_length);
1905                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1906                                     "Class number: %d - %s", 
1907                                     obj->class, object_type);
1908                 switch(obj->type) {
1909                 case 1: {
1910                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1911                                         "C-type: 1");
1912                     for (i=1, l = 0; l < obj_length - 4; i++) {
1913                         j = (unsigned char)pd[offset2+l];
1914                         switch(j) {
1915                         case 1: /* IPv4 */
1916                             ti2 = proto_tree_add_text(rsvp_object_tree, NullTVB, 
1917                                                       offset2+l, 8,
1918                                                       "IPv4 Subobject - %s",
1919                                                       ip_to_str(&pd[offset2+l+2]));
1920                             rsvp_ero_subtree = 
1921                                 proto_item_add_subtree(ti2, ett_rsvp_record_route_subobj); 
1922                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1923                                                 "Type: 1 (IPv4)");
1924                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+1, 1, 
1925                                                 "Length: %d", pd[offset2+l+1]);
1926                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+2, 4, 
1927                                                 "IPv4 hop: %s", ip_to_str(&pd[offset2+l+2]));
1928                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+6, 1, 
1929                                                 "Prefix length: %d", pd[offset2+l+6]);
1930                             break;
1931
1932                         case 2: /* IPv6 */
1933                             ti2 = proto_tree_add_text(rsvp_object_tree, NullTVB, 
1934                                                       offset2+l, 20,
1935                                                       "IPv6 Subobject");
1936                             rsvp_ero_subtree = 
1937                                 proto_item_add_subtree(ti2, ett_rsvp_record_route_subobj); 
1938                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1939                                                 "Type: 2 (IPv6)");
1940                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+1, 1, 
1941                                                 "Length: %d", pd[offset2+l+1]);
1942                             ip6a = (struct e_in6_addr *)pd+offset2+l+2;
1943                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+2, 16, 
1944                                                 "IPv6 hop: %s", ip6_to_str(ip6a));
1945                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+18, 1, 
1946                                                 "Prefix length: %d", pd[offset2+l+6]);
1947                             break;
1948
1949                         default: /* Unknown subobject */
1950                             k = ((unsigned char)pd[offset2+l]) & 0x80;
1951                             ti2 = proto_tree_add_text(rsvp_object_tree, NullTVB, 
1952                                                       offset2+l, pd[offset2+l+1],
1953                                                       "Unknown subobject: %d", j);
1954                             rsvp_ero_subtree = 
1955                                 proto_item_add_subtree(ti2, ett_rsvp_record_route_subobj); 
1956                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1957                                                 k ? "Loose Hop " : "Strict Hop");
1958                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l, 1, 
1959                                                 "Type: %d (Unknown)", j);
1960                             proto_tree_add_text(rsvp_ero_subtree, NullTVB, offset2+l+1, 1, 
1961                                                 "Length: %d", pd[offset2+l+1]);
1962
1963                         }
1964
1965                         l += ((unsigned char)pd[offset2+l+1]);
1966                     }
1967                     break;
1968                 }
1969                 
1970                 default: {
1971                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset+3, 1, 
1972                                         "C-type: Unknown (%d)",
1973                                         obj->type);
1974                     i = obj_length - sizeof(rsvp_object);
1975                     proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1976                                         "Data (%d bytes)", i);
1977                     break;
1978                 }
1979                 }
1980                 break;
1981             
1982             default :
1983                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_unknown_class);
1984                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset, 2, "Length: %d", 
1985                                     obj_length);
1986                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset+2, 1, 
1987                                     "Class number: %u - %s", 
1988                                     obj->class, object_type);
1989             default_class:
1990                 i = obj_length - sizeof(rsvp_object);
1991                 proto_tree_add_text(rsvp_object_tree, NullTVB, offset2, i,
1992                                     "Data (%d bytes)", i);
1993                 break;
1994
1995             case RSVP_CLASS_NULL :
1996                 break;
1997
1998             }  
1999             
2000             offset += obj_length;
2001             len += obj_length;
2002         }
2003     }
2004 }
2005
2006 void
2007 proto_register_rsvp(void)
2008 {
2009         static gint *ett[] = {
2010                 &ett_rsvp,
2011                 &ett_rsvp_hdr,
2012                 &ett_rsvp_session,
2013                 &ett_rsvp_hop,
2014                 &ett_rsvp_time_values,
2015                 &ett_rsvp_error,
2016                 &ett_rsvp_scope,
2017                 &ett_rsvp_style,
2018                 &ett_rsvp_confirm,
2019                 &ett_rsvp_sender_template,
2020                 &ett_rsvp_filter_spec,
2021                 &ett_rsvp_sender_tspec,
2022                 &ett_rsvp_flowspec,
2023                 &ett_rsvp_adspec,
2024                 &ett_rsvp_adspec_subtree,
2025                 &ett_rsvp_integrity,
2026                 &ett_rsvp_policy,
2027                 &ett_rsvp_label,
2028                 &ett_rsvp_label_request,
2029                 &ett_rsvp_session_attribute,
2030                 &ett_rsvp_session_attribute_flags,
2031                 &ett_rsvp_explicit_route,
2032                 &ett_rsvp_explicit_route_subobj,
2033                 &ett_rsvp_record_route,
2034                 &ett_rsvp_record_route_subobj,
2035                 &ett_rsvp_unknown_class,
2036         };
2037
2038         proto_rsvp = proto_register_protocol("Resource ReserVation Protocol (RSVP)",
2039             "RSVP", "rsvp");
2040         proto_register_field_array(proto_rsvp, rsvpf_info, array_length(rsvpf_info));
2041         proto_register_subtree_array(ett, array_length(ett));
2042 }
2043
2044 void
2045 proto_reg_handoff_rsvp(void)
2046 {
2047         old_dissector_add("ip.proto", IP_PROTO_RSVP, dissect_rsvp,
2048             proto_rsvp);
2049 }