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