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