Add in some missing header files.
[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.67 2002/06/06 11:02:05 guy Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
10  * Copyright 1998 Gerald Combs
11  * 
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  * 
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  * 
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 /*
28  * NOTES
29  *
30  * This module defines routines to disassemble RSVP packets, as defined in
31  * RFC 2205. All objects from RFC2205 are supported, in IPv4 and IPv6 mode.
32  * In addition, the Integrated Services traffic specification objects
33  * defined in RFC2210 are also supported. 
34  *
35  * IPv6 support is not completely tested
36  *
37  * Mar 3, 2000: Added support for MPLS/TE objects, as defined in 
38  * <draft-ietf-mpls-rsvp-lsp-tunnel-04.txt>
39  */
40
41  
42 #ifdef HAVE_CONFIG_H
43 # include "config.h"
44 #endif
45
46 #include <stdio.h>
47
48 #ifdef HAVE_UNISTD_H
49 #include <unistd.h>
50 #endif
51
52 #include <stdlib.h>
53 #include <string.h>
54
55 #ifdef HAVE_SYS_TYPES_H
56 # include <sys/types.h>
57 #endif
58
59 #ifdef HAVE_NETINET_IN_H
60 # include <netinet/in.h>
61 #endif
62
63 #include <glib.h>
64
65 #ifdef NEED_SNPRINTF_H
66 # include "snprintf.h"
67 #endif
68
69 #include <epan/tvbuff.h>
70 #include <epan/packet.h>
71 #include "in_cksum.h"
72 #include "etypes.h"
73 #include "ipproto.h"
74
75 #include "packet-rsvp.h"
76 #include "packet-ip.h"
77 #include "packet-frame.h"
78
79 static int proto_rsvp = -1;
80
81 static gint ett_rsvp = -1;
82 static gint ett_rsvp_hdr = -1;
83 static gint ett_rsvp_session = -1;
84 static gint ett_rsvp_hop = -1;
85 static gint ett_rsvp_time_values = -1;
86 static gint ett_rsvp_error = -1;
87 static gint ett_rsvp_scope = -1;
88 static gint ett_rsvp_style = -1;
89 static gint ett_rsvp_confirm = -1;
90 static gint ett_rsvp_sender_template = -1;
91 static gint ett_rsvp_filter_spec = -1;
92 static gint ett_rsvp_sender_tspec = -1;
93 static gint ett_rsvp_sender_tspec_subtree = -1;
94 static gint ett_rsvp_flowspec = -1;
95 static gint ett_rsvp_flowspec_subtree = -1;
96 static gint ett_rsvp_adspec = -1;
97 static gint ett_rsvp_adspec_subtree = -1;
98 static gint ett_rsvp_integrity = -1;
99 static gint ett_rsvp_integrity_flags = -1;
100 static gint ett_rsvp_dclass = -1;
101 static gint ett_rsvp_lsp_tunnel_if_id = -1;
102 static gint ett_rsvp_policy = -1;
103 static gint ett_rsvp_label = -1;
104 static gint ett_rsvp_label_request = -1;
105 static gint ett_rsvp_session_attribute = -1;
106 static gint ett_rsvp_session_attribute_flags = -1;
107 static gint ett_rsvp_hello_obj = -1;
108 static gint ett_rsvp_explicit_route = -1;
109 static gint ett_rsvp_explicit_route_subobj = -1;
110 static gint ett_rsvp_record_route = -1;
111 static gint ett_rsvp_record_route_subobj = -1;
112 static gint ett_rsvp_hop_subobj = -1;
113 static gint ett_rsvp_admin_status = -1;
114 static gint ett_rsvp_admin_status_flags = -1;
115 static gint ett_rsvp_gen_uni = -1;
116 static gint ett_rsvp_gen_uni_subobj = -1;
117 static gint ett_rsvp_unknown_class = -1;
118
119
120 /*
121  * RSVP message types.
122  * See
123  *
124  *      http://www.iana.org/assignments/rsvp-parameters
125  */
126 typedef enum {
127     RSVP_MSG_PATH=1,                    /* RFC 2205 */
128     RSVP_MSG_RESV,                      /* RFC 2205 */
129     RSVP_MSG_PERR,                      /* RFC 2205 */
130     RSVP_MSG_RERR,                      /* RFC 2205 */
131     RSVP_MSG_PTEAR,                     /* RFC 2205 */
132     RSVP_MSG_RTEAR,                     /* RFC 2205 */
133     RSVP_MSG_CONFIRM,                   /* XXX - DREQ, RFC 2745? */
134                                         /* 9 is DREP, RFC 2745 */
135     RSVP_MSG_RTEAR_CONFIRM=10,          /* from Fred Baker at Cisco */
136                                         /* 11 is unassigned */
137     RSVP_MSG_BUNDLE = 12,               /* RFC 2961 */
138     RSVP_MSG_ACK,                       /* RFC 2961 */
139                                         /* 14 is reserved */
140     RSVP_MSG_SREFRESH = 15,             /* RFC 2961 */
141                                         /* 16, 17, 18, 19 not listed */
142     RSVP_MSG_HELLO = 20                 /* RFC 3209 */
143                                         /* 25 is Integrity Challenge
144                                            RFC 2747, RFC 3097 */
145                                         /* 26 is Integrity Response
146                                            RFC 2747, RFC 3097 */
147                                         /* 66 is DSBM_willing [SBM] */
148                                         /* 67 is I_AM_DSBM [SBM] */
149                                         /* [SBM] is Subnet Bandwidth
150                                            Manager ID from July 1997 */
151 } rsvp_message_types;
152
153 static value_string message_type_vals[] = { 
154     {RSVP_MSG_PATH, "PATH Message. "},
155     {RSVP_MSG_RESV, "RESV Message. "},
156     {RSVP_MSG_PERR, "PATH ERROR Message. "},
157     {RSVP_MSG_RERR, "RESV ERROR Message. "},
158     {RSVP_MSG_PTEAR, "PATH TEAR Message. "},
159     {RSVP_MSG_RTEAR, "RESV TEAR Message. "},
160     {RSVP_MSG_CONFIRM, "CONFIRM Message. "},
161     {RSVP_MSG_RTEAR_CONFIRM, "RESV TEAR CONFIRM Message. "},
162     {RSVP_MSG_BUNDLE, "BUNDLE Message. "},
163     {RSVP_MSG_ACK, "ACK Message. "},
164     {RSVP_MSG_SREFRESH, "SREFRESH Message. "},
165     {RSVP_MSG_HELLO, "HELLO Message. "},
166     {0, NULL}
167 };
168
169 /* 
170  * RSVP classes
171  */
172 #define MAX_RSVP_CLASS 15
173
174 enum rsvp_classes {
175     RSVP_CLASS_NULL=0,
176     RSVP_CLASS_SESSION,
177
178     RSVP_CLASS_HOP=3,
179     RSVP_CLASS_INTEGRITY,
180     RSVP_CLASS_TIME_VALUES,
181     RSVP_CLASS_ERROR,
182     RSVP_CLASS_SCOPE,
183     RSVP_CLASS_STYLE,
184     RSVP_CLASS_FLOWSPEC,
185     RSVP_CLASS_FILTER_SPEC,
186     RSVP_CLASS_SENDER_TEMPLATE,
187     RSVP_CLASS_SENDER_TSPEC,
188     RSVP_CLASS_ADSPEC,
189     RSVP_CLASS_POLICY,
190     RSVP_CLASS_CONFIRM,
191     RSVP_CLASS_LABEL,
192
193     RSVP_CLASS_LABEL_REQUEST=19,
194     RSVP_CLASS_EXPLICIT_ROUTE,
195     RSVP_CLASS_RECORD_ROUTE,
196
197     RSVP_CLASS_HELLO,
198
199     RSVP_CLASS_MESSAGE_ID,
200     RSVP_CLASS_MESSAGE_ID_ACK,
201     RSVP_CLASS_MESSAGE_ID_LIST,
202
203     RSVP_CLASS_RECOVERY_LABEL = 34,
204     RSVP_CLASS_UPSTREAM_LABEL,
205     RSVP_CLASS_LABEL_SET,
206     RSVP_CLASS_PROTECTION,
207
208     RSVP_CLASS_SUGGESTED_LABEL = 129,
209     RSVP_CLASS_ACCEPTABLE_LABEL_SET,
210     RSVP_CLASS_RESTART_CAP,
211
212     RSVP_CLASS_NOTIFY_REQUEST = 195,
213     RSVP_CLASS_ADMIN_STATUS,
214
215     RSVP_CLASS_SESSION_ATTRIBUTE = 207,
216     RSVP_CLASS_GENERALIZED_UNI,
217     RSVP_CLASS_DCLASS = 225,
218     RSVP_CLASS_LSP_TUNNEL_IF_ID = 227
219 };
220
221 static value_string rsvp_class_vals[] = { 
222     {RSVP_CLASS_NULL, "NULL object"},
223     {RSVP_CLASS_SESSION, "SESSION object"},
224     {RSVP_CLASS_HOP, "HOP object"},
225     {RSVP_CLASS_INTEGRITY, "INTEGRITY object"},
226     {RSVP_CLASS_TIME_VALUES, "TIME VALUES object"},
227     {RSVP_CLASS_ERROR, "ERROR object"},
228     {RSVP_CLASS_SCOPE, "SCOPE object"},
229     {RSVP_CLASS_STYLE, "STYLE object"},
230     {RSVP_CLASS_FLOWSPEC, "FLOWSPEC object"},
231     {RSVP_CLASS_FILTER_SPEC, "FILTER SPEC object"},
232     {RSVP_CLASS_SENDER_TEMPLATE, "SENDER TEMPLATE object"},
233     {RSVP_CLASS_SENDER_TSPEC, "SENDER TSPEC object"},
234     {RSVP_CLASS_ADSPEC, "ADSPEC object"},
235     {RSVP_CLASS_POLICY, "POLICY object"},
236     {RSVP_CLASS_CONFIRM, "CONFIRM object"},
237     {RSVP_CLASS_LABEL, "LABEL object"},
238     {RSVP_CLASS_LABEL_REQUEST, "LABEL REQUEST object"},
239     {RSVP_CLASS_EXPLICIT_ROUTE, "EXPLICIT ROUTE object"},
240     {RSVP_CLASS_RECORD_ROUTE, "RECORD ROUTE object"},
241     {RSVP_CLASS_SESSION_ATTRIBUTE, "SESSION ATTRIBUTE object"},
242     {RSVP_CLASS_MESSAGE_ID, "MESSAGE-ID object"},
243     {RSVP_CLASS_MESSAGE_ID_ACK, "MESSAGE-ID ACK/NACK object"},
244     {RSVP_CLASS_MESSAGE_ID_LIST, "MESSAGE-ID LIST object"},
245     {RSVP_CLASS_HELLO, "HELLO object"},
246     {RSVP_CLASS_RECOVERY_LABEL, "RECOVERY-LABEL object"},
247     {RSVP_CLASS_UPSTREAM_LABEL, "UPSTREAM-LABEL object"},
248     {RSVP_CLASS_LABEL_SET, "LABEL-SET object"},
249     {RSVP_CLASS_PROTECTION, "PROTECTION object"},
250     {RSVP_CLASS_SUGGESTED_LABEL, "SUGGESTED-LABEL object"},
251     {RSVP_CLASS_ACCEPTABLE_LABEL_SET, "ACCEPTABLE-LABEL-SET object"},
252     {RSVP_CLASS_RESTART_CAP, "RESTART-CAPABILITY object"},
253     {RSVP_CLASS_DCLASS, "DCLASS object"},
254     {RSVP_CLASS_LSP_TUNNEL_IF_ID, "LSP-TUNNEL INTERFACE-ID object"},
255     {RSVP_CLASS_NOTIFY_REQUEST, "NOTIFY-REQUEST object"},
256     {RSVP_CLASS_ADMIN_STATUS, "ADMIN-STATUS object"},
257     {RSVP_CLASS_GENERALIZED_UNI, "GENERALIZED-UNI object"},
258     {0, NULL}
259 };
260
261 /*
262  * RSVP error values
263  */
264 enum rsvp_error_types {
265     RSVP_ERROR_CONFIRM = 0,
266     RSVP_ERROR_ADMISSION,
267     RSVP_ERROR_POLICY,
268     RSVP_ERROR_NO_PATH,
269     RSVP_ERROR_NO_SENDER,
270     RSVP_ERROR_CONFLICT_RESV_STYLE,
271     RSVP_ERROR_UNKNOWN_RESV_STYLE,
272     RSVP_ERROR_CONFLICT_DEST_PORTS,
273     RSVP_ERROR_CONFLICT_SRC_PORTS,
274     RSVP_ERROR_PREEMPTED=12,
275     RSVP_ERROR_UNKNOWN_CLASS,
276     RSVP_ERROR_UNKNOWN_C_TYPE,
277     RSVP_ERROR_TRAFFIC = 21,
278     RSVP_ERROR_TRAFFIC_SYSTEM,
279     RSVP_ERROR_SYSTEM,
280     RSVP_ERROR_ROUTING,
281     RSVP_ERROR_NOTIFY
282 };
283
284 static value_string rsvp_error_vals[] = {
285     {RSVP_ERROR_CONFIRM, "Confirmation"},
286     {RSVP_ERROR_ADMISSION, "Admission Control Failure "},
287     {RSVP_ERROR_POLICY, "Policy Control Failure"},
288     {RSVP_ERROR_NO_PATH, "No PATH information for this RESV message"},
289     {RSVP_ERROR_NO_SENDER, "No sender information for this RESV message"},
290     {RSVP_ERROR_CONFLICT_RESV_STYLE, "Conflicting reservation styles"},
291     {RSVP_ERROR_UNKNOWN_RESV_STYLE, "Unknown reservation style"},
292     {RSVP_ERROR_CONFLICT_DEST_PORTS, "Conflicting destination ports"},
293     {RSVP_ERROR_CONFLICT_SRC_PORTS, "Conflicting source ports"},
294     {RSVP_ERROR_PREEMPTED, "Service preempted"},
295     {RSVP_ERROR_UNKNOWN_CLASS, "Unknown object class"},
296     {RSVP_ERROR_UNKNOWN_C_TYPE, "Unknown object C-type"},
297     {RSVP_ERROR_TRAFFIC, "Traffic Control Error"},
298     {RSVP_ERROR_TRAFFIC_SYSTEM, "Traffic Control System Error"},
299     {RSVP_ERROR_SYSTEM, "RSVP System Error"},
300     {RSVP_ERROR_ROUTING, "Routing Error"},
301     {RSVP_ERROR_NOTIFY, "RSVP Notify Error"},
302     {0, NULL}
303 };
304
305 /*
306  * Defines the reservation style plus style-specific information that
307  * is not a FLOWSPEC or FILTER_SPEC object, in a RESV message.
308  */
309 #define RSVP_DISTINCT (1 << 3)
310 #define RSVP_SHARED (2 << 3)
311 #define RSVP_SHARING_MASK (RSVP_DISTINCT | RSVP_SHARED)
312
313 #define RSVP_SCOPE_WILD 1
314 #define RSVP_SCOPE_EXPLICIT 2
315 #define RSVP_SCOPE_MASK 0x07
316
317 #define RSVP_WF (RSVP_SHARED | RSVP_SCOPE_WILD)
318 #define RSVP_FF (RSVP_DISTINCT | RSVP_SCOPE_EXPLICIT)
319 #define RSVP_SE (RSVP_SHARED | RSVP_SCOPE_EXPLICIT)
320
321 static value_string style_vals[] = {
322     { RSVP_WF, "Wildcard Filter" },
323     { RSVP_FF, "Fixed Filter" },
324     { RSVP_SE, "Shared-Explicit" },
325     { 0,       NULL }
326 };
327
328 enum {
329     RSVP_SESSION_TYPE_IPV4 = 1,
330     RSVP_SESSION_TYPE_IPV6,
331
332     RSVP_SESSION_TYPE_IPV4_LSP = 7,
333     RSVP_SESSION_TYPE_IPV6_LSP,
334
335     RSVP_SESSION_TYPE_IPV4_UNI = 9
336 };
337
338 /*
339  * Defines a desired QoS, in a RESV message.
340  */
341 enum    qos_service_type {
342     QOS_QUALITATIVE =     128,          /* Qualitative service */
343     QOS_NULL =              6,          /* Null service (RFC2997) */
344     QOS_CONTROLLED_LOAD=    5,          /* Controlled Load Service */
345     QOS_GUARANTEED =        2,          /* Guaranteed service */
346     QOS_TSPEC =             1           /* Traffic specification */
347     };
348
349 static value_string qos_vals[] = {
350     { QOS_QUALITATIVE, "Qualitative QoS" },
351     { QOS_NULL, "Null-Service QoS" },
352     { QOS_CONTROLLED_LOAD, "Controlled-load QoS" },
353     { QOS_GUARANTEED, "Guaranteed rate QoS" },
354     { QOS_TSPEC, "Traffic specification" },
355     { 0, NULL }
356 };
357
358 static value_string svc_vals[] = {
359     { 126, "Compression Hint" },
360     { 127, "Token bucket" },
361     { 128, "Null Service" },
362     { 130, "Guaranteed-rate RSpec" },
363     { 0, NULL }
364 };
365
366 enum rsvp_spec_types { INTSRV = 2 };
367
368 enum intsrv_services {
369         INTSRV_GENERAL = 1,
370         INTSRV_GTD = 2,
371         INTSRV_CLOAD = 5,
372         INTSRV_NULL = 6,
373         INTSRV_QUALITATIVE = 128
374 };
375
376 static value_string intsrv_services_str[] = { 
377     {INTSRV_GENERAL, "Default General Parameters"},
378     {INTSRV_GTD, "Guaranteed Rate"},
379     {INTSRV_CLOAD, "Controlled Load"},
380     {INTSRV_NULL, "Null Service"},
381     {INTSRV_QUALITATIVE, "Null Service"},
382     { 0, NULL }
383 };
384
385 #if 0
386 enum intsrv_field_name {
387         INTSRV_NON_IS_HOPS = 1, INTSRV_COMPOSED_NON_IS_HOPS,
388         INTSRV_IS_HOPS, INTSRV_COMPOSED_IS_HOPS,
389         INTSRV_PATH_BANDWIDTH, INTSRV_MIN_PATH_BANDWIDTH,
390         INTSRV_IF_LATENCY, INTSRV_PATH_LATENCY,
391         INTSRV_MTU, INTSRV_COMPOSED_MTU,
392
393         INTSRV_TOKEN_BUCKET_TSPEC = 127,
394         INTSRV_QUALITATIVE_TSPEC = 128,
395         INTSRV_GTD_RSPEC = 130,
396
397         INTSRV_DELAY = 131,     /* Gtd Parameter C - Max Delay Bound - bytes */
398         INTSRV_MAX_JITTER,      /* Gtd Parameter D - Max Jitter */
399         INTSRV_E2E_DELAY,       /* Gtd Parameter Ctot */
400         INTSRV_E2E_MAX_JITTER,  /* Gtd Parameter Dtot */
401         INTSRV_SHP_DELAY,       /* Gtd Parameter Csum */
402         INTSRV_SHP_MAX_JITTER   /* Gtd Parameter Dsum */
403 };
404 #endif
405
406 static value_string adspec_params[] = { 
407     {4, "IS Hop Count"},
408     {6, "Path b/w estimate"},
409     {8, "Minimum path latency"},
410     {10, "Composed MTU"},
411     {133, "End-to-end composed value for C"},
412     {134, "End-to-end composed value for D"},
413     {135, "Since-last-reshaping point composed C"},
414     {136, "Since-last-reshaping point composed D"},
415     { 0, NULL }
416 };
417
418 const value_string gmpls_lsp_enc_str[] = {
419     { 1, "Packet"},
420     { 2, "Ethernet v2/DIX"},
421     { 3, "ANSI PDH"},
422     { 4, "ETSI PDH"},
423     { 5, "SDH ITU-T G.707"},
424     { 6, "SONET ANSI T1.105"},
425     { 7, "Digital Wrapper"},
426     { 8, "Lambda (photonic)"},
427     { 9, "Fiber"},
428     {10, "Ethernet 802.3"},
429     {11, "FiberChannel"},
430     { 0, NULL }
431 };
432
433 const value_string gmpls_switching_type_str[] = {
434     {  1, "Packet-Switch Capable-1 (PSC-1)"},
435     {  2, "Packet-Switch Capable-2 (PSC-2)"},
436     {  3, "Packet-Switch Capable-3 (PSC-3)"},
437     {  4, "Packet-Switch Capable-4 (PSC-4)"},
438     { 51, "Layer-2 Switch Capable (L2SC)"},
439     {100, "Time-Division-Multiplex Capable (TDM)"},
440     {150, "Lambda-Switch Capable (LSC)"},
441     {200, "Fiber-Switch Capable (FSC)"},
442     { 0, NULL }
443 };
444
445 static const value_string gmpls_gpid_str[] = {
446     { 5, "Asynchronous mapping of E3 (SONET, SDH)"},
447     { 8, "Bit synchronous mapping of E3 (SDH)"},
448     { 9, "Byte synchronous mapping of E3 (SDH)"},
449     {10, "Asynchronous mapping of DS2/T2 (SONET, SDH)"},
450     {11, "Bit synchronous mapping of DS2/T2 (SONET, SDH)"},
451     {13, "Asynchronous mapping of E1 (SONET, SDH)"},
452     {14, "Byte synchronous mapping of E1 (SONET, SDH)"},
453     {15, "Byte synchronous mapping of 31 * DS0 (SONET, SDH)"},
454     {16, "Asynchronous mapping of DS1/T1 (SONET, SDH)"},
455     {17, "Bit synchronous mapping of DS1/T1 (SONET, SDH)"},
456     {18, "Byte synchronous mapping of DS1/T1 (SONET, SDH)"},
457     {19, "VC-11 in VC-12 (SDH)"},
458     {22, "DS1 SF Asynchronous (SONET)"},
459     {23, "DS1 ESF Asynchronous (SONET)"},
460     {24, "DS3 M23 Asynchronous (SONET)"},
461     {25, "DS3 C-Bit Parity Asynchronous (SONET)"},
462     {26, "VT/LOVC (SONET, SDH)"},
463     {27, "STS SPE/HOVC (SONET, SDH)"},
464     {28, "POS - No Scrambling, 16 bit CRC (SONET, SDH)"},
465     {29, "POS - No Scrambling, 32 bit CRC (SONET, SDH)"},
466     {30, "POS - Scrambling, 16 bit CRC (SONET, SDH)"},
467     {31, "POS - Scrambling, 32 bit CRC (SONET, SDH)"},
468     {32, "ATM Mapping (SONET, SDH)"},
469     {33, "Ethernet (SDH, Lambda, Fiber)"},
470     {34, "SDH (Lambda, Fiber)"},
471     {35, "SONET (Lambda, Fiber)"},
472     {36, "Digital Wrapper (Lambda, Fiber)"},
473     {37, "Lambda (Fiber)"},
474     {38, "ETSI PDH (SDH)"},
475     {39, "ANSI PDH (SONET, SDH)"},
476     {40, "Link Access Protocol SDH: LAPS - X.85 and X.86 (SONET, SDH)"},
477     {41, "FDDI (SONET, SDH, Lambda, Fiber)"},
478     {42, "DQDB: ETSI ETS 300 216 (SONET, SDH)"},
479     {43, "FiberChannel-3 Services (FiberChannel)"},
480     { 0, NULL },
481 };
482
483 static const value_string gmpls_sonet_signal_type_str[] = {
484     { 1, "VT1.5 SPE / VC-11"},
485     { 2, "VT2 SPE / VC-12"}, 
486     { 3, "VT3 SPE"},
487     { 4, "VT6 SPE / VC-2"},
488     { 5, "STS-1 SPE / VC-3"},
489     { 6, "STS-3c SPE / VC-4"},
490     { 7, "STS-1 / STM-0"},
491     { 8, "STS-3 / STM-1"},
492     { 9, "STS-12 / STM-4"},
493     {10, "STS-48 / STM-16"},
494     {11, "STS-192 / STM-64"},
495     {12, "STS-768 / STM-256"},
496
497     /* Extended non-SONET signal types */
498     {13, "VTG / TUG-2"},
499     {14, "TUG-3"},
500     {15, "STSG-3 / AUG-1"},
501     {16, "STSG-12  / AUG-4"},
502     {17, "STSG-48  / AUG-16"},
503     {18, "STSG-192 / AUG-64"},
504     {19, "STSG-768 / AUG-256"},
505 };
506
507 static const value_string ouni_guni_diversity_str[] = {
508     {1, "Node Diverse"},
509     {2, "Link Diverse"},
510     {3, "Shared-Risk Link Group Diverse"},
511     {4, "Shared Path"},
512 };
513
514 /* -------------------- Stuff for MPLS/TE objects -------------------- */
515
516 static const value_string proto_vals[] = { {IP_PROTO_ICMP, "ICMP"},
517                                            {IP_PROTO_IGMP, "IGMP"},
518                                            {IP_PROTO_TCP,  "TCP" },
519                                            {IP_PROTO_UDP,  "UDP" },
520                                            {IP_PROTO_OSPF, "OSPF"},
521                                            {0,             NULL  } };
522
523 /* Filter keys */
524 enum rsvp_filter_keys {
525
526     /* Message types */
527     RSVPF_MSG,          /* Message type */
528     /* Shorthand for message types */
529     RSVPF_PATH,
530     RSVPF_RESV,
531     RSVPF_PATHERR,
532     RSVPF_RESVERR,
533     RSVPF_PATHTEAR,
534     RSVPF_RESVTEAR,
535     RSVPF_RCONFIRM,
536     RSVPF_JUNK_MSG8,
537     RSVPF_JUNK_MSG9,
538     RSVPF_RTEARCONFIRM,
539     RSVPF_JUNK11,
540     RSVPF_BUNDLE,
541     RSVPF_ACK,
542     RSVPF_JUNK14,
543     RSVPF_SREFRESH,
544     RSVPF_JUNK16,
545     RSVPF_JUNK17,
546     RSVPF_JUNK18,
547     RSVPF_JUNK19,
548     RSVPF_HELLO,
549     /* Does the message contain an object of this type? */
550     RSVPF_OBJECT,
551     /* Object present shorthands */
552     RSVPF_SESSION,
553     RSVPF_DUMMY_1,
554     RSVPF_HOP,
555     RSVPF_INTEGRITY,
556     RSVPF_TIME_VALUES,
557     RSVPF_ERROR,
558     RSVPF_SCOPE,
559     RSVPF_STYLE,
560     RSVPF_FLOWSPEC,
561     RSVPF_FILTER_SPEC,
562     RSVPF_SENDER,
563     RSVPF_TSPEC,
564     RSVPF_ADSPEC,
565     RSVPF_POLICY,
566     RSVPF_CONFIRM,
567     RSVPF_LABEL,
568     RSVPF_DUMMY_2,
569     RSVPF_DUMMY_3,
570     RSVPF_LABEL_REQUEST,
571     RSVPF_EXPLICIT_ROUTE,
572     RSVPF_RECORD_ROUTE,
573     RSVPF_HELLO_OBJ,
574     RSVPF_MESSAGE_ID,
575     RSVPF_MESSAGE_ID_ACK,
576     RSVPF_MESSAGE_ID_LIST,
577     RSVPF_RECOVERY_LABEL,
578     RSVPF_UPSTREAM_LABEL,
579     RSVPF_LABEL_SET,
580     RSVPF_PROTECTION,
581
582     RSVPF_SUGGESTED_LABEL,
583     RSVPF_ACCEPTABLE_LABEL_SET,
584     RSVPF_RESTART_CAP,
585
586     RSVPF_SESSION_ATTRIBUTE,
587     RSVPF_DCLASS,
588     RSVPF_LSP_TUNNEL_IF_ID,
589     RSVPF_NOTIFY_REQUEST,
590     RSVPF_ADMIN_STATUS,
591     RSVPF_GENERALIZED_UNI,
592     RSVPF_UNKNOWN_OBJ, 
593
594     /* Session object */
595     RSVPF_SESSION_IP,
596     RSVPF_SESSION_PROTO,
597     RSVPF_SESSION_PORT,
598     RSVPF_SESSION_TUNNEL_ID,
599     RSVPF_SESSION_EXT_TUNNEL_ID,
600
601     /* Sender template */
602     RSVPF_SENDER_IP,
603     RSVPF_SENDER_PORT,
604     RSVPF_SENDER_LSP_ID,
605
606     /* Sentinel */
607     RSVPF_MAX
608 };
609
610 static int rsvp_filter[RSVPF_MAX];
611
612 static hf_register_info rsvpf_info[] = {
613
614     /* Message type number */
615     {&rsvp_filter[RSVPF_MSG], 
616      { "Message Type", "rsvp.msg", FT_UINT8, BASE_DEC, VALS(message_type_vals), 0x0,
617         "", HFILL }},
618
619     /* Message type shorthands */
620     {&rsvp_filter[RSVPF_PATH], 
621      { "Path Message", "rsvp.path", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
622         "", HFILL }},
623
624     {&rsvp_filter[RSVPF_HELLO], 
625      { "HELLO Message", "rsvp.hello", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
626         "", HFILL }},
627
628     {&rsvp_filter[RSVPF_RESV], 
629      { "Resv Message", "rsvp.resv", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
630         "", HFILL }},
631
632     {&rsvp_filter[RSVPF_PATHERR], 
633      { "Path Error Message", "rsvp.perr", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
634         "", HFILL }},
635
636     {&rsvp_filter[RSVPF_RESVERR], 
637      { "Resv Error Message", "rsvp.rerr", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
638         "", HFILL }},
639
640     {&rsvp_filter[RSVPF_PATHTEAR], 
641      { "Path Tear Message", "rsvp.ptear", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
642         "", HFILL }},
643
644     {&rsvp_filter[RSVPF_RESVTEAR], 
645      { "Resv Tear Message", "rsvp.rtear", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
646         "", HFILL }},
647
648     {&rsvp_filter[RSVPF_RCONFIRM], 
649      { "Resv Confirm Message", "rsvp.resvconf", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
650         "", HFILL }},
651
652     {&rsvp_filter[RSVPF_RTEARCONFIRM], 
653      { "Resv Tear Confirm Message", "rsvp.rtearconf", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
654         "", HFILL }},
655
656     /* Object class */
657     {&rsvp_filter[RSVPF_OBJECT], 
658      { "Object class", "rsvp.object", FT_UINT8, BASE_DEC, VALS(rsvp_class_vals), 0x0,
659         "", HFILL }},
660
661     /* Object present shorthands */
662     {&rsvp_filter[RSVPF_SESSION], 
663      { "SESSION", "rsvp.session", FT_NONE, BASE_NONE, NULL, 0x0,
664         "", HFILL }},
665
666     {&rsvp_filter[RSVPF_HOP], 
667      { "HOP", "rsvp.hop", FT_NONE, BASE_NONE, NULL, 0x0,
668         "", HFILL }},
669
670     {&rsvp_filter[RSVPF_HELLO_OBJ], 
671      { "HELLO Request/Ack", "rsvp.hello_obj", FT_NONE, BASE_NONE, NULL, 0x0,
672         "", HFILL }},
673
674     {&rsvp_filter[RSVPF_INTEGRITY], 
675      { "INTEGRITY", "rsvp.integrity", FT_NONE, BASE_NONE, NULL, 0x0,
676         "", HFILL }},
677
678     {&rsvp_filter[RSVPF_TIME_VALUES], 
679      { "TIME VALUES", "rsvp.time", FT_NONE, BASE_NONE, NULL, 0x0,
680         "", HFILL }},
681
682     {&rsvp_filter[RSVPF_ERROR], 
683      { "ERROR", "rsvp.error", FT_NONE, BASE_NONE, NULL, 0x0,
684         "", HFILL }},
685
686     {&rsvp_filter[RSVPF_SCOPE], 
687      { "SCOPE", "rsvp.scope", FT_NONE, BASE_NONE, NULL, 0x0,
688         "", HFILL }},
689
690     {&rsvp_filter[RSVPF_STYLE], 
691      { "STYLE", "rsvp.style", FT_NONE, BASE_NONE, NULL, 0x0,
692         "", HFILL }},
693
694     {&rsvp_filter[RSVPF_FLOWSPEC], 
695      { "FLOWSPEC", "rsvp.flowspec", FT_NONE, BASE_NONE, NULL, 0x0,
696         "", HFILL }},
697
698     {&rsvp_filter[RSVPF_FILTER_SPEC], 
699      { "FILTERSPEC", "rsvp.filter", FT_NONE, BASE_NONE, NULL, 0x0,
700         "", HFILL }},
701
702     {&rsvp_filter[RSVPF_SENDER], 
703      { "SENDER TEMPLATE", "rsvp.sender", FT_NONE, BASE_NONE, NULL, 0x0,
704         "", HFILL }},
705
706     {&rsvp_filter[RSVPF_TSPEC], 
707      { "SENDER TSPEC", "rsvp.tspec", FT_NONE, BASE_NONE, NULL, 0x0,
708         "", HFILL }},
709
710     {&rsvp_filter[RSVPF_ADSPEC], 
711      { "ADSPEC", "rsvp.adspec", FT_NONE, BASE_NONE, NULL, 0x0,
712         "", HFILL }},
713
714     {&rsvp_filter[RSVPF_POLICY], 
715      { "POLICY", "rsvp.policy", FT_NONE, BASE_NONE, NULL, 0x0,
716         "", HFILL }},
717
718     {&rsvp_filter[RSVPF_CONFIRM], 
719      { "CONFIRM", "rsvp.confirm", FT_NONE, BASE_NONE, NULL, 0x0,
720         "", HFILL }},
721
722     {&rsvp_filter[RSVPF_LABEL], 
723      { "LABEL", "rsvp.label", FT_NONE, BASE_NONE, NULL, 0x0,
724         "", HFILL }},
725
726     {&rsvp_filter[RSVPF_RECOVERY_LABEL], 
727      { "RECOVERY LABEL", "rsvp.recovery_label", FT_NONE, BASE_NONE, NULL, 0x0,
728         "", HFILL }},
729
730     {&rsvp_filter[RSVPF_UPSTREAM_LABEL], 
731      { "UPSTREAM LABEL", "rsvp.upstream_label", FT_NONE, BASE_NONE, NULL, 0x0,
732         "", HFILL }},
733
734     {&rsvp_filter[RSVPF_SUGGESTED_LABEL], 
735      { "SUGGESTED LABEL", "rsvp.suggested_label", FT_NONE, BASE_NONE, NULL, 0x0,
736         "", HFILL }},
737
738     {&rsvp_filter[RSVPF_LABEL_SET], 
739      { "RESTRICTED LABEL SET", "rsvp.label_set", FT_NONE, BASE_NONE, NULL, 0x0,
740         "", HFILL }},
741
742     {&rsvp_filter[RSVPF_ACCEPTABLE_LABEL_SET], 
743      { "ACCEPTABLE LABEL SET", "rsvp.acceptable_label_set", FT_NONE, BASE_NONE, NULL, 0x0,
744         "", HFILL }},
745
746     {&rsvp_filter[RSVPF_PROTECTION], 
747      { "PROTECTION", "rsvp.protection", FT_NONE, BASE_NONE, NULL, 0x0,
748         "", HFILL }},
749
750     {&rsvp_filter[RSVPF_RESTART_CAP], 
751      { "RESTART CAPABILITY", "rsvp.restart", FT_NONE, BASE_NONE, NULL, 0x0,
752         "", HFILL }},
753
754     {&rsvp_filter[RSVPF_LABEL_REQUEST], 
755      { "LABEL REQUEST", "rsvp.label_request", FT_NONE, BASE_NONE, NULL, 0x0,
756         "", HFILL }},
757
758     {&rsvp_filter[RSVPF_SESSION_ATTRIBUTE], 
759      { "SESSION ATTRIBUTE", "rsvp.session_attribute", FT_NONE, BASE_NONE, NULL, 0x0,
760         "", HFILL }},
761
762     {&rsvp_filter[RSVPF_EXPLICIT_ROUTE], 
763      { "EXPLICIT ROUTE", "rsvp.explicit_route", FT_NONE, BASE_NONE, NULL, 0x0,
764         "", HFILL }},
765
766     {&rsvp_filter[RSVPF_RECORD_ROUTE], 
767      { "RECORD ROUTE", "rsvp.record_route", FT_NONE, BASE_NONE, NULL, 0x0,
768         "", HFILL }},
769
770     {&rsvp_filter[RSVPF_MESSAGE_ID], 
771      { "MESSAGE-ID", "rsvp.msgid", FT_NONE, BASE_NONE, NULL, 0x0,
772         "", HFILL }},
773
774     {&rsvp_filter[RSVPF_MESSAGE_ID_ACK], 
775      { "MESSAGE-ID ACK", "rsvp.ack", FT_NONE, BASE_NONE, NULL, 0x0,
776         "", HFILL }},
777
778     {&rsvp_filter[RSVPF_MESSAGE_ID_LIST], 
779      { "MESSAGE-ID LIST", "rsvp.msgid_list", FT_NONE, BASE_NONE, NULL, 0x0,
780         "", HFILL }},
781
782     {&rsvp_filter[RSVPF_HELLO_OBJ], 
783      { "HELLO", "rsvp.hello", FT_NONE, BASE_NONE, NULL, 0x0,
784         "", HFILL }},
785
786     {&rsvp_filter[RSVPF_DCLASS], 
787      { "DCLASS", "rsvp.dclass", FT_NONE, BASE_NONE, NULL, 0x0,
788         "", HFILL }},
789
790     {&rsvp_filter[RSVPF_LSP_TUNNEL_IF_ID], 
791      { "LSP INTERFACE-ID", "rsvp.lsp_tunnel_if_id", FT_NONE, BASE_NONE, NULL, 0x0,
792         "", HFILL }},
793
794     {&rsvp_filter[RSVPF_ADMIN_STATUS], 
795      { "ADMIN STATUS", "rsvp.admin_status", FT_NONE, BASE_NONE, NULL, 0x0,
796         "", HFILL }},
797
798     {&rsvp_filter[RSVPF_NOTIFY_REQUEST], 
799      { "NOTIFY REQUEST", "rsvp.notify_request", FT_NONE, BASE_NONE, NULL, 0x0,
800         "", HFILL }},
801
802     {&rsvp_filter[RSVPF_GENERALIZED_UNI], 
803      { "GENERALIZED UNI", "rsvp.generalized_uni", FT_NONE, BASE_NONE, NULL, 0x0,
804         "", HFILL }},
805
806     {&rsvp_filter[RSVPF_UNKNOWN_OBJ], 
807      { "Unknown object", "rsvp.obj_unknown", FT_NONE, BASE_NONE, NULL, 0x0,
808         "", HFILL }},
809
810     /* Session fields */
811     {&rsvp_filter[RSVPF_SESSION_IP], 
812      { "Destination address", "rsvp.session.ip", FT_IPv4, BASE_NONE, NULL, 0x0,
813         "", HFILL }},
814
815     {&rsvp_filter[RSVPF_SESSION_PORT], 
816      { "Port number", "rsvp.session.port", FT_UINT16, BASE_DEC, NULL, 0x0,
817         "", HFILL }},
818
819     {&rsvp_filter[RSVPF_SESSION_PROTO], 
820      { "Protocol", "rsvp.session.proto", FT_UINT8, BASE_DEC, VALS(proto_vals), 0x0,
821         "", HFILL }},
822
823     {&rsvp_filter[RSVPF_SESSION_TUNNEL_ID], 
824      { "Tunnel ID", "rsvp.session.tunnel_id", FT_UINT16, BASE_DEC, NULL, 0x0,
825         "", HFILL }},
826
827     {&rsvp_filter[RSVPF_SESSION_EXT_TUNNEL_ID], 
828      { "Extended tunnel ID", "rsvp.session.ext_tunnel_id", FT_UINT32, BASE_DEC, NULL, 0x0,
829         "", HFILL }},
830
831     /* Sender template/Filterspec fields */
832     {&rsvp_filter[RSVPF_SENDER_IP], 
833      { "Sender IPv4 address", "rsvp.sender.ip", FT_IPv4, BASE_NONE, NULL, 0x0,
834         "", HFILL }},
835
836     {&rsvp_filter[RSVPF_SENDER_PORT], 
837      { "Sender port number", "rsvp.sender.port", FT_UINT16, BASE_DEC, NULL, 0x0,
838        "", HFILL }},
839
840     {&rsvp_filter[RSVPF_SENDER_LSP_ID], 
841      { "Sender LSP ID", "rsvp.sender.lsp_id", FT_UINT16, BASE_DEC, NULL, 0x0,
842         "", HFILL }}
843 };
844
845 static inline int rsvp_class_to_filter_num(int classnum)
846 {
847     switch(classnum) {
848     case RSVP_CLASS_SESSION :
849     case RSVP_CLASS_HOP :
850     case RSVP_CLASS_INTEGRITY :
851     case RSVP_CLASS_TIME_VALUES :
852     case RSVP_CLASS_ERROR :
853     case RSVP_CLASS_SCOPE :
854     case RSVP_CLASS_STYLE :
855     case RSVP_CLASS_FLOWSPEC :
856     case RSVP_CLASS_FILTER_SPEC :
857     case RSVP_CLASS_SENDER_TEMPLATE :
858     case RSVP_CLASS_SENDER_TSPEC :
859     case RSVP_CLASS_ADSPEC :
860     case RSVP_CLASS_POLICY :
861     case RSVP_CLASS_CONFIRM :
862     case RSVP_CLASS_LABEL :
863     case RSVP_CLASS_LABEL_REQUEST :
864     case RSVP_CLASS_HELLO :
865     case RSVP_CLASS_EXPLICIT_ROUTE :
866     case RSVP_CLASS_RECORD_ROUTE :
867     case RSVP_CLASS_MESSAGE_ID :
868     case RSVP_CLASS_MESSAGE_ID_ACK :
869     case RSVP_CLASS_MESSAGE_ID_LIST :    
870         return classnum + RSVPF_OBJECT;
871         break;
872
873     case RSVP_CLASS_RECOVERY_LABEL :
874     case RSVP_CLASS_UPSTREAM_LABEL :
875     case RSVP_CLASS_LABEL_SET :
876     case RSVP_CLASS_PROTECTION :
877         return RSVPF_RECOVERY_LABEL + (classnum - RSVP_CLASS_RECOVERY_LABEL);
878
879     case RSVP_CLASS_SUGGESTED_LABEL :
880     case RSVP_CLASS_ACCEPTABLE_LABEL_SET :
881     case RSVP_CLASS_RESTART_CAP :
882         return RSVPF_SUGGESTED_LABEL + (classnum - RSVP_CLASS_SUGGESTED_LABEL);
883
884     case RSVP_CLASS_NOTIFY_REQUEST :
885         return RSVPF_NOTIFY_REQUEST;
886     case RSVP_CLASS_ADMIN_STATUS :
887         return RSVPF_ADMIN_STATUS;
888
889     case RSVP_CLASS_SESSION_ATTRIBUTE :
890         return RSVPF_SESSION_ATTRIBUTE;
891     case RSVP_CLASS_GENERALIZED_UNI :
892         return RSVPF_GENERALIZED_UNI;
893     case RSVP_CLASS_DCLASS :
894         return RSVPF_DCLASS;
895     case RSVP_CLASS_LSP_TUNNEL_IF_ID :
896         return RSVPF_LSP_TUNNEL_IF_ID;
897         
898     default:
899         return RSVPF_UNKNOWN_OBJ;
900     }
901 }
902
903 static void
904 find_rsvp_session_tempfilt(tvbuff_t *tvb, int hdr_offset, int *session_offp, int *tempfilt_offp)
905 {
906     int s_off = 0, t_off = 0;
907     int len, off;
908
909     if (!tvb)
910         goto done;
911
912     len = tvb_get_ntohs(tvb, hdr_offset+6) + hdr_offset;
913     off = hdr_offset + 8;
914     for (off = hdr_offset + 8; off < len; off += tvb_get_ntohs(tvb, off)) {
915         switch(tvb_get_guint8(tvb, off+2)) {
916         case RSVP_CLASS_SESSION:
917             s_off = off;
918             break;
919         case RSVP_CLASS_SENDER_TEMPLATE:
920         case RSVP_CLASS_FILTER_SPEC:
921             t_off = off;
922             break;
923         default:
924             break;
925         }
926     }
927
928  done:
929     if (session_offp) *session_offp = s_off;
930     if (tempfilt_offp) *tempfilt_offp = t_off;
931 }
932
933 static char *summary_session (tvbuff_t *tvb, int offset)
934 {
935     static char buf[80];
936
937     switch(tvb_get_guint8(tvb, offset+3)) {
938     case RSVP_SESSION_TYPE_IPV4:
939         snprintf(buf, 80, "SESSION: IPv4, Destination %s, Protocol %d, Port %d. ", 
940                  ip_to_str(tvb_get_ptr(tvb, offset+4, 4)), 
941                  tvb_get_guint8(tvb, offset+8),
942                  tvb_get_ntohs(tvb, offset+10));
943         break;
944     case RSVP_SESSION_TYPE_IPV4_LSP:
945         snprintf(buf, 80, "SESSION: IPv4-LSP, Destination %s, Tunnel ID %d, Ext ID %0x. ", 
946                  ip_to_str(tvb_get_ptr(tvb, offset+4, 4)), 
947                  tvb_get_ntohs(tvb, offset+10),
948                  tvb_get_ntohl(tvb, offset+12));
949         break;
950     case RSVP_SESSION_TYPE_IPV4_UNI:
951         snprintf(buf, 80, "SESSION: IPv4-UNI, Destination %s, Tunnel ID %d, Ext Address %s. ", 
952                  ip_to_str(tvb_get_ptr(tvb, offset+4, 4)), 
953                  tvb_get_ntohs(tvb, offset+10),
954                  ip_to_str(tvb_get_ptr(tvb, offset+12, 4)));
955         break;
956     default:
957         snprintf(buf, 80, "SESSION: Type %d. ", tvb_get_guint8(tvb, offset+3));
958     }
959
960     return buf;
961 }
962
963 static char *summary_template (tvbuff_t *tvb, int offset)
964 {
965     static char buf[80];
966     char *objtype;
967
968     if (tvb_get_guint8(tvb, offset+2) == RSVP_CLASS_FILTER_SPEC)
969         objtype = "FILTERSPEC";
970     else
971         objtype = "SENDER TEMPLATE";
972
973     switch(tvb_get_guint8(tvb, offset+3)) {
974     case 1:
975         snprintf(buf, 80, "%s: IPv4, Sender %s, Port %d. ", objtype,
976                  ip_to_str(tvb_get_ptr(tvb, offset+4, 4)), 
977                  tvb_get_ntohs(tvb, offset+10));
978         break;
979     case 7:
980         snprintf(buf, 80, "%s: IPv4-LSP, Tunnel Source: %s, LSP ID: %d. ", objtype,
981                  ip_to_str(tvb_get_ptr(tvb, offset+4, 4)), 
982                  tvb_get_ntohs(tvb, offset+10));
983         break;
984     default:
985         snprintf(buf, 80, "%s: Type %d. ", objtype, tvb_get_guint8(tvb, offset+3));
986     }
987
988     return buf;
989 }
990
991 /*------------------------------------------------------------------------------
992  * SESSION
993  *------------------------------------------------------------------------------*/
994 static void 
995 dissect_rsvp_session (proto_tree *ti, tvbuff_t *tvb, 
996                       int offset, int obj_length,
997                       int class, int type, 
998                       char *type_str)
999 {
1000     int offset2 = offset + 4;
1001     proto_tree *rsvp_object_tree;
1002
1003     rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_session);
1004     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
1005                         "Length: %u", obj_length);
1006     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
1007                         "Class number: %u - %s", 
1008                         class, type_str);
1009     proto_item_set_text(ti, summary_session(tvb, offset));
1010     
1011     switch(type) {
1012     case RSVP_SESSION_TYPE_IPV4:
1013         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
1014                             "C-type: 1 - IPv4");
1015         proto_tree_add_item(rsvp_object_tree,
1016                             rsvp_filter[RSVPF_SESSION_IP],
1017                             tvb, offset2, 4, FALSE);
1018         
1019         proto_tree_add_item(rsvp_object_tree,
1020                             rsvp_filter[RSVPF_SESSION_PROTO], tvb, 
1021                             offset2+4, 1, FALSE);
1022         proto_tree_add_text(rsvp_object_tree, tvb, offset2+5, 1,
1023                             "Flags: %x",
1024                             tvb_get_guint8(tvb, offset2+5));
1025         proto_tree_add_item(rsvp_object_tree,
1026                             rsvp_filter[RSVPF_SESSION_PORT], tvb, 
1027                             offset2+6, 2, FALSE);
1028         break;
1029         
1030     case RSVP_SESSION_TYPE_IPV6:
1031         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1032                             "C-type: 2 - IPv6");
1033         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16,
1034                             "Destination address: %s", 
1035                             ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
1036         proto_tree_add_text(rsvp_object_tree, tvb, offset2+16, 1,
1037                             "Protocol: %u",
1038                             tvb_get_guint8(tvb, offset2+16));
1039         proto_tree_add_text(rsvp_object_tree, tvb, offset2+17, 1,
1040                             "Flags: %x",
1041                             tvb_get_guint8(tvb, offset2+17));
1042         proto_tree_add_text(rsvp_object_tree, tvb, offset2+18, 2,
1043                             "Destination port: %u", 
1044                             tvb_get_ntohs(tvb, offset2+18));
1045         break;
1046         
1047     case RSVP_SESSION_TYPE_IPV4_LSP: 
1048         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1049                             "C-type: 7 - IPv4 LSP");
1050         proto_tree_add_item(rsvp_object_tree,
1051                             rsvp_filter[RSVPF_SESSION_IP],
1052                             tvb, offset2, 4, FALSE);
1053         
1054         proto_tree_add_item(rsvp_object_tree,
1055                             rsvp_filter[RSVPF_SESSION_TUNNEL_ID],
1056                             tvb, offset2+6, 2, FALSE);
1057         
1058         proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 4, 
1059                             "Extended Tunnel ID: %u (%s)",
1060                             tvb_get_ntohl(tvb, offset2+8),
1061                             ip_to_str(tvb_get_ptr(tvb, offset2+8, 4)));
1062         proto_tree_add_item_hidden(rsvp_object_tree,
1063                                    rsvp_filter[RSVPF_SESSION_EXT_TUNNEL_ID],
1064                                    tvb, offset2+8, 4, FALSE);
1065         break;
1066
1067     case RSVP_SESSION_TYPE_IPV4_UNI: 
1068         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1069                             "C-type: 9 - IPv4 UNI");
1070         proto_tree_add_item(rsvp_object_tree,
1071                             rsvp_filter[RSVPF_SESSION_IP],
1072                             tvb, offset2, 4, FALSE);
1073
1074         proto_tree_add_item(rsvp_object_tree,
1075                             rsvp_filter[RSVPF_SESSION_TUNNEL_ID],
1076                             tvb, offset2+6, 2, FALSE);
1077
1078         proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 4, 
1079                             "Extended IPv4 Address: %s",
1080                             ip_to_str(tvb_get_ptr(tvb, offset2+8, 4)));
1081         proto_tree_add_item_hidden(rsvp_object_tree,
1082                                    rsvp_filter[RSVPF_SESSION_EXT_TUNNEL_ID],
1083                                    tvb, offset2+8, 4, FALSE);
1084         break;
1085
1086     default: 
1087         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1088                             "C-type: Unknown (%u)",
1089                             type);
1090         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length-4,
1091                             "Data (%d bytes)", obj_length-4);
1092     }
1093 }
1094
1095 /*------------------------------------------------------------------------------
1096  * HOP
1097  *------------------------------------------------------------------------------*/
1098 static void 
1099 dissect_rsvp_hop (proto_tree *ti, tvbuff_t *tvb, 
1100                   int offset, int obj_length,
1101                   int class, int type, 
1102                   char *type_str)
1103 {
1104     int offset2 = offset + 4;
1105     proto_tree *rsvp_object_tree;
1106     proto_tree *rsvp_hop_subtree, *ti2;
1107
1108     rsvp_object_tree= proto_item_add_subtree(ti, ett_rsvp_hop);
1109
1110     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
1111                         "Length: %u", obj_length);
1112     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
1113                         "Class number: %u - %s", 
1114                         class, type_str);
1115     switch(type) {
1116     case 1:
1117         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1118                             "C-type: 1 - IPv4");
1119         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4, 
1120                             "Neighbor address: %s", 
1121                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
1122         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
1123                             "Logical interface: %u", 
1124                             tvb_get_ntohl(tvb, offset2+4));
1125         proto_item_set_text(ti, "HOP: IPv4, %s", 
1126                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
1127         break;
1128
1129     case 2:
1130         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1131                             "C-type: 2 - IPv6");
1132         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16,
1133                             "Neighbor address: %s", 
1134                             ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
1135         proto_tree_add_text(rsvp_object_tree, tvb, offset2+16, 4,
1136                             "Logical interface: 0x%08x", 
1137                             tvb_get_ntohl(tvb, offset2+16));
1138         break;
1139                 
1140     case 3: {
1141         guint16   tlv_off;
1142         guint16   tlv_type;
1143         guint16   tlv_len;
1144         char     *ifindex_name;
1145         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1146                             "C-type: 3 - IPv4 Out-Of-Band");
1147         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4, 
1148                             "Neighbor address: %s", 
1149                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
1150         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
1151                             "Logical interface: %u", 
1152                             tvb_get_ntohl(tvb, offset2+4));
1153
1154         proto_item_set_text(ti, "HOP: Out-of-band. Control IPv4: %s. ", 
1155                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
1156
1157         for (tlv_off = 0; tlv_off < obj_length - 12; ) {
1158             tlv_type = tvb_get_ntohs(tvb, offset2+8+tlv_off);
1159             tlv_len = tvb_get_ntohs(tvb, offset2+8+tlv_off+2);
1160             switch(tlv_type) {
1161             case 1: 
1162                 ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
1163                                           offset2+8+tlv_off, 8,
1164                                           "IPv4 TLV - %s",
1165                                           ip_to_str(tvb_get_ptr(tvb, offset2+8+tlv_off+4, 4)));
1166                 rsvp_hop_subtree = 
1167                     proto_item_add_subtree(ti2, ett_rsvp_hop_subobj); 
1168                 proto_tree_add_text(rsvp_hop_subtree, tvb, offset2+8+tlv_off, 2,
1169                                     "Type: 1 (IPv4)");
1170                 proto_tree_add_text(rsvp_hop_subtree, tvb, offset2+8+tlv_off+2, 2,
1171                                     "Length: %u",
1172                                     tvb_get_ntohs(tvb, offset2+8+tlv_off+2));
1173                 proto_tree_add_text(rsvp_hop_subtree, tvb, offset2+8+tlv_off+4, 4, 
1174                                     "IPv4 address: %s", 
1175                                     ip_to_str(tvb_get_ptr(tvb, offset2+8+tlv_off+4, 4)));
1176                 proto_item_append_text(ti, "Data IPv4: %s. ", 
1177                                     ip_to_str(tvb_get_ptr(tvb, offset2+8+tlv_off+4, 4)));
1178                 break;
1179
1180             case 3: 
1181                 ifindex_name = "";
1182                 goto hop_ifindex;
1183             case 4:
1184                 ifindex_name = " Forward";
1185                 goto hop_ifindex;
1186             case 5:
1187                 ifindex_name = " Reverse";
1188             hop_ifindex:
1189                 ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
1190                                           offset2+8+tlv_off, 12,
1191                                           "Interface-Index%s TLV - %s, %d",
1192                                           ifindex_name,
1193                                           ip_to_str(tvb_get_ptr(tvb, offset2+8+tlv_off+4, 4)),
1194                                           tvb_get_ntohl(tvb, offset2+8+tlv_off+8));
1195                 rsvp_hop_subtree = 
1196                     proto_item_add_subtree(ti2, ett_rsvp_hop_subobj); 
1197                 proto_tree_add_text(rsvp_hop_subtree, tvb, offset2+8+tlv_off, 2,
1198                                     "Type: %d (Interface Index%s)", tlv_type, ifindex_name);
1199                 proto_tree_add_text(rsvp_hop_subtree, tvb, offset2+8+tlv_off+2, 2,
1200                                     "Length: %u",
1201                                     tvb_get_ntohs(tvb, offset2+8+tlv_off+2));
1202                 proto_tree_add_text(rsvp_hop_subtree, tvb, offset2+8+tlv_off+4, 4, 
1203                                     "IPv4 address: %s", 
1204                                     ip_to_str(tvb_get_ptr(tvb, offset2+8+tlv_off+4, 4)));
1205                 proto_tree_add_text(rsvp_hop_subtree, tvb, offset2+8+tlv_off+8, 4, 
1206                                     "Interface-ID: %d", 
1207                                     tvb_get_ntohl(tvb, offset2+8+tlv_off+8));
1208                 proto_item_append_text(ti, "Data If-Index%s: %s, %d. ", ifindex_name, 
1209                                     ip_to_str(tvb_get_ptr(tvb, offset2+8+tlv_off+4, 4)), 
1210                                     tvb_get_ntohl(tvb, offset2+8+tlv_off+8));
1211                 break;
1212
1213             default:
1214                 proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
1215                                     "Logical interface: %u", 
1216                                     tvb_get_ntohl(tvb, offset2+4));
1217             }
1218             tlv_off += tlv_len;
1219         }
1220         break;
1221     }
1222
1223     default:
1224         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1225                             "C-type: Unknown (%u)",
1226                             type);
1227         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
1228                             "Data (%d bytes)", obj_length - 4);
1229     }
1230 }
1231
1232 /*------------------------------------------------------------------------------
1233  * TIME VALUES
1234  *------------------------------------------------------------------------------*/
1235 static void 
1236 dissect_rsvp_time_values (proto_tree *ti, tvbuff_t *tvb, 
1237                           int offset, int obj_length,
1238                           int class, int type, 
1239                           char *type_str)
1240 {
1241     int offset2 = offset + 4;
1242     proto_tree *rsvp_object_tree;
1243
1244     rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_time_values);
1245     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
1246                         "Length: %u", obj_length);
1247     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
1248                         "Class number: %u - %s", 
1249                         class, type_str);
1250     switch(type) {
1251     case 1:
1252         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1253                             "C-type: 1");
1254         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4, 
1255                             "Refresh interval: %u ms (%u seconds)",
1256                             tvb_get_ntohl(tvb, offset2),
1257                             tvb_get_ntohl(tvb, offset2)/1000);
1258         proto_item_set_text(ti, "TIME VALUES: %d ms", 
1259                             tvb_get_ntohl(tvb, offset2));
1260         break;
1261
1262     default: 
1263         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1264                             "C-type: Unknown (%u)",
1265                             type);
1266         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
1267                             "Data (%d bytes)", obj_length - 4);
1268         break;
1269     }
1270 }
1271
1272 /*------------------------------------------------------------------------------
1273  * ERROR 
1274  *------------------------------------------------------------------------------*/
1275 static void 
1276 dissect_rsvp_error (proto_tree *ti, tvbuff_t *tvb, 
1277                     int offset, int obj_length,
1278                     int class, int type, 
1279                     char *type_str)
1280 {
1281     int offset2 = offset + 4;
1282     proto_tree *rsvp_object_tree;
1283
1284     rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_error);
1285     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
1286                         "Length: %u", obj_length);
1287     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
1288                         "Class number: %u - %s", 
1289                         class, type_str);
1290     switch(type) {
1291     case 1: {
1292         guint8 error_code;
1293
1294         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1295                             "C-type: 1 - IPv4");
1296         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4, 
1297                             "Error node: %s",
1298                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
1299         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 1,
1300                             "Flags: 0x%02x",
1301                             tvb_get_guint8(tvb, offset2+4));
1302         error_code = tvb_get_guint8(tvb, offset2+5);
1303         proto_tree_add_text(rsvp_object_tree, tvb, offset2+5, 1,
1304                             "Error code: %u - %s", error_code,
1305                             val_to_str(error_code, rsvp_error_vals, "Unknown (%d)"));
1306         proto_tree_add_text(rsvp_object_tree, tvb, offset2+6, 2,
1307                             "Error value: %u",
1308                             tvb_get_ntohs(tvb, offset2+6));
1309         proto_item_set_text(ti, "ERROR: IPv4, Error code: %s, Value: %d, Error Node: %s", 
1310                             val_to_str(error_code, rsvp_error_vals, "Unknown (%d)"),
1311                             tvb_get_ntohs(tvb, offset2+6),
1312                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
1313         break;
1314     }
1315
1316     case 2: {
1317         guint8 error_code;
1318
1319         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1320                             "C-type: 2 - IPv6");
1321         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16,
1322                             "Error node: %s",
1323                             ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
1324         proto_tree_add_text(rsvp_object_tree, tvb, offset2+16, 1,
1325                             "Flags: 0x%02x",
1326                             tvb_get_guint8(tvb, offset2+16));
1327         error_code = tvb_get_guint8(tvb, offset2+17);
1328         proto_tree_add_text(rsvp_object_tree, tvb, offset2+17, 1,
1329                             "Error code: %u - %s", error_code,
1330                             val_to_str(error_code, rsvp_error_vals, "Unknown"));
1331         proto_tree_add_text(rsvp_object_tree, tvb, offset2+18, 2,
1332                             "Error value: %u",
1333                             tvb_get_ntohs(tvb, offset2+18));
1334         break;
1335     }
1336                 
1337     default:
1338         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1339                             "C-type: Unknown (%u)",
1340                             type);
1341         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
1342                             "Data (%d bytes)", obj_length - 4);
1343     }
1344 }
1345
1346 /*------------------------------------------------------------------------------
1347  * SCOPE
1348  *------------------------------------------------------------------------------*/
1349 static void 
1350 dissect_rsvp_scope (proto_tree *ti, tvbuff_t *tvb, 
1351                     int offset, int obj_length,
1352                     int class, int type, 
1353                     char *type_str)
1354 {
1355     int offset2 = offset + 4;
1356     proto_tree *rsvp_object_tree;
1357     int mylen;
1358
1359     rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_scope);
1360     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
1361                         "Length: %u", obj_length);
1362     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
1363                         "Class number: %u - %s", 
1364                         class, type_str);
1365     mylen = obj_length - 4;
1366     switch(type) {
1367     case 1: {
1368         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1369                             "C-type: 1 - IPv4");
1370         while (mylen > 0) {
1371             proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4, 
1372                                 "IPv4 Address: %s",
1373                                 ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
1374             offset2 += 4;
1375             mylen -= 4;
1376         }
1377         break;
1378     }
1379
1380     case 2: {
1381         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1382                             "C-type: 2 - IPv6");
1383         while (mylen > 0) {
1384             proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16, 
1385                                 "IPv6 Address: %s",
1386                                 ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
1387             offset2 += 16;
1388             mylen -= 16;
1389         }
1390         break;
1391     }
1392                 
1393     default: 
1394         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1395                             "C-type: Unknown (%u)",
1396                             type);
1397         proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
1398                             "Data (%d bytes)", mylen);
1399     }
1400 }
1401
1402 /*------------------------------------------------------------------------------
1403  * STYLE
1404  *------------------------------------------------------------------------------*/
1405 static void 
1406 dissect_rsvp_style (proto_tree *ti, tvbuff_t *tvb, 
1407                     int offset, int obj_length,
1408                     int class, int type, 
1409                     char *type_str)
1410 {
1411     int offset2 = offset + 4;
1412     proto_tree *rsvp_object_tree;
1413
1414     rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_style);
1415     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
1416                         "Length: %u", obj_length);
1417     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
1418                         "Class number: %u - %s", 
1419                         class, type_str);
1420     switch(type) {
1421     case 1: {
1422         guint32 style;
1423
1424         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1425                             "C-type: 1");
1426         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
1427                             "Flags: 0x%02x",
1428                             tvb_get_guint8(tvb, offset2));
1429         style = tvb_get_ntoh24(tvb, offset2+1);
1430         proto_tree_add_text(rsvp_object_tree, tvb, offset2+1,
1431                             3, "Style: 0x%06X - %s", style,
1432                             val_to_str(style, style_vals, "Unknown"));
1433         proto_item_set_text(ti, "STYLE: %s (%d)", 
1434                             val_to_str(style, style_vals, "Unknown"),
1435                             style);
1436         break;
1437     }
1438
1439     default: 
1440         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1441                             "C-type: Unknown (%u)",
1442                             type);
1443         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
1444                             "Data (%d bytes)", obj_length - 4);
1445         break;
1446     }
1447 }
1448
1449 /*------------------------------------------------------------------------------
1450  * CONFIRM
1451  *------------------------------------------------------------------------------*/
1452 static void 
1453 dissect_rsvp_confirm (proto_tree *ti, tvbuff_t *tvb, 
1454                       int offset, int obj_length,
1455                       int class, int type, 
1456                       char *type_str)
1457 {
1458     int offset2 = offset + 4;
1459     proto_tree *rsvp_object_tree;
1460
1461     rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_confirm);
1462     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
1463                         "Length: %u", obj_length);
1464     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
1465                         "Class number: %u - %s", 
1466                         class, type_str);
1467     switch(type) {
1468     case 1: {
1469         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1470                             "C-type: 1 - IPv4");
1471         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4, 
1472                             "Receiver address: %s", 
1473                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
1474         proto_item_set_text(ti, "CONFIRM: Receiver %s", 
1475                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
1476         break;
1477     }
1478
1479     case 2: {
1480         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1481                             "C-type: 2 - IPv6");
1482         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16, 
1483                             "Receiver address: %s", 
1484                             ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
1485         break;
1486     }
1487
1488     default:
1489         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1490                             "C-type: Unknown (%u)",
1491                             type);
1492         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
1493                             "Data (%d bytes)", obj_length - 4);
1494     }
1495 }
1496
1497 /*------------------------------------------------------------------------------
1498  * SENDER TEMPLATE and FILTERSPEC
1499  *------------------------------------------------------------------------------*/
1500 static void 
1501 dissect_rsvp_template_filter (proto_tree *ti, tvbuff_t *tvb, 
1502                               int offset, int obj_length,
1503                               int class, int type, 
1504                               char *type_str)
1505 {
1506     int offset2 = offset + 4;
1507     proto_tree *rsvp_object_tree;
1508
1509     switch(class) {
1510     case RSVP_CLASS_SENDER_TEMPLATE :
1511         rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_sender_template);
1512         proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
1513                             "Length: %u", obj_length);
1514         proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
1515                             "Class number: %u - %s", 
1516                             class, type_str);
1517         break;
1518
1519     default:
1520     case RSVP_CLASS_FILTER_SPEC :
1521         rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_filter_spec);
1522         proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
1523                             "Length: %u", obj_length);
1524         proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
1525                             "Class number: %u - %s", 
1526                             class, type_str);
1527         break;
1528     }
1529
1530      proto_item_set_text(ti, summary_template(tvb, offset));
1531      switch(type) {
1532      case 1: 
1533          proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1534                              "C-type: 1 - IPv4");
1535          proto_tree_add_item(rsvp_object_tree,
1536                              rsvp_filter[RSVPF_SENDER_IP],
1537                              tvb, offset2, 4, FALSE);
1538          proto_tree_add_item(rsvp_object_tree,
1539                              rsvp_filter[RSVPF_SENDER_PORT],
1540                              tvb, offset2+6, 2, FALSE);
1541          break;
1542
1543      case 2: 
1544          proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1545                              "C-type: 2 - IPv6");
1546          proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16, 
1547                              "Source address: %s", 
1548                              ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
1549          proto_tree_add_text(rsvp_object_tree, tvb, offset2+18, 2,
1550                              "Source port: %u",
1551                              tvb_get_ntohs(tvb, offset2+18));
1552          break;
1553                 
1554      case 7: 
1555          proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1556                              "C-type: 7 - IPv4 LSP");
1557          proto_tree_add_item(rsvp_object_tree,
1558                              rsvp_filter[RSVPF_SENDER_IP],
1559                              tvb, offset2, 4, FALSE);
1560          proto_tree_add_item(rsvp_object_tree,
1561                              rsvp_filter[RSVPF_SENDER_LSP_ID],
1562                              tvb, offset2+6, 2, FALSE);
1563          break;
1564
1565      default: 
1566          proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1567                              "C-type: Unknown (%u)",
1568                              type);
1569          proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
1570                              "Data (%d bytes)", obj_length - 4);
1571      }
1572 }
1573
1574 /*------------------------------------------------------------------------------
1575  * SENDER TSPEC
1576  *------------------------------------------------------------------------------*/
1577 static void 
1578 dissect_rsvp_tspec (proto_tree *ti, tvbuff_t *tvb, 
1579                     int offset, int obj_length,
1580                     int class, int type, 
1581                     char *type_str)
1582 {
1583     int offset2 = offset + 4;
1584     proto_tree *rsvp_object_tree;
1585     int mylen;
1586     proto_tree *tspec_tree, *ti2;
1587     guint8 signal_type;
1588
1589     rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_sender_tspec);
1590     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
1591                         "Length: %u", obj_length);
1592     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
1593                         "Class number: %u - %s", 
1594                         class, type_str);
1595     mylen = obj_length - 4;
1596
1597     switch(type) {
1598     case 2: 
1599         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1600                             "C-type: 1 - Integrated Services");
1601         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1, 
1602                             "Message format version: %u", 
1603                             tvb_get_guint8(tvb, offset2)>>4);
1604         proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2, 
1605                             "Data length: %u words, not including header", 
1606                             tvb_get_ntohs(tvb, offset2+2));
1607         
1608         mylen -= 4;
1609         offset2 += 4;
1610         
1611         proto_item_set_text(ti, "SENDER TSPEC: IntServ: ");
1612         
1613         while (mylen > 0) {
1614             guint8 service_num;
1615             guint8 param_id;
1616             guint16 param_len;
1617             guint16 param_len_processed;
1618             guint16 length;
1619             
1620             service_num = tvb_get_guint8(tvb, offset2);
1621             proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1, 
1622                                 "Service header: %u - %s", 
1623                                 service_num,
1624                                 val_to_str(service_num, qos_vals, "Unknown"));
1625             length = tvb_get_ntohs(tvb, offset2+2);
1626             proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2, 
1627                                 "Length of service %u data: %u words, " 
1628                                 "not including header", 
1629                                 service_num, length);
1630             
1631             mylen -= 4;
1632             offset2 += 4;
1633             
1634             /* Process all known service headers as a set of parameters */
1635             param_len_processed = 0;
1636             while (param_len_processed < length) {
1637                 param_id = tvb_get_guint8(tvb, offset2);
1638                 param_len = tvb_get_ntohs(tvb, offset2+2) + 1;
1639                 switch(param_id) {
1640                 case 127: 
1641                     /* Token Bucket */
1642                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
1643                                               offset2, param_len*4, 
1644                                               "Token Bucket TSpec: ");
1645                     tspec_tree = proto_item_add_subtree(ti2, ett_rsvp_sender_tspec_subtree);
1646
1647                     proto_tree_add_text(tspec_tree, tvb, offset2, 1, 
1648                                         "Parameter %u - %s", 
1649                                         param_id,
1650                                         val_to_str(param_id, svc_vals, "Unknown"));
1651                     proto_tree_add_text(tspec_tree, tvb, offset2+1, 1,
1652                                         "Parameter %u flags: 0x%02x",
1653                                         param_id,
1654                                         tvb_get_guint8(tvb, offset2+1));
1655                     proto_tree_add_text(tspec_tree, tvb, offset2+2, 2,
1656                                         "Parameter %u data length: %u words, " 
1657                                         "not including header",
1658                                         param_id,
1659                                         tvb_get_ntohs(tvb, offset2+2));
1660                     proto_tree_add_text(tspec_tree, tvb, offset2+4, 4,
1661                                         "Token bucket rate: %.10g", 
1662                                         tvb_get_ntohieee_float(tvb, offset2+4));
1663                     proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
1664                                         "Token bucket size: %.10g", 
1665                                         tvb_get_ntohieee_float(tvb, offset2+8));
1666                     proto_tree_add_text(tspec_tree, tvb, offset2+12, 4,
1667                                         "Peak data rate: %.10g", 
1668                                         tvb_get_ntohieee_float(tvb, offset2+12));
1669                     proto_tree_add_text(tspec_tree, tvb, offset2+16, 4,
1670                                         "Minimum policed unit [m]: %u", 
1671                                         tvb_get_ntohl(tvb, offset2+16));
1672                     proto_tree_add_text(tspec_tree, tvb, offset2+20, 4,
1673                                         "Maximum packet size [M]: %u", 
1674                                         tvb_get_ntohl(tvb, offset2+20));
1675                     proto_item_append_text(ti, "Token Bucket, %.10g bytes/sec. ", 
1676                                            tvb_get_ntohieee_float(tvb, offset2+4));
1677                     proto_item_append_text(ti2, "Rate=%.10g Burst=%.10g Peak=%.10g m=%u M=%u", 
1678                                            tvb_get_ntohieee_float(tvb, offset2+4),
1679                                            tvb_get_ntohieee_float(tvb, offset2+8),
1680                                            tvb_get_ntohieee_float(tvb, offset2+12),
1681                                            tvb_get_ntohl(tvb, offset2+16),
1682                                            tvb_get_ntohl(tvb, offset2+20));
1683                     break;
1684
1685                 case 128:
1686                     /* Null Service (RFC2997) */
1687                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
1688                                               offset2, param_len*4, 
1689                                               "Null Service TSpec: ");
1690                     tspec_tree = proto_item_add_subtree(ti2, ett_rsvp_sender_tspec_subtree);
1691                                 
1692                     proto_tree_add_text(tspec_tree, tvb, offset2, 1, 
1693                                         "Parameter %u - %s", 
1694                                         param_id,
1695                                         val_to_str(param_id, svc_vals, "Unknown"));
1696                     proto_tree_add_text(tspec_tree, tvb, offset2+1, 1,
1697                                         "Parameter %u flags: %x", 
1698                                         param_id,
1699                                         tvb_get_guint8(tvb, offset2+1));
1700                     proto_tree_add_text(tspec_tree, tvb, offset2+2, 2,
1701                                         "Parameter %u data length: %u words, " 
1702                                         "not including header",
1703                                         param_id,
1704                                         tvb_get_ntohs(tvb, offset2+2));
1705                     proto_tree_add_text(tspec_tree, tvb, offset2+4, 4,
1706                                         "Maximum packet size [M]: %u", 
1707                                         tvb_get_ntohl(tvb, offset2+4));
1708                     proto_item_append_text(ti, "Null Service. M=%u", 
1709                                            tvb_get_ntohl(tvb, offset2+4));
1710                     proto_item_append_text(ti2, "Max pkt size=%u", 
1711                                            tvb_get_ntohl(tvb, offset2+4));
1712                     break;
1713
1714                 case 126:
1715                     /* Compression hint (RFC3006) */
1716                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
1717                                               offset2, param_len*4, 
1718                                               "Compression Hint: ");
1719                     tspec_tree = proto_item_add_subtree(ti2, ett_rsvp_sender_tspec_subtree);
1720                                 
1721                     proto_tree_add_text(tspec_tree, tvb, offset2, 1, 
1722                                         "Parameter %u - %s", 
1723                                         param_id,
1724                                         val_to_str(param_id, svc_vals, "Unknown"));
1725                     proto_tree_add_text(tspec_tree, tvb, offset2+1, 1,
1726                                         "Parameter %u flags: %x", 
1727                                         param_id,
1728                                         tvb_get_guint8(tvb, offset2+1));
1729                     proto_tree_add_text(tspec_tree, tvb, offset2+2, 2,
1730                                         "Parameter %u data length: %u words, " 
1731                                         "not including header",
1732                                         param_id,
1733                                         tvb_get_ntohs(tvb, offset2+2));
1734                     proto_tree_add_text(tspec_tree, tvb, offset2+4, 4,
1735                                         "Hint: %u", 
1736                                         tvb_get_ntohl(tvb, offset2+4));
1737                     proto_tree_add_text(tspec_tree, tvb, offset2+4, 4,
1738                                         "Compression Factor: %u", 
1739                                         tvb_get_ntohl(tvb, offset2+8));
1740                     proto_item_append_text(ti, "Compression Hint. Hint=%u, Factor=%u", 
1741                                            tvb_get_ntohl(tvb, offset2+4),
1742                                            tvb_get_ntohl(tvb, offset2+8));
1743                     proto_item_append_text(ti2, "Hint=%u, Factor=%u", 
1744                                            tvb_get_ntohl(tvb, offset2+4),
1745                                            tvb_get_ntohl(tvb, offset2+8));
1746                     break;
1747
1748                 default: 
1749                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, param_len*4, 
1750                                         "Unknown parameter %d, %d words", 
1751                                         param_id, param_len);
1752                     break;
1753                 }
1754                 param_len_processed += param_len;
1755                 offset2 += param_len*4;
1756             }
1757             mylen -= length*4;
1758         }
1759         break;
1760
1761     case 4: /* SONET/SDH Tspec */
1762         proto_item_set_text(ti, "SENDER TSPEC: SONET/SDH: ");
1763         
1764         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1765                             "C-type: 4 - SONET/SDH");
1766         signal_type = tvb_get_guint8(tvb, offset2);
1767         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1, 
1768                             "Signal Type: %d - %s", signal_type,
1769                             val_to_str(signal_type, 
1770                                        gmpls_sonet_signal_type_str, "Unknown"));
1771         ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2+1, 1, 
1772                             "Requested Concatenation (RCC): %d", tvb_get_guint8(tvb, offset2+1));
1773         tspec_tree = proto_item_add_subtree(ti2, ett_rsvp_sender_tspec_subtree);
1774         proto_tree_add_text(tspec_tree, tvb, offset2+1, 1,
1775                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+1), 0x01, 8, 
1776                                                     "Standard contiguous concatenation", 
1777                                                     "No standard contiguous concatenation"));
1778         proto_tree_add_text(tspec_tree, tvb, offset2+1, 1,
1779                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+1), 0x02, 8, 
1780                                                     "Arbitrary contiguous concatenation", 
1781                                                     "No arbitrary contiguous concatenation"));
1782         proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2, 
1783                             "Number of Contiguous Components (NCC): %d", tvb_get_ntohs(tvb, offset2+2));
1784         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 2, 
1785                             "Number of Virtual Components (NVC): %d", tvb_get_ntohs(tvb, offset2+4));
1786         proto_tree_add_text(rsvp_object_tree, tvb, offset2+6, 2, 
1787                             "Multiplier (MT): %d", tvb_get_ntohs(tvb, offset2+6));
1788         ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 4, 
1789                                   "Transparency (T): 0x%0x", tvb_get_ntohl(tvb, offset2+8));
1790         tspec_tree = proto_item_add_subtree(ti2, ett_rsvp_sender_tspec_subtree);
1791         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
1792                             decode_boolean_bitfield(tvb_get_ntohl(tvb, offset2+8), 0x0001, 32, 
1793                                                     "Section/Regenerator Section layer transparency", 
1794                                                     "No Section/Regenerator Section layer transparency"));
1795         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
1796                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0002, 32, 
1797                                                     "Line/Multiplex Section layer transparency", 
1798                                                     "No Line/Multiplex Section layer transparency"));
1799         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
1800                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0004, 32, 
1801                                                     "J0 transparency", 
1802                                                     "No J0 transparency"));
1803         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
1804                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0008, 32, 
1805                                                     "SOH/RSOH DCC transparency", 
1806                                                     "No SOH/RSOH DCC transparency"));
1807         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
1808                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0010, 32, 
1809                                                     "LOH/MSOH DCC transparency", 
1810                                                     "No LOH/MSOH DCC transparency"));
1811         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
1812                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0020, 32, 
1813                                                     "LOH/MSOH Extended DCC transparency", 
1814                                                     "No LOH/MSOH Extended DCC transparency"));
1815         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
1816                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0040, 32, 
1817                                                     "K1/K2 transparency", 
1818                                                     "No K1/K2 transparency"));
1819         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
1820                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0080, 32, 
1821                                                     "E1 transparency", 
1822                                                     "No E1 transparency"));
1823         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
1824                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0100, 32, 
1825                                                     "F1 transparency", 
1826                                                     "No F1 transparency"));
1827         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
1828                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0200, 32, 
1829                                                     "E2 transparency", 
1830                                                     "No E2 transparency"));
1831         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
1832                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0400, 32, 
1833                                                     "B1 transparency", 
1834                                                     "No B1 transparency"));
1835         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
1836                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0800, 32, 
1837                                                     "B2 transparency", 
1838                                                     "No B2 transparency"));
1839         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
1840                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x1000, 32, 
1841                                                     "M0 transparency", 
1842                                                     "No M0 transparency"));
1843         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
1844                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x2000, 32, 
1845                                                     "M1 transparency", 
1846                                                     "No M1 transparency"));
1847         proto_tree_add_text(rsvp_object_tree, tvb, offset2+12, 4, 
1848                             "Profile (P): %d", tvb_get_ntohl(tvb, offset2+12));
1849
1850         proto_item_append_text(ti, "Signal [%s], RCC %d, NCC %d, NVC %d, MT %d, Transparency %d, Profile %d", 
1851                                val_to_str(signal_type, gmpls_sonet_signal_type_str, "Unknown"),
1852                                tvb_get_guint8(tvb, offset2+1), tvb_get_ntohs(tvb, offset2+2),
1853                                tvb_get_ntohs(tvb, offset2+4), tvb_get_ntohs(tvb, offset2+6),
1854                                tvb_get_ntohl(tvb, offset2+8), tvb_get_ntohl(tvb, offset2+12));
1855         break;
1856         
1857     default: /* Unknown TSpec */
1858         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1859                             "C-type: Unknown (%u)",
1860                             type);
1861         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
1862                             "Data (%d bytes)", obj_length - 4);
1863         break;
1864         
1865     }
1866 }
1867
1868 /*------------------------------------------------------------------------------
1869  * FLOWSPEC
1870  *------------------------------------------------------------------------------*/
1871 static void 
1872 dissect_rsvp_flowspec (proto_tree *ti, tvbuff_t *tvb, 
1873                        int offset, int obj_length,
1874                        int class, int type, 
1875                        char *type_str)
1876 {
1877     int offset2 = offset + 4;
1878     proto_tree *rsvp_object_tree;
1879     int mylen, signal_type;
1880     proto_tree *flowspec_tree, *ti2;
1881
1882     rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_flowspec);
1883     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
1884                         "Length: %u", obj_length);
1885     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
1886                         "Class number: %u - %s", 
1887                         class, type_str);
1888     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1889                         "C-type: %u", type);
1890     mylen = obj_length - 4;
1891
1892     switch(type) {
1893
1894     case 2:
1895         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1, 
1896                             "Message format version: %u", 
1897                             tvb_get_guint8(tvb, offset2)>>4);
1898         proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2, 
1899                             "Data length: %u words, not including header", 
1900                             tvb_get_ntohs(tvb, offset2+2));
1901
1902         proto_item_set_text(ti, "FLOWSPEC: ");
1903
1904         mylen -= 4;
1905         offset2+= 4;
1906         while (mylen > 0) {
1907             guint8 service_num;
1908             guint16 length;
1909             guint8 param_id;
1910             guint16 param_len;
1911             guint16 param_len_processed;
1912
1913             service_num = tvb_get_guint8(tvb, offset2);
1914             proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1, 
1915                                 "Service header: %u - %s", 
1916                                 service_num,
1917                                 val_to_str(service_num, intsrv_services_str, "Unknown"));
1918             length = tvb_get_ntohs(tvb, offset2+2);
1919             proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2, 
1920                                 "Length of service %u data: %u words, " 
1921                                 "not including header", 
1922                                 service_num,
1923                                 length);
1924
1925             mylen -= 4;
1926             offset2 += 4;
1927
1928             proto_item_append_text(ti, "%s: ", 
1929                                    val_to_str(service_num, intsrv_services_str, 
1930                                               "Unknown (%d)"));
1931
1932             /* Process all known service headers as a set of parameters */
1933             param_len_processed = 0;
1934             while (param_len_processed < length) {
1935                 param_id = tvb_get_guint8(tvb, offset2);
1936                 param_len = tvb_get_ntohs(tvb, offset2+2) + 1;
1937                 switch(param_id) {
1938                 case 127: 
1939                     /* Token Bucket */
1940                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
1941                                               offset2, param_len*4, 
1942                                               "Token Bucket: ");
1943                     flowspec_tree = proto_item_add_subtree(ti2, ett_rsvp_flowspec_subtree);
1944
1945                     proto_tree_add_text(flowspec_tree, tvb, offset2, 1, 
1946                                         "Parameter %u - %s", 
1947                                         param_id,
1948                                         val_to_str(param_id, svc_vals, "Unknown"));
1949                     proto_tree_add_text(flowspec_tree, tvb, offset2+1, 1,
1950                                         "Parameter %u flags: 0x%02x",
1951                                         param_id,
1952                                         tvb_get_guint8(tvb, offset2+1));
1953                     proto_tree_add_text(flowspec_tree, tvb, offset2+2, 2,
1954                                         "Parameter %u data length: %u words, " 
1955                                         "not including header",
1956                                         param_id,
1957                                         tvb_get_ntohs(tvb, offset2+2));
1958                     proto_tree_add_text(flowspec_tree, tvb, offset2+4, 4,
1959                                         "Token bucket rate: %.10g", 
1960                                         tvb_get_ntohieee_float(tvb, offset2+4));
1961                     proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
1962                                         "Token bucket size: %.10g", 
1963                                         tvb_get_ntohieee_float(tvb, offset2+8));
1964                     proto_tree_add_text(flowspec_tree, tvb, offset2+12, 4,
1965                                         "Peak data rate: %.10g", 
1966                                         tvb_get_ntohieee_float(tvb, offset2+12));
1967                     proto_tree_add_text(flowspec_tree, tvb, offset2+16, 4,
1968                                         "Minimum policed unit [m]: %u", 
1969                                         tvb_get_ntohl(tvb, offset2+16));
1970                     proto_tree_add_text(flowspec_tree, tvb, offset2+20, 4,
1971                                         "Maximum packet size [M]: %u", 
1972                                         tvb_get_ntohl(tvb, offset2+20));
1973                     proto_item_append_text(ti, "Token Bucket, %.10g bytes/sec. ", 
1974                                            tvb_get_ntohieee_float(tvb, offset2+4));
1975                     proto_item_append_text(ti2, "Rate=%.10g Burst=%.10g Peak=%.10g m=%u M=%u", 
1976                                            tvb_get_ntohieee_float(tvb, offset2+4),
1977                                            tvb_get_ntohieee_float(tvb, offset2+8),
1978                                            tvb_get_ntohieee_float(tvb, offset2+12),
1979                                            tvb_get_ntohl(tvb, offset2+16),
1980                                            tvb_get_ntohl(tvb, offset2+20));
1981                     break;
1982
1983                 case 130:
1984                     /* Guaranteed-rate RSpec */
1985                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
1986                                               offset2, param_len*4, 
1987                                               "Guaranteed-Rate RSpec: ");
1988                     flowspec_tree = proto_item_add_subtree(ti2, ett_rsvp_flowspec_subtree);
1989                     proto_tree_add_text(flowspec_tree, tvb, offset2, 1,
1990                                         "Parameter %u - %s", 
1991                                         param_id,
1992                                         val_to_str(param_id, svc_vals, "Unknown"));
1993                     proto_tree_add_text(flowspec_tree, tvb, offset2+1, 1, 
1994                                         "Parameter %u flags: %x", 
1995                                         param_id,
1996                                         tvb_get_guint8(tvb, offset2+1));
1997                     proto_tree_add_text(flowspec_tree, tvb, offset2+2, 2,
1998                                         "Parameter %u data length: %u words, " 
1999                                         "not including header",
2000                                         param_id,
2001                                         tvb_get_ntohs(tvb, offset2+2));
2002                             
2003                     proto_tree_add_text(flowspec_tree, tvb, offset2+4, 4,
2004                                         "Rate: %.10g", 
2005                                         tvb_get_ntohieee_float(tvb, offset2+4));
2006                     proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
2007                                         "Slack term: %u", 
2008                                         tvb_get_ntohl(tvb, offset2+8));
2009                     proto_item_append_text(ti, "RSpec, %.10g bytes/sec. ", 
2010                                            tvb_get_ntohieee_float(tvb, offset2+4));
2011                     proto_item_append_text(ti2, "R=%.10g, s=%u", 
2012                                            tvb_get_ntohieee_float(tvb, offset2+4),
2013                                            tvb_get_ntohl(tvb, offset2+8));
2014                     break;
2015
2016                 case 128:
2017                     /* Null Service (RFC2997) */
2018                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
2019                                               offset2, param_len*4, 
2020                                               "Null Service Flowspec: ");
2021                     flowspec_tree = proto_item_add_subtree(ti2, ett_rsvp_flowspec_subtree);
2022                                 
2023                     proto_tree_add_text(flowspec_tree, tvb, offset2, 1, 
2024                                         "Parameter %u - %s", 
2025                                         param_id,
2026                                         val_to_str(param_id, svc_vals, "Unknown"));
2027                     proto_tree_add_text(flowspec_tree, tvb, offset2+1, 1,
2028                                         "Parameter %u flags: %x", 
2029                                         param_id,
2030                                         tvb_get_guint8(tvb, offset2+1));
2031                     proto_tree_add_text(flowspec_tree, tvb, offset2+2, 2,
2032                                         "Parameter %u data length: %u words, " 
2033                                         "not including header",
2034                                         param_id,
2035                                         tvb_get_ntohs(tvb, offset2+2));
2036                     proto_tree_add_text(flowspec_tree, tvb, offset2+4, 4,
2037                                         "Maximum packet size [M]: %u", 
2038                                         tvb_get_ntohl(tvb, offset2+4));
2039                     proto_item_append_text(ti, "Null Service. M=%u", 
2040                                            tvb_get_ntohl(tvb, offset2+4));
2041                     proto_item_append_text(ti2, "Max pkt size=%u", 
2042                                            tvb_get_ntohl(tvb, offset2+4));
2043                     break;
2044
2045                 default: 
2046                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, param_len*4, 
2047                                         "Unknown parameter %d, %d words", 
2048                                         param_id, param_len);
2049                     break;
2050                 }
2051                 param_len_processed += param_len;
2052                 offset2 += param_len * 4;
2053             }
2054
2055             /* offset2 += length*4; */
2056             mylen -= length*4;
2057         }
2058         break;
2059
2060     case 4:
2061         proto_item_set_text(ti, "FLOWSPEC: SONET/SDH: ");
2062         
2063         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
2064                             "C-type: 4 - SONET/SDH");
2065         signal_type = tvb_get_guint8(tvb, offset2);
2066         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1, 
2067                             "Signal Type: %d - %s", signal_type, 
2068                             val_to_str(signal_type, 
2069                                        gmpls_sonet_signal_type_str, "Unknown"));
2070         ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2+1, 1, 
2071                                   "Requested Concatenation (RCC): %d", tvb_get_guint8(tvb, offset2+1));
2072         flowspec_tree = proto_item_add_subtree(ti2, ett_rsvp_flowspec_subtree);
2073         proto_tree_add_text(flowspec_tree, tvb, offset2+1, 1,
2074                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+1), 0x01, 8, 
2075                                                     "Standard contiguous concatenation", 
2076                                                     "No standard contiguous concatenation"));
2077         proto_tree_add_text(flowspec_tree, tvb, offset2+1, 1,
2078                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+1), 0x02, 8, 
2079                                                     "Arbitrary contiguous concatenation", 
2080                                                     "No arbitrary contiguous concatenation"));
2081         proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2, 
2082                             "Number of Contiguous Components (NCC): %d", tvb_get_ntohs(tvb, offset2+2));
2083         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 2, 
2084                             "Number of Virtual Components (NVC): %d", tvb_get_ntohs(tvb, offset2+4));
2085         proto_tree_add_text(rsvp_object_tree, tvb, offset2+6, 2, 
2086                             "Multiplier (MT): %d", tvb_get_ntohs(tvb, offset2+6));
2087         ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 4, 
2088                                   "Transparency (T): 0x%0x", tvb_get_ntohl(tvb, offset2+8));
2089         flowspec_tree = proto_item_add_subtree(ti2, ett_rsvp_flowspec_subtree);
2090         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
2091                             decode_boolean_bitfield(tvb_get_ntohl(tvb, offset2+8), 0x0001, 32, 
2092                                                     "Section/Regenerator Section layer transparency", 
2093                                                     "No Section/Regenerator Section layer transparency"));
2094         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
2095                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0002, 32, 
2096                                                     "Line/Multiplex Section layer transparency", 
2097                                                     "No Line/Multiplex Section layer transparency"));
2098         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
2099                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0004, 32, 
2100                                                     "J0 transparency", 
2101                                                     "No J0 transparency"));
2102         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
2103                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0008, 32, 
2104                                                     "SOH/RSOH DCC transparency", 
2105                                                     "No SOH/RSOH DCC transparency"));
2106         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
2107                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0010, 32, 
2108                                                     "LOH/MSOH DCC transparency", 
2109                                                     "No LOH/MSOH DCC transparency"));
2110         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
2111                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0020, 32, 
2112                                                     "LOH/MSOH Extended DCC transparency", 
2113                                                     "No LOH/MSOH Extended DCC transparency"));
2114         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
2115                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0040, 32, 
2116                                                     "K1/K2 transparency", 
2117                                                     "No K1/K2 transparency"));
2118         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
2119                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0080, 32, 
2120                                                     "E1 transparency", 
2121                                                     "No E1 transparency"));
2122         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
2123                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0100, 32, 
2124                                                     "F1 transparency", 
2125                                                     "No F1 transparency"));
2126         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
2127                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0200, 32, 
2128                                                     "E2 transparency", 
2129                                                     "No E2 transparency"));
2130         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
2131                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0400, 32, 
2132                                                     "B1 transparency", 
2133                                                     "No B1 transparency"));
2134         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
2135                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0800, 32, 
2136                                                     "B2 transparency", 
2137                                                     "No B2 transparency"));
2138         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
2139                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x1000, 32, 
2140                                                     "M0 transparency", 
2141                                                     "No M0 transparency"));
2142         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
2143                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x2000, 32, 
2144                                                     "M1 transparency", 
2145                                                     "No M1 transparency"));
2146         proto_tree_add_text(rsvp_object_tree, tvb, offset2+12, 4, 
2147                             "Profile (P): %d", tvb_get_ntohl(tvb, offset2+12));
2148
2149         proto_item_append_text(ti, "Signal [%s], RCC %d, NCC %d, NVC %d, MT %d, Transparency %d, Profile %d", 
2150                                val_to_str(signal_type, gmpls_sonet_signal_type_str, "Unknown"),
2151                                tvb_get_guint8(tvb, offset2+1), tvb_get_ntohs(tvb, offset2+2),
2152                                tvb_get_ntohs(tvb, offset2+4), tvb_get_ntohs(tvb, offset2+6),
2153                                tvb_get_ntohl(tvb, offset2+8), tvb_get_ntohl(tvb, offset2+12));
2154         break;
2155         
2156     default:
2157         break;
2158     }
2159
2160
2161 }
2162
2163 /*------------------------------------------------------------------------------
2164  * ADSPEC
2165  *------------------------------------------------------------------------------*/
2166 static void 
2167 dissect_rsvp_adspec (proto_tree *ti, tvbuff_t *tvb, 
2168                      int offset, int obj_length,
2169                      int class, int type, 
2170                      char *type_str)
2171 {
2172     int offset2 = offset + 4;
2173     proto_tree *rsvp_object_tree;
2174     int mylen, i;
2175     proto_tree *adspec_tree;    
2176
2177     rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_adspec);
2178     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
2179                         "Length: %u", obj_length);
2180     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
2181                         "Class number: %u - %s", 
2182                         class, type_str);
2183     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
2184                         "C-type: %u", type);
2185     mylen = obj_length - 4;
2186
2187     proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
2188                         "Message format version: %u", 
2189                         tvb_get_guint8(tvb, offset2)>>4);
2190     proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
2191                         "Data length: %u words, not including header", 
2192                         tvb_get_ntohs(tvb, offset2+2));
2193     mylen -= 4;
2194     offset2 += 4;
2195     while (mylen > 0) {
2196         guint8 service_num;
2197         guint8 break_bit;
2198         guint16 length;
2199         char *str;
2200
2201         service_num = tvb_get_guint8(tvb, offset2);
2202         str = val_to_str(service_num, intsrv_services_str, "Unknown");
2203         break_bit = tvb_get_guint8(tvb, offset2+1);
2204         length = tvb_get_ntohs(tvb, offset2+2);
2205         ti = proto_tree_add_text(rsvp_object_tree, tvb, offset2, 
2206                                  (length+1)*4,
2207                                  str);
2208         adspec_tree = proto_item_add_subtree(ti,
2209                                              ett_rsvp_adspec_subtree);
2210         proto_tree_add_text(adspec_tree, tvb, offset2, 1,
2211                             "Service header %u - %s",
2212                             service_num, str);
2213         proto_tree_add_text(adspec_tree, tvb, offset2+1, 1,
2214                             (break_bit&0x80)?
2215                             "Break bit set":"Break bit not set");
2216         proto_tree_add_text(adspec_tree, tvb, offset2+2, 2, 
2217                             "Data length: %u words, not including header", 
2218                             length);
2219         mylen -= 4;
2220         offset2 += 4;
2221         i = length*4;
2222         while (i > 0) {
2223             guint8 id;
2224             guint16 phdr_length;
2225
2226             id = tvb_get_guint8(tvb, offset2);
2227             phdr_length = tvb_get_ntohs(tvb, offset2+2);
2228             str = match_strval(id, adspec_params);
2229             if (str) {
2230                 switch(id) {
2231                 case 4:
2232                 case 8:
2233                 case 10:
2234                 case 133:
2235                 case 134:
2236                 case 135:
2237                 case 136:
2238                     /* 32-bit unsigned integer */
2239                     proto_tree_add_text(adspec_tree, tvb, offset2,
2240                                         (phdr_length+1)<<2,
2241                                         "%s - %u (type %u, length %u)",
2242                                         str,
2243                                         tvb_get_ntohl(tvb, offset2+4),
2244                                         id, phdr_length);
2245                     break;
2246                                 
2247                 case 6:
2248                     /* IEEE float */
2249                     proto_tree_add_text(adspec_tree, tvb, offset2,
2250                                         (phdr_length+1)<<2,
2251                                         "%s - %.10g (type %u, length %u)",
2252                                         str,
2253                                         tvb_get_ntohieee_float(tvb, offset2+4),
2254                                         id, phdr_length);
2255                     break;
2256                 default: 
2257                     proto_tree_add_text(adspec_tree, tvb, offset2, 
2258                                         (phdr_length+1)<<2,
2259                                         "%s (type %u, length %u)",
2260                                         str,
2261                                         id, phdr_length);
2262                 }
2263             } else {
2264                 proto_tree_add_text(adspec_tree, tvb, offset2, 
2265                                     (phdr_length+1)<<2,
2266                                     "Unknown (type %u, length %u)",
2267                                     id, phdr_length);
2268             }
2269             offset2 += (phdr_length+1)<<2;
2270             i -= (phdr_length+1)<<2;
2271             mylen -= (phdr_length+1)<<2;
2272         }
2273     }
2274 }
2275
2276 /*------------------------------------------------------------------------------
2277  * INTEGRITY
2278  *------------------------------------------------------------------------------*/
2279 static void 
2280 dissect_rsvp_integrity (proto_tree *ti, tvbuff_t *tvb, 
2281                         int offset, int obj_length,
2282                         int class, int type, 
2283                         char *type_str)
2284 {
2285     int offset2 = offset + 4;
2286     proto_tree *rsvp_object_tree;
2287     proto_tree *ti2, *rsvp_integ_flags_tree;
2288     int flags;
2289     guint64 sequence_number;
2290
2291     rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_integrity);
2292     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
2293                         "Length: %u", obj_length);
2294     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
2295                         "Class number: %u - %s", 
2296                         class, type_str);
2297     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
2298                         "C-type: %u", type);
2299     flags = tvb_get_guint8(tvb, offset2);
2300     ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1, 
2301                               "Flags: 0x%02x", flags);
2302     rsvp_integ_flags_tree = proto_item_add_subtree(ti2, ett_rsvp_integrity_flags);
2303     proto_tree_add_text(rsvp_integ_flags_tree, tvb, offset2, 1,
2304         decode_boolean_bitfield(flags, 0x01, 8, "Handshake capable", "Handshake not capable"));
2305     proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 6, 
2306                         "Key Identifier: %s", tvb_bytes_to_str(tvb, offset2+2, 6));
2307     sequence_number = tvb_get_ntohl(tvb, offset2+8);
2308     sequence_number <<= 32;
2309     sequence_number = tvb_get_ntohl(tvb, offset2+12);
2310     proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 8, 
2311                         "Sequence Number: %llu", sequence_number);
2312     proto_tree_add_text(rsvp_object_tree, tvb, offset2+16, obj_length - 20, 
2313                         "Hash: %s", tvb_bytes_to_str(tvb, offset2+16, obj_length - 20));
2314 }
2315
2316 /*------------------------------------------------------------------------------
2317  * POLICY
2318  *------------------------------------------------------------------------------*/
2319 static void 
2320 dissect_rsvp_policy (proto_tree *ti, tvbuff_t *tvb, 
2321                      int offset, int obj_length,
2322                      int class, int type, 
2323                      char *type_str)
2324 {
2325     int offset2 = offset + 4;
2326     proto_tree *rsvp_object_tree;
2327
2328     rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_policy);
2329     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
2330                         "Length: %u", obj_length);
2331     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
2332                         "Class number: %u - %s", 
2333                         class, type_str);
2334     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
2335                         "C-type: %u", type);
2336     proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
2337                         "Data (%d bytes)", obj_length - 4);
2338 }
2339
2340 /*------------------------------------------------------------------------------
2341  * LABEL_REQUEST
2342  *------------------------------------------------------------------------------*/
2343 static void 
2344 dissect_rsvp_label_request (proto_tree *ti, tvbuff_t *tvb, 
2345                             int offset, int obj_length,
2346                             int class, int type, 
2347                             char *type_str)
2348 {
2349     int offset2 = offset + 4;
2350     proto_tree *rsvp_object_tree;
2351
2352     rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_label_request);
2353     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
2354                         "Length: %u", obj_length);
2355     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
2356                         "Class number: %u - %s", 
2357                         class, type_str);
2358     switch(type) {
2359     case 1: {
2360         unsigned short l3pid = tvb_get_ntohs(tvb, offset2+2);
2361         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
2362                             "C-type: 1");
2363         proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
2364                             "L3PID: %s (0x%04x)",
2365                             val_to_str(l3pid, etype_vals, "Unknown"),
2366                             l3pid);
2367         proto_item_set_text(ti, "LABEL REQUEST: %s (0x%04x)",
2368                             val_to_str(l3pid, etype_vals, "Unknown"),
2369                             l3pid);
2370         break;
2371     }
2372
2373     case 4: {
2374         unsigned short l3pid = tvb_get_ntohs(tvb, offset2+2);
2375         unsigned char  lsp_enc = tvb_get_guint8(tvb,offset2);
2376         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
2377                             "C-type: 4 (Generalized Label Request)");
2378         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
2379                             "LSP Encoding Type: %s",
2380                             val_to_str(lsp_enc, gmpls_lsp_enc_str, "Unknown (%d)"));
2381         proto_tree_add_text(rsvp_object_tree, tvb, offset2+1, 1,
2382                             "Switching Type: %s",
2383                             val_to_str(tvb_get_guint8(tvb,offset2+1), 
2384                                        gmpls_switching_type_str, "Unknown (%d)"));
2385         proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
2386                             "G-PID: %s (0x%0x)",
2387                             val_to_str(l3pid, gmpls_gpid_str, 
2388                                        val_to_str(l3pid, etype_vals, 
2389                                                   "Unknown G-PID(0x%04x)")),
2390                             l3pid);
2391         proto_item_set_text(ti, "LABEL REQUEST: Generalized: LSP Encoding=%s, "
2392                             "Switching Type=%s, G-PID=%s ",
2393                             val_to_str(lsp_enc, gmpls_lsp_enc_str, "Unknown (%d)"),
2394                             val_to_str(tvb_get_guint8(tvb,offset2+1), 
2395                                        gmpls_switching_type_str, "Unknown (%d)"),
2396                             val_to_str(l3pid, gmpls_gpid_str, 
2397                                        val_to_str(l3pid, etype_vals, 
2398                                                   "Unknown (0x%04x)")));
2399         break;
2400     }
2401
2402     default: {
2403         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
2404                             "C-type: Unknown (%u)",
2405                             type);
2406         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
2407                             "Data (%d bytes)", obj_length - 4);
2408         break;
2409     }
2410     }
2411 }
2412
2413 /*------------------------------------------------------------------------------
2414  * LABEL
2415  *------------------------------------------------------------------------------*/
2416 static void 
2417 dissect_rsvp_label (proto_tree *ti, tvbuff_t *tvb, 
2418                     int offset, int obj_length,
2419                     int class, int type, 
2420                     char *type_str)
2421 {
2422     int offset2 = offset + 4;
2423     proto_tree *rsvp_object_tree;
2424     int mylen, i;
2425     char *name;
2426
2427     name = (class==RSVP_CLASS_SUGGESTED_LABEL ? "SUGGESTED LABEL":
2428             (class==RSVP_CLASS_UPSTREAM_LABEL ? "UPSTREAM LABEL":
2429              "LABEL"));
2430     rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_label);
2431     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
2432                         "Length: %u", obj_length);
2433     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
2434                         "Class number: %u - %s", 
2435                         class, type_str);
2436     mylen = obj_length - 4;
2437     switch(type) {
2438     case 1: 
2439         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
2440                             "C-type: 1 (Packet Label)");
2441         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
2442                             "Label: %u", 
2443                             tvb_get_ntohl(tvb, offset2));
2444         proto_item_set_text(ti, "%s: %d", name,
2445                             tvb_get_ntohl(tvb, offset2));
2446         break;
2447
2448     case 2: 
2449         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
2450                             "C-type: 2 (Generalized Label)");
2451         proto_item_set_text(ti, "%s: Generalized: ", name);
2452         for (i = 0; i < mylen; i += 4) {
2453             proto_tree_add_text(rsvp_object_tree, tvb, offset2+i, 4,
2454                                 "Generalized Label: %u", 
2455                                 tvb_get_ntohl(tvb, offset2+i));
2456             if (i < 16) {
2457                 proto_item_append_text(ti, "%d%s", 
2458                                        tvb_get_ntohl(tvb, offset2+i),
2459                                        i+4<mylen?", ":"");
2460             } else if (i == 16) {
2461                 proto_item_append_text(ti, "...");
2462             }                       
2463         }
2464         break;
2465
2466     default: 
2467         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
2468                             "C-type: Unknown (%u)",
2469                             type);
2470         proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
2471                             "Data (%d bytes)", mylen);
2472         break;
2473     }
2474 }
2475
2476 /*------------------------------------------------------------------------------
2477  * SESSION ATTRIBUTE
2478  *------------------------------------------------------------------------------*/
2479 static void 
2480 dissect_rsvp_session_attribute (proto_tree *ti, tvbuff_t *tvb, 
2481                                 int offset, int obj_length,
2482                                 int class, int type, 
2483                                 char *type_str)
2484 {
2485     int offset2 = offset + 4;
2486     proto_tree *rsvp_object_tree;
2487     guint8 flags;
2488     guint8 name_len;
2489     proto_tree *ti2, *rsvp_sa_flags_tree;
2490
2491     rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_session_attribute);
2492     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
2493                         "Length: %u", obj_length);
2494     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
2495                         "Class number: %u - %s", 
2496                         class, type_str);
2497     switch(type) {
2498     case 7:
2499
2500         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
2501                             "C-type: 7 - IPv4 LSP");
2502         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
2503                             "Setup priority: %u",
2504                             tvb_get_guint8(tvb, offset2));
2505         proto_tree_add_text(rsvp_object_tree, tvb, offset2+1, 1,
2506                             "Hold priority: %u",
2507                             tvb_get_guint8(tvb, offset2+1));
2508         flags = tvb_get_guint8(tvb, offset2+2);
2509         ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 1,
2510                                   "Flags: 0x%02x", flags);
2511         rsvp_sa_flags_tree = proto_item_add_subtree(ti2, 
2512                                                     ett_rsvp_session_attribute_flags);
2513         proto_tree_add_text(rsvp_sa_flags_tree, tvb, offset2+2, 1,
2514                             decode_boolean_bitfield(flags, 0x01, 8,
2515                                                     "Local protection desired",
2516                                                     "Local protection not desired"));
2517         proto_tree_add_text(rsvp_sa_flags_tree, tvb, offset2+2, 1,
2518                             decode_boolean_bitfield(flags, 0x02, 8,
2519                                                     "Merging permitted",
2520                                                     "Merging not permitted"));
2521         proto_tree_add_text(rsvp_sa_flags_tree, tvb, offset2+2, 1,
2522                             decode_boolean_bitfield(flags, 0x04, 8,
2523                                                     "Ingress node may reroute",
2524                                                     "Ingress node may not reroute"));
2525                     
2526         name_len = tvb_get_guint8(tvb, offset2+3);
2527         proto_tree_add_text(rsvp_object_tree, tvb, offset2+3, 1,
2528                             "Name length: %u", name_len);
2529         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, name_len,
2530                             "Name: %.*s",
2531                             name_len,
2532                             tvb_get_ptr(tvb, offset2+4, name_len));
2533
2534         proto_item_set_text(ti, "SESSION ATTRIBUTE: SetupPrio %d, HoldPrio %d, %s%s%s [%s]",
2535                             tvb_get_guint8(tvb, offset2), 
2536                             tvb_get_guint8(tvb, offset2+1),
2537                             flags &0x01 ? "Local Protection, " : "",
2538                             flags &0x02 ? "Merging, " : "",
2539                             flags &0x04 ? "May Reroute, " : "",
2540                             name_len ? (char*)tvb_format_text(tvb, offset2+4, name_len) : "");
2541         break;
2542
2543     default: 
2544         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
2545                             "C-type: Unknown (%u)",
2546                             type);
2547         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
2548                             "Data (%d bytes)", obj_length - 4);
2549         break;
2550     }
2551 }
2552
2553 /*------------------------------------------------------------------------------
2554  * EXPLICIT ROUTE OBJECT
2555  *------------------------------------------------------------------------------*/
2556 static void 
2557 dissect_rsvp_explicit_route (proto_tree *ti, tvbuff_t *tvb, 
2558                              int offset, int obj_length,
2559                              int class, int type, 
2560                              char *type_str)
2561 {
2562     int offset2 = offset + 4;
2563     proto_tree *rsvp_object_tree;
2564     int mylen, i, j, k, l;
2565     proto_tree *ti2, *rsvp_ero_subtree;
2566
2567     rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_explicit_route);
2568     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
2569                         "Length: %u", obj_length);
2570     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
2571                         "Class number: %u - %s", 
2572                         class, type_str);
2573     mylen = obj_length - 4;
2574     switch(type) {
2575     case 1: {
2576         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
2577                             "C-type: 1");
2578         proto_item_set_text(ti, "EXPLICIT ROUTE: ");
2579         for (i=1, l = 0; l < mylen; i++) {
2580             j = tvb_get_guint8(tvb, offset2+l) & 0x7f;
2581             switch(j) {
2582             case 1: /* IPv4 */
2583                 k = tvb_get_guint8(tvb, offset2+l) & 0x80;
2584                 ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
2585                                           offset2+l, 8,
2586                                           "IPv4 Subobject - %s, %s",
2587                                           ip_to_str(tvb_get_ptr(tvb, offset2+l+2, 4)),
2588                                           k ? "Loose" : "Strict");
2589                 rsvp_ero_subtree = 
2590                     proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); 
2591                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
2592                                     k ? "Loose Hop " : "Strict Hop");
2593                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
2594                                     "Type: 1 (IPv4)");
2595                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+1, 1,
2596                                     "Length: %u",
2597                                     tvb_get_guint8(tvb, offset2+l+1));
2598                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+2, 4,
2599                                     "IPv4 hop: %s",
2600                                     ip_to_str(tvb_get_ptr(tvb, offset2+l+2, 4)));
2601                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+6, 1, 
2602                                     "Prefix length: %u",
2603                                     tvb_get_guint8(tvb, offset2+l+6));
2604                 if (i < 4) {
2605                     proto_item_append_text(ti, "IPv4 %s%s", 
2606                                            ip_to_str(tvb_get_ptr(tvb, offset2+l+2, 4)),
2607                                            k ? " [L]":"");
2608                 }
2609
2610                 break;
2611
2612             case 2: /* IPv6 */
2613                 ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
2614                                           offset2+l, 20,
2615                                           "IPv6 Subobject");
2616                 rsvp_ero_subtree = 
2617                     proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); 
2618                 k = tvb_get_guint8(tvb, offset2+l) & 0x80;
2619                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
2620                                     k ? "Loose Hop " : "Strict Hop");
2621                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
2622                                     "Type: 2 (IPv6)");
2623                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+1, 1,
2624                                     "Length: %u",
2625                                     tvb_get_guint8(tvb, offset2+l+1));
2626                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+2, 16,
2627                                     "IPv6 hop: %s",
2628                                     ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2+l+2, 16)));
2629                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+18, 1,
2630                                     "Prefix length: %u",
2631                                     tvb_get_guint8(tvb, offset2+l+6));
2632                 if (i < 4) {
2633                     proto_item_append_text(ti, "IPv6 [...]%s", k ? " [L]":"");
2634                 }
2635
2636                 break;
2637
2638             case 3: /* Label */
2639                 k = tvb_get_guint8(tvb, offset2+l) & 0x80;
2640                 ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
2641                                           offset2+l, 8,
2642                                           "Label Subobject - %d, %s",
2643                                           tvb_get_ntohl(tvb, offset2+l+4), 
2644                                           k ? "Loose" : "Strict");
2645                 rsvp_ero_subtree = 
2646                     proto_item_add_subtree(ti2, ett_rsvp_record_route_subobj); 
2647                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
2648                                     k ? "Loose Hop " : "Strict Hop");
2649                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
2650                                     "Type: 3 (Label)");
2651                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+1, 1,
2652                                     "Length: %u",
2653                                     tvb_get_guint8(tvb, offset2+l+1));
2654                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+2, 1,
2655                                     "Flags: %0x", 
2656                                     tvb_get_guint8(tvb, offset2+l+2));
2657                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+3, 1,
2658                                     "C-Type: %u",
2659                                     tvb_get_guint8(tvb, offset2+l+3));
2660                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+4, 4,
2661                                     "Label: %d",
2662                                     tvb_get_ntohl(tvb, offset2+l+4));
2663                 if (i < 4) {
2664                     proto_item_append_text(ti, "Label %d%s", 
2665                                            tvb_get_ntohl(tvb, offset2+l+4), 
2666                                            k ? " [L]":"");
2667                 }
2668                 break;
2669
2670             case 4: /* Unnumbered Interface-ID */
2671                 k = tvb_get_guint8(tvb, offset2+l) & 0x80;
2672                 ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
2673                                           offset2+l, 8,
2674                                           "Unnumbered Interface-ID - %s, %d, %s",
2675                                           ip_to_str(tvb_get_ptr(tvb, offset2+l+4, 4)),
2676                                           tvb_get_ntohl(tvb, offset2+l+8), 
2677                                           k ? "Loose" : "Strict");
2678                 rsvp_ero_subtree = 
2679                     proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); 
2680                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
2681                                     k ? "Loose Hop " : "Strict Hop");
2682                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
2683                                     "Type: 4 (Unnumbered Interface-ID)");
2684                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+1, 1,
2685                                     "Length: %u",
2686                                     tvb_get_guint8(tvb, offset2+l+1));
2687                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+4, 4,
2688                                     "Router-ID: %s",
2689                                     ip_to_str(tvb_get_ptr(tvb, offset2+l+4, 4)));
2690                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+8, 4,
2691                                     "Interface-ID: %d",
2692                                     tvb_get_ntohl(tvb, offset2+l+8));
2693                 if (i < 4) {
2694                     proto_item_append_text(ti, "Unnum %s/%d%s", 
2695                                            ip_to_str(tvb_get_ptr(tvb, offset2+l+4, 4)),
2696                                            tvb_get_ntohl(tvb, offset2+l+8),
2697                                            k ? " [L]":"");
2698                 }
2699
2700                 break;
2701
2702             case 32: /* AS */
2703                 k = tvb_get_ntohs(tvb, offset2+l+2);
2704                 ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
2705                                           offset2+l, 4,
2706                                           "Autonomous System %u",
2707                                           k);
2708                 rsvp_ero_subtree = 
2709                     proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); 
2710                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
2711                                     "Type: 32 (Autonomous System Number)");
2712                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+1, 1,
2713                                     "Length: %u",
2714                                     tvb_get_guint8(tvb, offset2+l+1));
2715                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+2, 2,
2716                                     "Autonomous System %u", k);
2717                 if (i < 4) {
2718                     proto_item_append_text(ti, "AS %d", 
2719                                            tvb_get_ntohs(tvb, offset2+l+2));
2720                 }
2721
2722                 break;
2723
2724             case 64: /* Path Term */
2725                 k = tvb_get_guint8(tvb, offset2+l) & 0x80;
2726                 ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
2727                                           offset2+l, 4,
2728                                           "LSP Path Termination");
2729                 rsvp_ero_subtree = 
2730                     proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); 
2731                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
2732                                     k ? "Loose Hop " : "Strict Hop");
2733                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
2734                                     "Type: 64 (MPLS LSP Path Termination)");
2735                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+1, 1,
2736                                     "Length: %u",
2737                                     tvb_get_guint8(tvb, offset2+l+1));
2738                 if (i < 4) {
2739                     proto_item_append_text(ti, "Path Term");
2740                 }
2741                 break;
2742
2743             default: /* Unknown subobject */
2744                 k = tvb_get_guint8(tvb, offset2+l) & 0x80;
2745                 ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
2746                                           offset2+l,
2747                                           tvb_get_guint8(tvb, offset2+l+1),
2748                                           "Unknown subobject: %d", j);
2749                 rsvp_ero_subtree = 
2750                     proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); 
2751                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
2752                                     k ? "Loose Hop " : "Strict Hop");
2753                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
2754                                     "Type: %u (Unknown)", j);
2755                 proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+1, 1,
2756                                     "Length: %u",
2757                                     tvb_get_guint8(tvb, offset2+l+1));
2758
2759             }
2760
2761             l += tvb_get_guint8(tvb, offset2+l+1);
2762             if (l < mylen) {
2763                 if (i < 4)
2764                     proto_item_append_text(ti, ", ");
2765                 else if (i==4)
2766                     proto_item_append_text(ti, "...");
2767             }
2768         }
2769         break;
2770     }
2771     default:
2772         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
2773                             "C-type: Unknown (%u)",
2774                             type);
2775         proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
2776                             "Data (%d bytes)", mylen);
2777         break;
2778     }
2779 }
2780
2781 /*------------------------------------------------------------------------------
2782  * RECORD ROUTE OBJECT
2783  *------------------------------------------------------------------------------*/
2784 static void 
2785 dissect_rsvp_record_route (proto_tree *ti, tvbuff_t *tvb, 
2786                            int offset, int obj_length,
2787                            int class, int type, 
2788                            char *type_str)
2789 {
2790     int offset2 = offset + 4;
2791     proto_tree *rsvp_object_tree;
2792     int mylen, i, j, l;
2793     proto_tree *ti2, *rsvp_rro_subtree;
2794
2795     rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_record_route);
2796     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
2797                         "Length: %u", obj_length);
2798     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
2799                         "Class number: %u - %s", 
2800                         class, type_str);
2801     proto_item_set_text(ti, "RECORD ROUTE: ");
2802     mylen = obj_length - 4;
2803     switch(type) {
2804     case 1: {
2805         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
2806                             "C-type: 1");
2807         for (i=1, l = 0; l < mylen; i++) {
2808             j = tvb_get_guint8(tvb, offset2+l);
2809             switch(j) {
2810             case 1: /* IPv4 */
2811                 ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
2812                                           offset2+l, 8,
2813                                           "IPv4 Subobject - %s",
2814                                           ip_to_str(tvb_get_ptr(tvb, offset2+l+2, 4)));
2815                 rsvp_rro_subtree = 
2816                     proto_item_add_subtree(ti2, ett_rsvp_record_route_subobj); 
2817                 proto_tree_add_text(rsvp_rro_subtree, tvb, offset2+l, 1,
2818                                     "Type: 1 (IPv4)");
2819                 proto_tree_add_text(rsvp_rro_subtree, tvb, offset2+l+1, 1,
2820                                     "Length: %u",
2821                                     tvb_get_guint8(tvb, offset2+l+1));
2822                 proto_tree_add_text(rsvp_rro_subtree, tvb, offset2+l+2, 4,
2823                                     "IPv4 hop: %s",
2824                                     ip_to_str(tvb_get_ptr(tvb, offset2+l+2, 4)));
2825                 proto_tree_add_text(rsvp_rro_subtree, tvb, offset2+l+6, 1,
2826                                     "Prefix length: %u",
2827                                     tvb_get_guint8(tvb, offset2+l+6));
2828                 if (i < 4) {
2829                     proto_item_append_text(ti, "IPv4 %s", 
2830                                            ip_to_str(tvb_get_ptr(tvb, offset2+l+2, 4)));
2831                 }
2832
2833                 break;
2834
2835             case 2: /* IPv6 */
2836                 ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
2837                                           offset2+l, 20,
2838                                           "IPv6 Subobject");
2839                 rsvp_rro_subtree = 
2840                     proto_item_add_subtree(ti2, ett_rsvp_record_route_subobj); 
2841                 proto_tree_add_text(rsvp_rro_subtree, tvb, offset2+l, 1,
2842                                     "Type: 2 (IPv6)");
2843                 proto_tree_add_text(rsvp_rro_subtree, tvb, offset2+l+1, 1,
2844                                     "Length: %u",
2845                                     tvb_get_guint8(tvb, offset2+l+1));
2846                 proto_tree_add_text(rsvp_rro_subtree, tvb, offset2+l+2, 16,
2847                                     "IPv6 hop: %s",
2848                                     ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2+l+2, 16)));
2849                 proto_tree_add_text(rsvp_rro_subtree, tvb, offset2+l+18, 1,
2850                                     "Prefix length: %u",
2851                                     tvb_get_guint8(tvb, offset2+l+6));
2852                 if (i < 4) {
2853                     proto_item_append_text(ti, "IPv6 [...]");
2854                 }
2855                 break;
2856
2857             case 3: /* Label */
2858                 ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
2859                                           offset2+l, 8,
2860                                           "Label Subobject - %d",
2861                                           tvb_get_ntohl(tvb, offset2+l+4));
2862                 rsvp_rro_subtree = 
2863                     proto_item_add_subtree(ti2, ett_rsvp_record_route_subobj); 
2864                 proto_tree_add_text(rsvp_rro_subtree, tvb, offset2+l, 1,
2865                                     "Type: 3 (Label)");
2866                 proto_tree_add_text(rsvp_rro_subtree, tvb, offset2+l+1, 1,
2867                                     "Length: %u",
2868                                     tvb_get_guint8(tvb, offset2+l+1));
2869                 proto_tree_add_text(rsvp_rro_subtree, tvb, offset2+l+2, 1,
2870                                     "Flags: %0x", 
2871                                     tvb_get_guint8(tvb, offset2+l+2));
2872                 proto_tree_add_text(rsvp_rro_subtree, tvb, offset2+l+3, 1,
2873                                     "C-Type: %u",
2874                                     tvb_get_guint8(tvb, offset2+l+3));
2875                 proto_tree_add_text(rsvp_rro_subtree, tvb, offset2+l+4, 4,
2876                                     "Label: %d",
2877                                     tvb_get_ntohl(tvb, offset2+l+4));
2878                 if (i < 4) {
2879                     proto_item_append_text(ti, "Label %d", 
2880                                            tvb_get_ntohl(tvb, offset2+l+4));
2881                 }
2882                 break;
2883
2884             case 4: /* Unnumbered Interface-ID */
2885                 ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
2886                                           offset2+l, 8,
2887                                           "Unnumbered Interface-ID - %s, %d",
2888                                           ip_to_str(tvb_get_ptr(tvb, offset2+l+4, 4)),
2889                                           tvb_get_ntohl(tvb, offset2+l+8));
2890                 rsvp_rro_subtree = 
2891                     proto_item_add_subtree(ti2, ett_rsvp_record_route_subobj); 
2892                 proto_tree_add_text(rsvp_rro_subtree, tvb, offset2+l, 1,
2893                                     "Type: 4 (Unnumbered Interface-ID)");
2894                 proto_tree_add_text(rsvp_rro_subtree, tvb, offset2+l+1, 1,
2895                                     "Length: %u",
2896                                     tvb_get_guint8(tvb, offset2+l+1));
2897                 proto_tree_add_text(rsvp_rro_subtree, tvb, offset2+l+1, 1,
2898                                     "Flags: %u",
2899                                     tvb_get_guint8(tvb, offset2+l+2));
2900                 proto_tree_add_text(rsvp_rro_subtree, tvb, offset2+l+4, 4,
2901                                     "Router-ID: %s",
2902                                     ip_to_str(tvb_get_ptr(tvb, offset2+l+4, 4)));
2903                 proto_tree_add_text(rsvp_rro_subtree, tvb, offset2+l+8, 4,
2904                                     "Interface-ID: %d",
2905                                     tvb_get_ntohl(tvb, offset2+l+8));
2906                 if (i < 4) {
2907                     proto_item_append_text(ti, "Unnum %s/%d", 
2908                                            ip_to_str(tvb_get_ptr(tvb, offset2+l+4, 4)),
2909                                            tvb_get_ntohl(tvb, offset2+l+8));
2910                 }
2911                 break;
2912
2913             default: /* Unknown subobject */
2914                 ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
2915                                           offset2+l,
2916                                           tvb_get_guint8(tvb, offset2+l+1),
2917                                           "Unknown subobject: %u",
2918                                           j);
2919                 rsvp_rro_subtree = 
2920                     proto_item_add_subtree(ti2, ett_rsvp_record_route_subobj); 
2921                 proto_tree_add_text(rsvp_rro_subtree, tvb, offset2+l, 1,
2922                                     "Type: %u (Unknown)", j);
2923                 proto_tree_add_text(rsvp_rro_subtree, tvb, offset2+l+1, 1,
2924                                     "Length: %u",
2925                                     tvb_get_guint8(tvb, offset2+l+1));
2926
2927             }
2928
2929             l += tvb_get_guint8(tvb, offset2+l+1);
2930             if (l < mylen) {
2931                 if (i < 4)
2932                     proto_item_append_text(ti, ", ");
2933                 else if (i==4)
2934                     proto_item_append_text(ti, "...");
2935             }
2936         }
2937         break;
2938     }
2939                 
2940     default: {
2941         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
2942                             "C-type: Unknown (%u)",
2943                             type);
2944         proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
2945                             "Data (%d bytes)", mylen);
2946         break;
2947     }
2948     }
2949 }
2950
2951 /*------------------------------------------------------------------------------
2952  * MESSAGE ID
2953  *------------------------------------------------------------------------------*/
2954 static void 
2955 dissect_rsvp_message_id (proto_tree *ti, tvbuff_t *tvb, 
2956                          int offset, int obj_length,
2957                          int class, int type, 
2958                          char *type_str)
2959 {
2960     int offset2 = offset + 4;
2961     proto_tree *rsvp_object_tree;
2962
2963     rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_policy);
2964     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
2965                         "Length: %u", obj_length);
2966     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
2967                         "Class number: %u - %s", 
2968                         class, type_str);
2969     switch(type) {
2970     case 1: 
2971         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
2972                             "C-type: 1");
2973         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1,
2974                             "Flags: %d", tvb_get_guint8(tvb, offset+4));
2975         proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 3,
2976                             "Epoch: %d", tvb_get_ntoh24(tvb, offset+5));
2977         proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
2978                             "Message-ID: %d", tvb_get_ntohl(tvb, offset+8));
2979         proto_item_set_text(ti, "MESSAGE-ID: %d %s", 
2980                             tvb_get_ntohl(tvb, offset+8), 
2981                             tvb_get_guint8(tvb, offset+4) & 1 ? "(Ack Desired)" : "");
2982         break;
2983
2984     default:
2985         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
2986                             "C-type: Unknown (%u)",
2987                             type);
2988         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
2989                             "Data (%d bytes)", obj_length - 4);
2990         break;
2991     }
2992 }
2993
2994 /*------------------------------------------------------------------------------
2995  * MESSAGE ID ACK
2996  *------------------------------------------------------------------------------*/
2997 static void 
2998 dissect_rsvp_message_id_ack (proto_tree *ti, tvbuff_t *tvb, 
2999                              int offset, int obj_length,
3000                              int class, int type, 
3001                              char *type_str)
3002 {
3003     int offset2 = offset + 4;
3004     proto_tree *rsvp_object_tree;
3005
3006     rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_policy);
3007     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3008                         "Length: %u", obj_length);
3009     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
3010                         "Class number: %u - %s", 
3011                         class, type_str);
3012     switch(type) {
3013     case 1: 
3014         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
3015                             "C-type: 1");
3016         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1,
3017                             "Flags: %d", tvb_get_guint8(tvb, offset+4));
3018         proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 3,
3019                             "Epoch: %d", tvb_get_ntoh24(tvb, offset+5));
3020         proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
3021                             "Message-ID: %d", tvb_get_ntohl(tvb, offset+8));
3022         proto_item_set_text(ti, "MESSAGE-ID ACK: %d", tvb_get_ntohl(tvb, offset+8));
3023         break;
3024
3025     case 2: 
3026         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
3027                             "C-type: 2");
3028         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1,
3029                             "Flags: %d", tvb_get_guint8(tvb, offset+4));
3030         proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 3,
3031                             "Epoch: %d", tvb_get_ntoh24(tvb, offset+5));
3032         proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
3033                             "Message-ID: %d", tvb_get_ntohl(tvb, offset+8));
3034         proto_item_set_text(ti, "MESSAGE-ID NACK: %d", tvb_get_ntohl(tvb, offset+8));
3035         break;
3036
3037     default:
3038         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
3039                             "C-type: Unknown (%u)",
3040                             type);
3041         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
3042                             "Data (%d bytes)", obj_length - 4);
3043         break;
3044     }
3045 }
3046
3047 /*------------------------------------------------------------------------------
3048  * MESSAGE ID LIST
3049  *------------------------------------------------------------------------------*/
3050 static void 
3051 dissect_rsvp_message_id_list (proto_tree *ti, tvbuff_t *tvb, 
3052                               int offset, int obj_length,
3053                               int class, int type, 
3054                               char *type_str)
3055 {
3056     int offset2 = offset + 4;
3057     proto_tree *rsvp_object_tree;
3058     int mylen;
3059
3060     rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_policy);
3061     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3062                         "Length: %u", obj_length);
3063     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
3064                         "Class number: %u - %s", 
3065                         class, type_str);
3066     switch(type) {
3067     case 1: 
3068         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
3069                             "C-type: 1");
3070         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1,
3071                             "Flags: %d", tvb_get_guint8(tvb, offset+4));
3072         proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 3,
3073                             "Epoch: %d", tvb_get_ntoh24(tvb, offset+5));
3074         for (mylen = 8; mylen < obj_length; mylen += 4)
3075             proto_tree_add_text(rsvp_object_tree, tvb, offset+mylen, 4,
3076                                 "Message-ID: %d", tvb_get_ntohl(tvb, offset+mylen));
3077         proto_item_set_text(ti, "MESSAGE-ID LIST: %d IDs", 
3078                             (obj_length - 8)/4);
3079         break;
3080
3081     default:
3082         mylen = obj_length - 4;
3083         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
3084                             "C-type: Unknown (%u)",
3085                             type);
3086         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
3087                             "Data (%d bytes)", obj_length - 4);
3088         break;
3089     }
3090 }
3091
3092 /*------------------------------------------------------------------------------
3093  * HELLO
3094  *------------------------------------------------------------------------------*/
3095 static void 
3096 dissect_rsvp_hello (proto_tree *ti, tvbuff_t *tvb, 
3097                     int offset, int obj_length,
3098                     int class, int type, 
3099                     char *type_str)
3100 {
3101     proto_tree *rsvp_object_tree;
3102
3103     rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_hello_obj);
3104     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3105                         "Length: %u", obj_length);
3106     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
3107                         "Class number: %u - %s", 
3108                         class, type_str);        
3109     switch(type) {
3110     case 1:
3111     case 2:
3112         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
3113                             "C-Type: 1 - HELLO %s object",
3114                             type==1 ? "REQUEST" : "ACK");
3115         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 4,
3116                             "Source Instance: 0x%x",tvb_get_ntohl(tvb, offset+4));
3117         proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
3118                             "Destination Instance: 0x%x",tvb_get_ntohl(tvb, offset+8));
3119         break;
3120     default: 
3121         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
3122                             "C-Type: %d - UNKNOWN", type);
3123         break;
3124     };
3125 }
3126
3127 /*------------------------------------------------------------------------------
3128  * DCLASS
3129  *------------------------------------------------------------------------------*/
3130 static void 
3131 dissect_rsvp_dclass (proto_tree *ti, tvbuff_t *tvb, 
3132                      int offset, int obj_length,
3133                      int class, int type, 
3134                      char *type_str)
3135 {
3136     int offset2 = offset + 4;
3137     proto_tree *rsvp_object_tree;
3138     int mylen;
3139
3140     rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_dclass);
3141     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3142                         "Length: %u", obj_length);
3143     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
3144                         "Class number: %u - %s", 
3145                         class, type_str);
3146     proto_item_set_text(ti, "DCLASS: ");
3147     switch(type) {
3148     case 1: 
3149         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
3150                             "C-type: 1");
3151         for (mylen = 4; mylen < obj_length; mylen += 4) {
3152             proto_tree_add_text(rsvp_object_tree, tvb, offset+mylen+3, 1,
3153                                 "DSCP: %s", 
3154                                 val_to_str(tvb_get_guint8(tvb, offset+mylen+3),
3155                                            dscp_vals, "Unknown (%d)"));
3156             proto_item_append_text(ti, "%d%s", 
3157                                    tvb_get_guint8(tvb, offset+mylen+3)>>2,
3158                                    mylen==obj_length-4 ? "":
3159                                    mylen<16 ? ", ":
3160                                    mylen==16 ? ", ..." : "");
3161         }
3162         break;
3163
3164     default:
3165         mylen = obj_length - 4;
3166         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
3167                             "C-type: Unknown (%u)",
3168                             type);
3169         proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
3170                             "Data (%d bytes)", mylen);
3171         break;
3172     }
3173 }
3174
3175 /*------------------------------------------------------------------------------
3176  * ADMINISTRATIVE STATUS
3177  *------------------------------------------------------------------------------*/
3178 static void 
3179 dissect_rsvp_admin_status (proto_tree *ti, tvbuff_t *tvb, 
3180                            int offset, int obj_length,
3181                            int class, int type, 
3182                            char *type_str)
3183 {
3184     int offset2 = offset + 4;
3185     proto_tree *rsvp_object_tree;
3186     proto_tree *ti2, *rsvp_admin_subtree;
3187     int mylen;
3188     guint32 status;
3189     rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_admin_status);
3190     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3191                         "Length: %u", obj_length);
3192     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
3193                         "Class number: %u - %s", 
3194                         class, type_str);
3195     proto_item_set_text(ti, "ADMIN STATUS: ");
3196     switch(type) {
3197     case 1: 
3198         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
3199                             "C-type: 1");
3200         status = tvb_get_ntohl(tvb, offset2);
3201         ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
3202                                   "Admin Status: 0x%08x", status);
3203         rsvp_admin_subtree = 
3204             proto_item_add_subtree(ti2, ett_rsvp_admin_status_flags); 
3205         proto_tree_add_text(rsvp_admin_subtree, tvb, offset2, 4,
3206                             decode_boolean_bitfield(status, 0x80000000, 32,
3207                                                     "R: Reflect",
3208                                                     "R: Do not reflect"));
3209         proto_tree_add_text(rsvp_admin_subtree, tvb, offset2, 4,
3210                             decode_boolean_bitfield(status, 0x04, 32,
3211                                                     "T: Testing",
3212                                                     "T: "));
3213         proto_tree_add_text(rsvp_admin_subtree, tvb, offset2, 4,
3214                             decode_boolean_bitfield(status, 0x02, 32,
3215                                                     "A: Administratively Down",
3216                                                     "A: "));
3217         proto_tree_add_text(rsvp_admin_subtree, tvb, offset2, 4,
3218                             decode_boolean_bitfield(status, 0x01, 32,
3219                                                     "D: Delete In Progress",
3220                                                     "D: "));
3221         proto_item_set_text(ti, "ADMIN-STATUS: %s %s %s %s", 
3222                             (status & (1<<31)) ? "Reflect" : "",
3223                             (status & (1<<2))  ? "Testing" : "",
3224                             (status & (1<<1))  ? "Admin-Down" : "",
3225                             (status & (1<<0))  ? "Deleting" : "");
3226         break;
3227
3228     default:
3229         mylen = obj_length - 4;
3230         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
3231                             "C-type: Unknown (%u)",
3232                             type);
3233         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
3234                             "Data (%d bytes)", obj_length - 4);
3235         break;
3236     }
3237 }
3238
3239 /*------------------------------------------------------------------------------
3240  * LSP TUNNEL INTERFACE ID
3241  *------------------------------------------------------------------------------*/
3242 static void 
3243 dissect_rsvp_lsp_tunnel_if_id (proto_tree *ti, tvbuff_t *tvb, 
3244                                int offset, int obj_length,
3245                                int class, int type, 
3246                                char *type_str)
3247 {
3248     int offset2 = offset + 4;
3249     proto_tree *rsvp_object_tree;
3250
3251     rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_lsp_tunnel_if_id);
3252     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3253                         "Length: %u", obj_length);
3254     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
3255                         "Class number: %u - %s", 
3256                         class, type_str);
3257     proto_item_set_text(ti, "LSP INTERFACE-ID: ");
3258     switch(type) {
3259     case 1: 
3260         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
3261                             "C-type: 1 - IPv4");
3262         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4, 
3263                             "Router ID: %s",
3264                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
3265         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
3266                             "Interface ID: %u", tvb_get_ntohl(tvb, offset2+4));
3267         proto_item_set_text(ti, "LSP INTERFACE-ID: IPv4, Router-ID %s, Interface-ID %d", 
3268                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)),
3269                             tvb_get_ntohl(tvb, offset2+4));
3270         break;
3271
3272     default:
3273         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
3274                             "C-type: Unknown (%u)",
3275                             type);
3276         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
3277                             "Data (%d bytes)", obj_length - 4);
3278         break;
3279     }
3280 }
3281
3282 /*------------------------------------------------------------------------------
3283  * GENERALIZED UNI
3284  *------------------------------------------------------------------------------*/
3285 static void 
3286 dissect_rsvp_gen_uni (proto_tree *ti, tvbuff_t *tvb, 
3287                       int offset, int obj_length,
3288                       int class, int type, 
3289                       char *type_str)
3290 {
3291     int offset2 = offset + 4;
3292     proto_tree *rsvp_object_tree;
3293     int mylen, i, j, k, l, m;
3294     proto_tree *ti2, *rsvp_gen_uni_subtree;
3295     int s_len, s_class, s_type;
3296
3297     rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_gen_uni);
3298     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3299                         "Length: %u", obj_length);
3300     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
3301                         "Class number: %u - %s", 
3302                         class, type_str);
3303     proto_item_set_text(ti, "GENERALIZED UNI: ");
3304
3305     mylen = obj_length - 4;
3306     switch(type) {
3307     case 1: {
3308         char *c;
3309         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
3310                             "C-type: 1");
3311         for (i=1, l = 0; l < mylen; i++) {
3312             j = tvb_get_guint8(tvb, offset2+l+2);
3313             switch(j) {
3314             case 1: 
3315             case 2: /* We do source and destination TNA together */
3316                 c = (j==1) ? "Source" : "Destination";
3317                 k = tvb_get_guint8(tvb, offset2+l+3);
3318                 switch(k) {
3319                 case 1:
3320                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
3321                                               offset2+l, 8,
3322                                               "%s IPv4 TNA - %s", c, 
3323                                               ip_to_str(tvb_get_ptr(tvb, offset2+l+4, 4)));
3324                     rsvp_gen_uni_subtree = 
3325                         proto_item_add_subtree(ti2, ett_rsvp_gen_uni_subobj); 
3326                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
3327                                         "Class: %d (%s)", j, c);
3328                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
3329                                         "Type: 1 (IPv4)");
3330                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
3331                                         "Length: %u",
3332                                         tvb_get_ntohs(tvb, offset2+l));
3333                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 4,
3334                                         "IPv4 hop: %s",
3335                                         ip_to_str(tvb_get_ptr(tvb, offset2+l+4, 4)));
3336                     if (i < 4) {
3337                         proto_item_append_text(ti, "%s IPv4 %s", c,
3338                                                ip_to_str(tvb_get_ptr(tvb, offset2+l+2, 4)));
3339                     }
3340                     break;
3341
3342                 case 2:
3343                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
3344                                               offset2+l, 20,
3345                                               "%s IPv6 TNA", c);
3346                     rsvp_gen_uni_subtree = 
3347                         proto_item_add_subtree(ti2, ett_rsvp_gen_uni_subobj); 
3348                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
3349                                         "Class: %d (%s)", j, c);
3350                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
3351                                         "Type: 2 (IPv6)");
3352                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
3353                                         "Length: %u",
3354                                         tvb_get_ntohs(tvb, offset2+l));
3355                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 4,
3356                                         "Data");
3357                     if (i < 4) {
3358                         proto_item_append_text(ti, "%s IPv6", c);
3359                     }
3360                     break;
3361
3362                 case 3:
3363                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
3364                                               offset2+l, tvb_get_ntohs(tvb, offset2+l),
3365                                               "%s NSAP TNA", c);
3366                     rsvp_gen_uni_subtree = 
3367                         proto_item_add_subtree(ti2, ett_rsvp_gen_uni_subobj); 
3368                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
3369                                         "Class: %d (%s)", j, c);
3370                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
3371                                         "Type: 3 (NSAP)");
3372                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
3373                                         "Length: %u",
3374                                         tvb_get_ntohs(tvb, offset2+l));
3375                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 
3376                                         tvb_get_ntohs(tvb, offset2+l)-4,
3377                                         "Data");
3378                     if (i < 4) {
3379                         proto_item_append_text(ti, "%s NSAP", c);
3380                     }
3381                     break;
3382
3383                 default:
3384                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
3385                                               offset2+l, tvb_get_ntohs(tvb, offset2+l),
3386                                               "%s UNKNOWN TNA", c);
3387                     rsvp_gen_uni_subtree = 
3388                         proto_item_add_subtree(ti2, ett_rsvp_gen_uni_subobj); 
3389                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
3390                                         "Class: %d (%s)", j, c);
3391                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
3392                                         "Type: %d (UNKNOWN)", j);
3393                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
3394                                         "Length: %u",
3395                                         tvb_get_ntohs(tvb, offset2+l));
3396                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 
3397                                         tvb_get_ntohs(tvb, offset2+l)-4,
3398                                         "Data");
3399                     if (i < 4) {
3400                         proto_item_append_text(ti, "%s UNKNOWN", c);
3401                     }
3402                     break;
3403                 }
3404                 break;
3405
3406             case 3: /* Diversity subobject */
3407                 k = tvb_get_guint8(tvb, offset2+l+3);
3408                 switch(k) {
3409                 default:
3410                 case 1:
3411                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
3412                                               offset2+l, tvb_get_ntohs(tvb, offset2+l),
3413                                               "Diversity Subobject");
3414                     rsvp_gen_uni_subtree = 
3415                         proto_item_add_subtree(ti2, ett_rsvp_gen_uni_subobj); 
3416                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
3417                                         "Class: %d (Diversity)", j);
3418                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
3419                                         "Type: %d", tvb_get_guint8(tvb, offset2+l+3));
3420                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
3421                                         "Length: %u",
3422                                         tvb_get_ntohs(tvb, offset2+l));
3423                     m = tvb_get_guint8(tvb, offset2+l+4) >> 4;
3424                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 1, 
3425                                         "Diversity: %d - %s", m, 
3426                                         val_to_str(m, ouni_guni_diversity_str, "Unknown"));
3427                     s_len = tvb_get_ntohs(tvb, offset2+l+8);
3428                     s_class = tvb_get_guint8(tvb, offset2+l+10);
3429                     s_type = tvb_get_guint8(tvb, offset2+l+11);
3430                     ti2 = proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+8, 
3431                                               s_len, "Session");
3432                     dissect_rsvp_session(ti2, tvb, offset2+l+8, s_len, s_class, s_type, 
3433                                          val_to_str(s_class, rsvp_class_vals, "Unknown"));
3434                     offset2 += s_len;
3435                     s_len = tvb_get_ntohs(tvb, offset2+l+8);
3436                     s_class = tvb_get_guint8(tvb, offset2+l+10);
3437                     s_type = tvb_get_guint8(tvb, offset2+l+11);
3438                     ti2 = proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+8, 
3439                                               s_len, "Template");
3440                     dissect_rsvp_template_filter(ti2, tvb, offset2+l+8, s_len, s_class, s_type, 
3441                                                  val_to_str(s_class, rsvp_class_vals, "Unknown"));
3442
3443                     if (i < 4) {
3444                         proto_item_append_text(ti, "Diversity");
3445                     }
3446                     break;
3447
3448                 }
3449                 break;
3450
3451             case 4: /* Egress Label */
3452                 k = tvb_get_guint8(tvb, offset2+l+3);
3453                 switch(k) {
3454                 default:
3455                 case 1:
3456                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
3457                                               offset2+l, tvb_get_ntohs(tvb, offset2+l),
3458                                               "Egress Label Subobject");
3459                     rsvp_gen_uni_subtree = 
3460                         proto_item_add_subtree(ti2, ett_rsvp_gen_uni_subobj); 
3461                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
3462                                         "Class: %d (Egress Label)", j);
3463                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
3464                                         "Type: %d", tvb_get_guint8(tvb, offset2+l+3));
3465                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
3466                                         "Length: %u",
3467                                         tvb_get_ntohs(tvb, offset2+l));
3468                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 1,
3469                                         "Direction: %s",
3470                                         decode_boolean_bitfield(
3471                                             tvb_get_guint8(tvb, offset2+l+4), 0x80, 8,
3472                                             "U: 1 - Upstream label/port ID",
3473                                             "U: 0 - Downstream label/port ID"));
3474                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+7, 1,
3475                                         "Label type: %u", tvb_get_guint8(tvb, offset2+l+7));
3476                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+8, 4,
3477                                         "Logical Port ID: %u", tvb_get_ntohl(tvb, offset2+l+8));
3478                     proto_item_append_text(ti2, ": %s, Label type %d, Port ID %d, Label ",
3479                                            tvb_get_guint8(tvb, offset2+l+4) & 0x80 ? 
3480                                            "Upstream" : "Downstream", 
3481                                            tvb_get_guint8(tvb, offset2+l+7), 
3482                                            tvb_get_ntohl(tvb, offset2+l+8));
3483                     for (j=12; j < tvb_get_ntohs(tvb, offset2+l); j+=4) {
3484                         proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+8, 4,
3485                                             "Label: %u", tvb_get_ntohl(tvb, offset2+l+j));
3486                         proto_item_append_text(ti2, "%u ", tvb_get_ntohl(tvb, offset2+l+j));
3487                     }
3488                     if (i < 4) {
3489                         proto_item_append_text(ti, "Egress Label");
3490                     }
3491                     break;
3492                 }
3493                 break;
3494
3495             case 5: /* Service Level */
3496                 k = tvb_get_guint8(tvb, offset2+l+3);
3497                 switch(k) {
3498                 default:
3499                 case 1:
3500                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
3501                                               offset2+l, tvb_get_ntohs(tvb, offset2+l),
3502                                               "Service Level Subobject");
3503                     rsvp_gen_uni_subtree = 
3504                         proto_item_add_subtree(ti2, ett_rsvp_gen_uni_subobj); 
3505                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
3506                                         "Class: %d (Egress Label)", j);
3507                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
3508                                         "Type: %d", tvb_get_guint8(tvb, offset2+l+3));
3509                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
3510                                         "Length: %u",
3511                                         tvb_get_ntohs(tvb, offset2+l));
3512                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 1,
3513                                         "Service Level: %u", tvb_get_guint8(tvb, offset2+l+4));
3514                     proto_item_append_text(ti2, ": %u", tvb_get_guint8(tvb, offset2+l+4));
3515                     if (i < 4) {
3516                         proto_item_append_text(ti, "Service Level %d", tvb_get_guint8(tvb, offset2+l+4));
3517                     }
3518                     break;
3519                 }
3520                 break;
3521
3522             default: /* Unknown subobject */
3523                 ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
3524                                           offset2+l,
3525                                           tvb_get_ntohs(tvb, offset2+l),
3526                                           "Unknown subobject: %u",
3527                                           j);
3528                 rsvp_gen_uni_subtree = 
3529                     proto_item_add_subtree(ti2, ett_rsvp_record_route_subobj); 
3530                 proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 1,
3531                                     "Type: %u (Unknown)", j);
3532                 proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+1, 1,
3533                                     "Length: %u",
3534                                     tvb_get_guint8(tvb, offset2+l+1));
3535
3536             }
3537
3538             l += tvb_get_guint8(tvb, offset2+l+1);
3539             if (l < mylen) {
3540                 if (i < 4)
3541                     proto_item_append_text(ti, ", ");
3542                 else if (i==4)
3543                     proto_item_append_text(ti, "...");
3544             }
3545         }
3546         break;
3547     }
3548                 
3549     default:
3550         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
3551                             "C-type: Unknown (%u)",
3552                             type);
3553         proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
3554                             "Data (%d bytes)", mylen);
3555         break;
3556     }
3557 }
3558
3559 /*------------------------------------------------------------------------------
3560  * The main loop
3561  *------------------------------------------------------------------------------*/
3562 static void 
3563 dissect_rsvp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) 
3564 {
3565     int offset = 0;
3566     proto_tree *rsvp_tree = NULL, *ti; 
3567     proto_tree *rsvp_header_tree;
3568     proto_tree *rsvp_object_tree;
3569     guint8 ver_flags;
3570     guint8 message_type;
3571     guint16 cksum, computed_cksum;
3572     vec_t cksum_vec[1];
3573     int len;
3574     int msg_length;
3575     int obj_length;
3576     int offset2;
3577     int session_off, tempfilt_off;
3578
3579     if (check_col(pinfo->cinfo, COL_PROTOCOL))
3580         col_set_str(pinfo->cinfo, COL_PROTOCOL, "RSVP");
3581     if (check_col(pinfo->cinfo, COL_INFO))
3582         col_clear(pinfo->cinfo, COL_INFO);
3583
3584     ver_flags = tvb_get_guint8(tvb, offset+0);
3585     message_type = tvb_get_guint8(tvb, offset+1);
3586     if (check_col(pinfo->cinfo, COL_INFO)) {
3587         col_add_str(pinfo->cinfo, COL_INFO,
3588             val_to_str(message_type, message_type_vals, "Unknown (%u). ")); 
3589         find_rsvp_session_tempfilt(tvb, offset, &session_off, &tempfilt_off);
3590         if (session_off) 
3591             col_append_str(pinfo->cinfo, COL_INFO, summary_session(tvb, session_off));
3592         if (tempfilt_off) 
3593             col_append_str(pinfo->cinfo, COL_INFO, summary_template(tvb, tempfilt_off));
3594     }
3595
3596     if (tree) {
3597         msg_length = tvb_get_ntohs(tvb, offset+6);
3598         ti = proto_tree_add_item(tree, proto_rsvp, tvb, offset, msg_length,
3599             FALSE);
3600         rsvp_tree = proto_item_add_subtree(ti, ett_rsvp);
3601
3602         ti = proto_tree_add_text(rsvp_tree, tvb, offset, 8, "RSVP Header. %s", 
3603                                  val_to_str(message_type, message_type_vals, 
3604                                             "Unknown Message (%u). ")); 
3605         rsvp_header_tree = proto_item_add_subtree(ti, ett_rsvp_hdr);
3606
3607         proto_tree_add_text(rsvp_header_tree, tvb, offset, 1, "RSVP Version: %u", 
3608                             (ver_flags & 0xf0)>>4);  
3609         proto_tree_add_text(rsvp_header_tree, tvb, offset, 1, "Flags: %02x",
3610                             ver_flags & 0xf);
3611         proto_tree_add_uint(rsvp_header_tree, rsvp_filter[RSVPF_MSG], tvb, 
3612                             offset+1, 1, message_type);
3613         switch (RSVPF_MSG + message_type) {
3614
3615         case RSVPF_PATH:
3616         case RSVPF_RESV:
3617         case RSVPF_PATHERR:
3618         case RSVPF_RESVERR:
3619         case RSVPF_PATHTEAR:
3620         case RSVPF_RESVTEAR:
3621         case RSVPF_RCONFIRM:
3622         case RSVPF_RTEARCONFIRM:
3623         case RSVPF_BUNDLE:
3624         case RSVPF_ACK:
3625         case RSVPF_SREFRESH:
3626         case RSVPF_HELLO:
3627                proto_tree_add_boolean_hidden(rsvp_header_tree, rsvp_filter[RSVPF_MSG + message_type], tvb, 
3628                                    offset+1, 1, 1);
3629                break;
3630
3631         default:
3632                 proto_tree_add_protocol_format(rsvp_header_tree, proto_malformed, tvb, offset+1, 1,
3633                         "Invalid message type: %u", message_type);
3634                 return;
3635         }
3636
3637         cksum = tvb_get_ntohs(tvb, offset+2);
3638         if (!pinfo->fragmented && (int) tvb_length(tvb) >= msg_length) {
3639             /* The packet isn't part of a fragmented datagram and isn't
3640                truncated, so we can checksum it. */
3641             cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, msg_length);
3642             cksum_vec[0].len = msg_length;
3643             computed_cksum = in_cksum(&cksum_vec[0], 1);
3644             if (computed_cksum == 0) {
3645                 proto_tree_add_text(rsvp_header_tree, tvb, offset+2, 2,
3646                                     "Message Checksum: 0x%04x (correct)",
3647                                     cksum);
3648             } else {
3649                 proto_tree_add_text(rsvp_header_tree, tvb, offset+2, 2,
3650                                     "Message Checksum: 0x%04x (incorrect, should be 0x%04x)",
3651                                     cksum,
3652                                     in_cksum_shouldbe(cksum, computed_cksum));
3653             }
3654         } else {
3655             proto_tree_add_text(rsvp_header_tree, tvb, offset+2, 2,
3656                                 "Message Checksum: 0x%04x",
3657                                 cksum);
3658         }
3659         proto_tree_add_text(rsvp_header_tree, tvb, offset+4, 1,
3660                             "Sending TTL: %u",
3661                             tvb_get_guint8(tvb, offset+4));
3662         proto_tree_add_text(rsvp_header_tree, tvb, offset+6, 2,
3663                             "Message length: %u", msg_length);
3664
3665         offset += 8;
3666         len = 8;
3667         while (len < msg_length) {
3668             guint8 class;       
3669             guint8 type;
3670             char *type_str;
3671
3672             obj_length = tvb_get_ntohs(tvb, offset);
3673             class = tvb_get_guint8(tvb, offset+2);
3674             type = tvb_get_guint8(tvb, offset+3);
3675             type_str = val_to_str(class, rsvp_class_vals, "Unknown");
3676             proto_tree_add_uint_hidden(rsvp_tree, rsvp_filter[RSVPF_OBJECT], tvb, 
3677                                             offset, obj_length, class);
3678             ti = proto_tree_add_item(rsvp_tree, rsvp_filter[rsvp_class_to_filter_num(class)],
3679                                      tvb, offset, obj_length, FALSE);
3680
3681             offset2 = offset+4;
3682
3683             switch(class) {
3684
3685             case RSVP_CLASS_SESSION:
3686                 dissect_rsvp_session(ti, tvb, offset, obj_length, class, type, type_str);
3687                 break;
3688                 
3689             case RSVP_CLASS_HOP:
3690                 dissect_rsvp_hop(ti, tvb, offset, obj_length, class, type, type_str);
3691                 break;
3692                 
3693             case RSVP_CLASS_TIME_VALUES:
3694                 dissect_rsvp_time_values(ti, tvb, offset, obj_length, class, type, type_str);
3695                 break;
3696
3697             case RSVP_CLASS_ERROR:
3698                 dissect_rsvp_error(ti, tvb, offset, obj_length, class, type, type_str);
3699                 break;
3700
3701             case RSVP_CLASS_SCOPE:
3702                 dissect_rsvp_scope(ti, tvb, offset, obj_length, class, type, type_str);
3703                 break;
3704                 
3705             case RSVP_CLASS_STYLE:
3706                 dissect_rsvp_style(ti, tvb, offset, obj_length, class, type, type_str);
3707                 break;
3708             
3709             case RSVP_CLASS_CONFIRM:
3710                 dissect_rsvp_confirm(ti, tvb, offset, obj_length, class, type, type_str);
3711                 break;
3712
3713             case RSVP_CLASS_SENDER_TEMPLATE:
3714             case RSVP_CLASS_FILTER_SPEC:
3715                 dissect_rsvp_template_filter(ti, tvb, offset, obj_length, class, type, type_str);
3716                 break;
3717
3718             case RSVP_CLASS_SENDER_TSPEC:
3719                 dissect_rsvp_tspec(ti, tvb, offset, obj_length, class, type, type_str);
3720                 break;
3721
3722             case RSVP_CLASS_FLOWSPEC:
3723                 dissect_rsvp_flowspec(ti, tvb, offset, obj_length, class, type, type_str);
3724                 break;
3725
3726             case RSVP_CLASS_ADSPEC:
3727                 dissect_rsvp_adspec(ti, tvb, offset, obj_length, class, type, type_str);
3728                 break;
3729
3730             case RSVP_CLASS_INTEGRITY:
3731                 dissect_rsvp_integrity(ti, tvb, offset, obj_length, class, type, type_str);
3732                 break;
3733
3734             case RSVP_CLASS_POLICY:
3735                 dissect_rsvp_policy(ti, tvb, offset, obj_length, class, type, type_str);
3736                 break;
3737
3738             case RSVP_CLASS_LABEL_REQUEST:
3739                 dissect_rsvp_label_request(ti, tvb, offset, obj_length, class, type, type_str);
3740                 break;
3741             
3742             case RSVP_CLASS_UPSTREAM_LABEL:
3743             case RSVP_CLASS_SUGGESTED_LABEL:
3744             case RSVP_CLASS_LABEL:
3745                 dissect_rsvp_label(ti, tvb, offset, obj_length, class, type, type_str);
3746                 break;
3747             
3748             case RSVP_CLASS_SESSION_ATTRIBUTE:
3749                 dissect_rsvp_session_attribute(ti, tvb, offset, obj_length, class, type, type_str);
3750                 break;
3751
3752             case RSVP_CLASS_EXPLICIT_ROUTE:
3753                 dissect_rsvp_explicit_route(ti, tvb, offset, obj_length, class, type, type_str);
3754                 break;
3755
3756             case RSVP_CLASS_RECORD_ROUTE:
3757                 dissect_rsvp_record_route(ti, tvb, offset, obj_length, class, type, type_str);
3758                 break;
3759             
3760             case RSVP_CLASS_MESSAGE_ID:
3761                 dissect_rsvp_message_id(ti, tvb, offset, obj_length, class, type, type_str);
3762                 break;
3763
3764             case RSVP_CLASS_MESSAGE_ID_ACK:
3765                 dissect_rsvp_message_id_ack(ti, tvb, offset, obj_length, class, type, type_str);
3766                 break;
3767
3768             case RSVP_CLASS_MESSAGE_ID_LIST:
3769                 dissect_rsvp_message_id_list(ti, tvb, offset, obj_length, class, type, type_str);
3770                 break;
3771
3772             case RSVP_CLASS_HELLO:
3773                 dissect_rsvp_hello(ti, tvb, offset, obj_length, class, type, type_str);
3774                 break;
3775
3776             case RSVP_CLASS_DCLASS:
3777                 dissect_rsvp_dclass(ti, tvb, offset, obj_length, class, type, type_str);
3778                 break;
3779
3780             case RSVP_CLASS_ADMIN_STATUS: 
3781                 dissect_rsvp_admin_status(ti, tvb, offset, obj_length, class, type, type_str);
3782                 break;
3783
3784             case RSVP_CLASS_LSP_TUNNEL_IF_ID:
3785                 dissect_rsvp_lsp_tunnel_if_id(ti, tvb, offset, obj_length, class, type, type_str);
3786                 break;
3787
3788             case RSVP_CLASS_GENERALIZED_UNI: 
3789                 dissect_rsvp_gen_uni(ti, tvb, offset, obj_length, class, type, type_str);
3790                 break;
3791
3792             case RSVP_CLASS_NULL:
3793             default:
3794                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_unknown_class);
3795                 proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3796                                     "Length: %u", obj_length);
3797                 proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
3798                                     "Class number: %u - %s", 
3799                                     class, type_str);
3800                 proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
3801                                     "Data (%d bytes)", obj_length - 4);
3802                 break;
3803             }  
3804             
3805             offset += obj_length;
3806             len += obj_length;
3807         }
3808     }
3809 }
3810
3811 void
3812 proto_register_rsvp(void)
3813 {
3814         static gint *ett[] = {
3815                 &ett_rsvp,
3816                 &ett_rsvp_hdr,
3817                 &ett_rsvp_session,
3818                 &ett_rsvp_hop,
3819                 &ett_rsvp_hop_subobj,
3820                 &ett_rsvp_time_values,
3821                 &ett_rsvp_error,
3822                 &ett_rsvp_scope,
3823                 &ett_rsvp_style,
3824                 &ett_rsvp_confirm,
3825                 &ett_rsvp_sender_template,
3826                 &ett_rsvp_filter_spec,
3827                 &ett_rsvp_sender_tspec,
3828                 &ett_rsvp_sender_tspec_subtree,
3829                 &ett_rsvp_flowspec,
3830                 &ett_rsvp_flowspec_subtree,
3831                 &ett_rsvp_adspec,
3832                 &ett_rsvp_adspec_subtree,
3833                 &ett_rsvp_integrity,
3834                 &ett_rsvp_integrity_flags,
3835                 &ett_rsvp_policy,
3836                 &ett_rsvp_label,
3837                 &ett_rsvp_label_request,
3838                 &ett_rsvp_session_attribute,
3839                 &ett_rsvp_session_attribute_flags,
3840                 &ett_rsvp_explicit_route,
3841                 &ett_rsvp_explicit_route_subobj,
3842                 &ett_rsvp_record_route,
3843                 &ett_rsvp_record_route_subobj,
3844                 &ett_rsvp_hello_obj,
3845                 &ett_rsvp_dclass,
3846                 &ett_rsvp_lsp_tunnel_if_id,
3847                 &ett_rsvp_admin_status,
3848                 &ett_rsvp_admin_status_flags,
3849                 &ett_rsvp_gen_uni,
3850                 &ett_rsvp_gen_uni_subobj,
3851                 &ett_rsvp_unknown_class,
3852         };
3853
3854         proto_rsvp = proto_register_protocol("Resource ReserVation Protocol (RSVP)",
3855             "RSVP", "rsvp");
3856         proto_register_field_array(proto_rsvp, rsvpf_info, array_length(rsvpf_info));
3857         proto_register_subtree_array(ett, array_length(ett));
3858 }
3859
3860 void
3861 proto_reg_handoff_rsvp(void)
3862 {
3863         dissector_handle_t rsvp_handle;
3864
3865         rsvp_handle = create_dissector_handle(dissect_rsvp, proto_rsvp);
3866         dissector_add("ip.proto", IP_PROTO_RSVP, rsvp_handle);
3867 }