fix usage of "if(tree) {" to display the right things, even if no coloring rule is set
[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 <epan/in_cksum.h>
73 #include "etypes.h"
74 #include <epan/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
2618     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_INTEGRITY));
2619     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
2620                         "Length: %u", obj_length);
2621     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
2622                         "Class number: %u - %s",
2623                         class, type_str);
2624     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2625                         "C-type: %u", type);
2626     flags = tvb_get_guint8(tvb, offset2);
2627     ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
2628                               "Flags: 0x%02x", flags);
2629     rsvp_integ_flags_tree = proto_item_add_subtree(ti2, TREE(TT_INTEGRITY_FLAGS));
2630     proto_tree_add_text(rsvp_integ_flags_tree, tvb, offset2, 1,
2631         decode_boolean_bitfield(flags, 0x01, 8, "Handshake capable", "Handshake not capable"));
2632     proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 6,
2633                         "Key Identifier: %s", tvb_bytes_to_str(tvb, offset2+2, 6));
2634     proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 8,
2635                         "Sequence Number: %" PRIu64, tvb_get_ntoh64(tvb, offset2+8));
2636     proto_tree_add_text(rsvp_object_tree, tvb, offset2+16, obj_length - 20,
2637                         "Hash: %s", tvb_bytes_to_str(tvb, offset2+16, obj_length - 20));
2638 }
2639
2640 /*------------------------------------------------------------------------------
2641  * POLICY
2642  *------------------------------------------------------------------------------*/
2643 static void
2644 dissect_rsvp_policy (proto_tree *ti, tvbuff_t *tvb,
2645                      int offset, int obj_length,
2646                      int class, int type,
2647                      char *type_str)
2648 {
2649     int offset2 = offset + 4;
2650     proto_tree *rsvp_object_tree;
2651
2652     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_POLICY));
2653     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
2654                         "Length: %u", obj_length);
2655     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
2656                         "Class number: %u - %s",
2657                         class, type_str);
2658     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2659                         "C-type: %u", type);
2660     proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
2661                         "Data (%d bytes)", obj_length - 4);
2662 }
2663
2664 /*------------------------------------------------------------------------------
2665  * LABEL_REQUEST
2666  *------------------------------------------------------------------------------*/
2667 static void
2668 dissect_rsvp_label_request (proto_tree *ti, tvbuff_t *tvb,
2669                             int offset, int obj_length,
2670                             int class, int type,
2671                             char *type_str)
2672 {
2673     int offset2 = offset + 4;
2674     proto_tree *rsvp_object_tree;
2675
2676     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_LABEL_REQUEST));
2677     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
2678                         "Length: %u", obj_length);
2679     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
2680                         "Class number: %u - %s",
2681                         class, type_str);
2682     switch(type) {
2683     case 1: {
2684         unsigned short l3pid = tvb_get_ntohs(tvb, offset2+2);
2685         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2686                             "C-type: 1");
2687         proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
2688                             "L3PID: %s (0x%04x)",
2689                             val_to_str(l3pid, etype_vals, "Unknown"),
2690                             l3pid);
2691         proto_item_set_text(ti, "LABEL REQUEST: Basic: L3PID: %s (0x%04x)",
2692                             val_to_str(l3pid, etype_vals, "Unknown"),
2693                             l3pid);
2694         break;
2695     }
2696
2697     case 2: {
2698         unsigned short l3pid = tvb_get_ntohs(tvb, offset2+2);
2699         unsigned short min_vpi, min_vci, max_vpi, max_vci;
2700         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2701                             "C-type: 2 (Label Request with ATM label Range)");
2702         proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
2703                             "L3PID: %s (0x%04x)",
2704                             val_to_str(l3pid, etype_vals, "Unknown"),
2705                             l3pid);
2706         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 1, 
2707                             "M: %s Merge in Data Plane",
2708                             (tvb_get_guint8(tvb, offset2+4) & 0x80) ? 
2709                             "1: Can" : "0: Cannot");
2710         min_vpi = tvb_get_ntohs(tvb, offset2+4) & 0x7f;
2711         min_vci = tvb_get_ntohs(tvb, offset2+6);
2712         max_vpi = tvb_get_ntohs(tvb, offset2+8) & 0x7f;
2713         max_vci = tvb_get_ntohs(tvb, offset2+10);
2714         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 2,
2715                             "Min VPI: %d", min_vpi);
2716         proto_tree_add_text(rsvp_object_tree, tvb, offset2+6, 2,
2717                             "Min VCI: %d", min_vci);
2718         proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 2,
2719                             "Max VPI: %d", max_vpi);
2720         proto_tree_add_text(rsvp_object_tree, tvb, offset2+10, 2,
2721                             "Max VCI: %d", max_vci);
2722         proto_item_set_text(ti, "LABEL REQUEST: ATM: L3PID: %s (0x%04x). VPI/VCI: Min: %d/%d, Max: %d/%d. %s Merge. ",
2723                             val_to_str(l3pid, etype_vals, "Unknown"), l3pid,
2724                             min_vpi, min_vci, max_vpi, max_vci, 
2725                             (tvb_get_guint8(tvb, offset2+4) & 0x80) ? "Can" : "Cannot");
2726         break;
2727     }
2728
2729     case 3: {
2730         guint16 l3pid = tvb_get_ntohs(tvb, offset2+2);
2731         guint32 min_dlci, max_dlci, dlci_len, dlci_len_code;
2732         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2733                             "C-type: 2 (Label Request with ATM label Range)");
2734         proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
2735                             "L3PID: %s (0x%04x)",
2736                             val_to_str(l3pid, etype_vals, "Unknown"),
2737                             l3pid);
2738         dlci_len_code = (tvb_get_ntohs(tvb, offset2+4) & 0x0180) >> 7; 
2739         min_dlci = tvb_get_ntohl(tvb, offset2+4) & 0x7fffff;
2740         max_dlci = tvb_get_ntohl(tvb, offset2+8) & 0x7fffff;
2741         switch(dlci_len_code) {
2742         case 0: 
2743             /* 10-bit DLCIs */
2744             dlci_len = 10;
2745             min_dlci &= 0x3ff;
2746             max_dlci &= 0x3ff;
2747         case 2:
2748             dlci_len = 23;
2749         default:
2750             dlci_len = 0;
2751             min_dlci = 0;
2752             max_dlci = 0;
2753         }
2754         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 2, 
2755                             "DLCI Length: %s (%d)", 
2756                             dlci_len==10 ? "10 bits" : 
2757                             dlci_len==23 ? "23 bits" : 
2758                             "INVALID", dlci_len_code);
2759         proto_tree_add_text(rsvp_object_tree, tvb, offset2+5, 3,
2760                             "Min DLCI: %d", min_dlci);
2761         proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 2,
2762                             "Max DLCI: %d", max_dlci);
2763         proto_item_set_text(ti, "LABEL REQUEST: Frame: L3PID: %s (0x%04x). DLCI Len: %s. Min DLCI: %d. Max DLCI: %d",
2764                             val_to_str(l3pid, etype_vals, "Unknown"), l3pid,
2765                             dlci_len==10 ? "10 bits" : 
2766                             dlci_len==23 ? "23 bits" : 
2767                             "INVALID", min_dlci, max_dlci);
2768         break;
2769     }
2770     case 4: {
2771         unsigned short l3pid = tvb_get_ntohs(tvb, offset2+2);
2772         unsigned char  lsp_enc = tvb_get_guint8(tvb,offset2);
2773         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2774                             "C-type: 4 (Generalized Label Request)");
2775         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
2776                             "LSP Encoding Type: %s",
2777                             val_to_str(lsp_enc, gmpls_lsp_enc_str, "Unknown (%d)"));
2778         proto_tree_add_text(rsvp_object_tree, tvb, offset2+1, 1,
2779                             "Switching Type: %s",
2780                             val_to_str(tvb_get_guint8(tvb,offset2+1),
2781                                        gmpls_switching_type_str, "Unknown (%d)"));
2782         proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
2783                             "G-PID: %s (0x%0x)",
2784                             val_to_str(l3pid, gmpls_gpid_str,
2785                                        val_to_str(l3pid, etype_vals,
2786                                                   "Unknown G-PID(0x%04x)")),
2787                             l3pid);
2788         proto_item_set_text(ti, "LABEL REQUEST: Generalized: LSP Encoding=%s, "
2789                             "Switching Type=%s, G-PID=%s ",
2790                             val_to_str(lsp_enc, gmpls_lsp_enc_str, "Unknown (%d)"),
2791                             val_to_str(tvb_get_guint8(tvb,offset2+1),
2792                                        gmpls_switching_type_str, "Unknown (%d)"),
2793                             val_to_str(l3pid, gmpls_gpid_str,
2794                                        val_to_str(l3pid, etype_vals,
2795                                                   "Unknown (0x%04x)")));
2796         break;
2797     }
2798
2799     default: {
2800         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2801                             "C-type: Unknown (%u)",
2802                             type);
2803         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
2804                             "Data (%d bytes)", obj_length - 4);
2805         break;
2806     }
2807     }
2808 }
2809
2810 /*------------------------------------------------------------------------------
2811  * LABEL
2812  *------------------------------------------------------------------------------*/
2813 static void
2814 dissect_rsvp_label (proto_tree *ti, tvbuff_t *tvb,
2815                     int offset, int obj_length,
2816                     int class, int type,
2817                     char *type_str)
2818 {
2819     int offset2 = offset + 4;
2820     proto_tree *rsvp_object_tree;
2821     int mylen, i;
2822     char *name;
2823
2824     name = (class==RSVP_CLASS_SUGGESTED_LABEL ? "SUGGESTED LABEL":
2825             (class==RSVP_CLASS_UPSTREAM_LABEL ? "UPSTREAM LABEL":
2826              "LABEL"));
2827     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_LABEL));
2828     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
2829                         "Length: %u", obj_length);
2830     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
2831                         "Class number: %u - %s",
2832                         class, type_str);
2833     mylen = obj_length - 4;
2834     switch(type) {
2835     case 1:
2836         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2837                             "C-type: 1 (Packet Label)");
2838         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
2839                             "Label: %u",
2840                             tvb_get_ntohl(tvb, offset2));
2841         proto_item_set_text(ti, "%s: %d", name,
2842                             tvb_get_ntohl(tvb, offset2));
2843         break;
2844
2845     case 2:
2846         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2847                             "C-type: 2 (Generalized Label)");
2848         proto_item_set_text(ti, "%s: Generalized: ", name);
2849         for (i = 0; i < mylen; i += 4) {
2850             proto_tree_add_text(rsvp_object_tree, tvb, offset2+i, 4,
2851                                 "Generalized Label: %u",
2852                                 tvb_get_ntohl(tvb, offset2+i));
2853             if (i < 16) {
2854                 proto_item_append_text(ti, "%d%s",
2855                                        tvb_get_ntohl(tvb, offset2+i),
2856                                        i+4<mylen?", ":"");
2857             } else if (i == 16) {
2858                 proto_item_append_text(ti, "...");
2859             }
2860         }
2861         break;
2862
2863     default:
2864         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2865                             "C-type: Unknown (%u)",
2866                             type);
2867         proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
2868                             "Data (%d bytes)", mylen);
2869         break;
2870     }
2871 }
2872
2873 /*------------------------------------------------------------------------------
2874  * LABEL_SET
2875  *------------------------------------------------------------------------------*/
2876 static void
2877 dissect_rsvp_label_set (proto_tree *ti, tvbuff_t *tvb,
2878                         int offset, int obj_length,
2879                         int class, int type,
2880                         char *type_str)
2881 {
2882     int offset2 = offset + 8;
2883     proto_tree *rsvp_object_tree;
2884     guint8 label_type;
2885     int len, i;
2886
2887     static value_string action_type_vals[] = {
2888       {0, "Inclusive list"},
2889       {1, "Exclusive list"},
2890       {2, "Inclusive range"},
2891       {3, "Exclusive range"},
2892       {0xff, NULL}
2893    };
2894
2895     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_LABEL_SET));
2896     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
2897                         "Length: %u", obj_length);
2898     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
2899                         "Class number: %u - %s",
2900                         class, type_str);
2901     len = obj_length - 8;
2902     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, "C-type: %u", type);
2903     proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1, "Action: %s", 
2904                         val_to_str(tvb_get_guint8(tvb, offset+4),
2905                         action_type_vals, "Unknown (%u)"));
2906     label_type = tvb_get_guint8 (tvb, offset+7);
2907     proto_tree_add_text(rsvp_object_tree, tvb, offset+7, 1, "Label type: %s",
2908                         label_type==1 ? "Packet Label" : "Generalized Label");
2909
2910     for (i = 0; i < len/4; i++) {
2911         proto_tree_add_text(rsvp_object_tree, tvb, offset2+i*4, 4,
2912                             "Subchannel %u: %u", i+1,
2913                             tvb_get_ntohl(tvb, offset2+i*4));
2914     }
2915 }
2916
2917 /*------------------------------------------------------------------------------
2918  * SESSION ATTRIBUTE
2919  *------------------------------------------------------------------------------*/
2920 static void
2921 dissect_rsvp_session_attribute (proto_tree *ti, tvbuff_t *tvb,
2922                                 int offset, int obj_length,
2923                                 int class, int type,
2924                                 char *type_str)
2925 {
2926     int offset2 = offset + 4;
2927     proto_tree *rsvp_object_tree;
2928     guint8 flags;
2929     guint8 name_len;
2930     proto_tree *ti2, *rsvp_sa_flags_tree;
2931
2932     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_SESSION_ATTRIBUTE));
2933     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
2934                         "Length: %u", obj_length);
2935     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
2936                         "Class number: %u - %s",
2937                         class, type_str);
2938     switch(type) {
2939     case 1:
2940     case 7:
2941
2942         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2943                             "C-type: %u - IPv4 LSP (%sResource Affinities)",
2944                             type, (type == 1) ? "" : "No ");
2945         
2946         if (type == 1) {
2947             proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4, 
2948                             "Exclude-Any: 0x%0x", tvb_get_ntohl(tvb, offset2));
2949             proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4, 
2950                             "Include-Any: 0x%0x", tvb_get_ntohl(tvb, offset2+4));
2951             proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 4, 
2952                             "Include-All: 0x%0x", tvb_get_ntohl(tvb, offset2+8));
2953             offset2 = offset2+12;
2954         }
2955
2956         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
2957                             "Setup priority: %u",
2958                             tvb_get_guint8(tvb, offset2));
2959         proto_tree_add_text(rsvp_object_tree, tvb, offset2+1, 1,
2960                             "Hold priority: %u",
2961                             tvb_get_guint8(tvb, offset2+1));
2962         flags = tvb_get_guint8(tvb, offset2+2);
2963         ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 1,
2964                                   "Flags: 0x%02x", flags);
2965         rsvp_sa_flags_tree = proto_item_add_subtree(ti2,
2966                                                     TREE(TT_SESSION_ATTRIBUTE_FLAGS));
2967         proto_tree_add_text(rsvp_sa_flags_tree, tvb, offset2+2, 1,
2968                             decode_boolean_bitfield(flags, 0x01, 8,
2969                                                     "Local protection desired",
2970                                                     "Local protection not desired"));
2971         proto_tree_add_text(rsvp_sa_flags_tree, tvb, offset2+2, 1,
2972                             decode_boolean_bitfield(flags, 0x02, 8,
2973                                                     "Label recording desired",
2974                                                     "Label recording not desired"));
2975         proto_tree_add_text(rsvp_sa_flags_tree, tvb, offset2+2, 1,
2976                             decode_boolean_bitfield(flags, 0x04, 8,
2977                                                     "SE style desired",
2978                                                     "SE style not desired"));
2979         proto_tree_add_text(rsvp_sa_flags_tree, tvb, offset2+2, 1,
2980                             decode_boolean_bitfield(flags, 0x08, 8,
2981                                                     "Bandwidth protection desired",
2982                                                     "Bandwidth protection not desired"));
2983         proto_tree_add_text(rsvp_sa_flags_tree, tvb, offset2+2, 1,
2984                             decode_boolean_bitfield(flags, 0x10, 8,
2985                                                     "Node protection desired",
2986                                                     "Node protection not desired"));
2987
2988         name_len = tvb_get_guint8(tvb, offset2+3);
2989         proto_tree_add_text(rsvp_object_tree, tvb, offset2+3, 1,
2990                             "Name length: %u", name_len);
2991         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, name_len,
2992                             "Name: %s",
2993                             tvb_format_text(tvb, offset2+4, name_len));
2994
2995         proto_item_set_text(ti, "SESSION ATTRIBUTE: SetupPrio %d, HoldPrio %d, %s%s%s%s%s [%s]",
2996                             tvb_get_guint8(tvb, offset2),
2997                             tvb_get_guint8(tvb, offset2+1),
2998                             flags &0x01 ? "Local Protection, " : "",
2999                             flags &0x02 ? "Label Recording, " : "",
3000                             flags &0x04 ? "SE Style, " : "",
3001                             flags &0x08 ? "Bandwidth Protection, " : "",
3002                             flags &0x10 ? "Node Protection, " : "",
3003                             name_len ? tvb_format_text(tvb, offset2+4, name_len) : "");
3004         break;
3005
3006     default:
3007         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3008                             "C-type: Unknown (%u)",
3009                             type);
3010         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
3011                             "Data (%d bytes)", obj_length - 4);
3012         break;
3013     }
3014 }
3015
3016 /*------------------------------------------------------------------------------
3017  * EXPLICIT ROUTE AND RECORD ROUTE SUBOBJECTS
3018  *------------------------------------------------------------------------------*/
3019 static void
3020 dissect_rsvp_ero_rro_subobjects (proto_tree *ti, proto_tree *rsvp_object_tree, 
3021                                  tvbuff_t *tvb,
3022                                  int offset, int obj_length, int class)
3023 {
3024     int i, j, k, l, flags;
3025     proto_tree *ti2, *rsvp_ro_subtree, *rsvp_rro_flags_subtree;
3026     int tree_type;
3027
3028     switch(class) {
3029     case RSVP_CLASS_EXPLICIT_ROUTE:
3030         tree_type = TREE(TT_EXPLICIT_ROUTE_SUBOBJ); 
3031         break;
3032     case RSVP_CLASS_RECORD_ROUTE:
3033         tree_type = TREE(TT_RECORD_ROUTE_SUBOBJ); 
3034         break;
3035     default:
3036         /* Bail out */
3037         return;
3038     }
3039
3040     for (i=1, l = 0; l < obj_length - 4; i++) {
3041         j = tvb_get_guint8(tvb, offset+l) & 0x7f;
3042         switch(j) {
3043         case 1: /* IPv4 */
3044             k = tvb_get_guint8(tvb, offset+l) & 0x80;
3045             ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3046                                       offset+l, 8,
3047                                       "IPv4 Subobject - %s%s",
3048                                       ip_to_str(tvb_get_ptr(tvb, offset+l+2, 4)),
3049                                       class == RSVP_CLASS_EXPLICIT_ROUTE ? 
3050                                       (k ? ", Loose" : ", Strict") : "");
3051             rsvp_ro_subtree =
3052                 proto_item_add_subtree(ti2, tree_type);
3053             if (class == RSVP_CLASS_EXPLICIT_ROUTE) 
3054                 proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3055                                     k ? "Loose Hop " : "Strict Hop");
3056             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3057                                 "Type: 1 (IPv4)");
3058             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
3059                                 "Length: %u",
3060                                 tvb_get_guint8(tvb, offset+l+1));
3061             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+2, 4,
3062                                 "IPv4 hop: %s",
3063                                 ip_to_str(tvb_get_ptr(tvb, offset+l+2, 4)));
3064             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+6, 1,
3065                                 "Prefix length: %u",
3066                                 tvb_get_guint8(tvb, offset+l+6));
3067             if (i < 4) {
3068                 proto_item_append_text(ti, "IPv4 %s%s",
3069                                        ip_to_str(tvb_get_ptr(tvb, offset+l+2, 4)),
3070                                        k ? " [L]" : "");
3071             }
3072             if (class == RSVP_CLASS_RECORD_ROUTE) {
3073                 flags = tvb_get_guint8(tvb, offset+l+7);
3074                 if (flags&0x10) {
3075                     proto_item_append_text(ti,  " (Node-id)");
3076                     proto_item_append_text(ti2, " (Node-id)");
3077                 }
3078                 if (flags&0x01) proto_item_append_text(ti2, ", Local Protection Available");
3079                 if (flags&0x02) proto_item_append_text(ti2, ", Local Protection In Use");
3080                 if (flags&0x04) proto_item_append_text(ti2, ", Backup BW Avail");
3081                 if (flags&0x08) proto_item_append_text(ti2, ", Backup is Next-Next-Hop");
3082                 ti2 = proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+7, 1,
3083                                           "Flags: 0x%02x", flags);
3084                 rsvp_rro_flags_subtree = 
3085                     proto_item_add_subtree(ti2, TREE(TT_RECORD_ROUTE_SUBOBJ_FLAGS)); 
3086                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
3087                                     decode_boolean_bitfield(flags, 0x01, 8, 
3088                                                             "Local Protection Available",
3089                                                             "Local Protection Not Available"));
3090                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
3091                                     decode_boolean_bitfield(flags, 0x02, 8, 
3092                                                             "Local Protection In Use",
3093                                                             "Local Protection Not In Use"));
3094                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
3095                                     decode_boolean_bitfield(flags, 0x04, 8, 
3096                                                             "Bandwidth Protection Available",
3097                                                             "Bandwidth Protection Not Available"));
3098                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
3099                                     decode_boolean_bitfield(flags, 0x08, 8, 
3100                                                             "Node Protection Available",
3101                                                             "Node Protection Not Available"));
3102                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
3103                                     decode_boolean_bitfield(flags, 0x10, 8,
3104                                                             "Address Specifies a Node-id Address",
3105                                                             "Address Doesn't Specify a Node-id Address"));
3106             }
3107
3108             break;
3109
3110         case 2: /* IPv6 */
3111             ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3112                                       offset+l, 20,
3113                                       "IPv6 Subobject");
3114             rsvp_ro_subtree =
3115                 proto_item_add_subtree(ti2, tree_type);
3116             k = tvb_get_guint8(tvb, offset+l) & 0x80;
3117             if (class == RSVP_CLASS_EXPLICIT_ROUTE) 
3118                 proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3119                                     k ? "Loose Hop " : "Strict Hop");
3120             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3121                                 "Type: 2 (IPv6)");
3122             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
3123                                 "Length: %u",
3124                                 tvb_get_guint8(tvb, offset+l+1));
3125             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+2, 16,
3126                                 "IPv6 hop: %s",
3127                                 ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset+l+2, 16)));
3128             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+18, 1,
3129                                 "Prefix length: %u",
3130                                 tvb_get_guint8(tvb, offset+l+18));
3131             if (i < 4) {
3132                 proto_item_append_text(ti, "IPv6 [...]%s", k ? " [L]":"");
3133             }
3134             if (class == RSVP_CLASS_RECORD_ROUTE) {
3135                 flags = tvb_get_guint8(tvb, offset+l+19);
3136                 if (flags&0x10) {
3137                     proto_item_append_text(ti,  " (Node-id)");
3138                     proto_item_append_text(ti2, " (Node-id)");
3139                 }
3140                 if (flags&0x01) proto_item_append_text(ti2, ", Local Protection Available");
3141                 if (flags&0x02) proto_item_append_text(ti2, ", Local Protection In Use");
3142                 if (flags&0x04) proto_item_append_text(ti2, ", Backup BW Avail");
3143                 if (flags&0x08) proto_item_append_text(ti2, ", Backup is Next-Next-Hop");
3144                 ti2 = proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+19, 1,
3145                                           "Flags: 0x%02x", flags);
3146                 rsvp_rro_flags_subtree = 
3147                     proto_item_add_subtree(ti2, TREE(TT_RECORD_ROUTE_SUBOBJ_FLAGS)); 
3148                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
3149                                     decode_boolean_bitfield(flags, 0x01, 8, 
3150                                                             "Local Protection Available",
3151                                                             "Local Protection Not Available"));
3152                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
3153                                     decode_boolean_bitfield(flags, 0x02, 8, 
3154                                                             "Local Protection In Use",
3155                                                             "Local Protection Not In Use"));
3156                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
3157                                     decode_boolean_bitfield(flags, 0x04, 8, 
3158                                                             "Backup Tunnel Has Bandwidth",
3159                                                             "Backup Tunnel Does Not Have Bandwidth"));
3160                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
3161                                     decode_boolean_bitfield(flags, 0x08, 8, 
3162                                                             "Backup Tunnel Goes To Next-Next-Hop",
3163                                                             "Backup Tunnel Goes To Next-Hop"));
3164                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
3165                                     decode_boolean_bitfield(flags, 0x10, 8,
3166                                                             "Address Specifies a Node-id Address",
3167                                                             "Address Doesn't Specify a Node-id Address"));
3168             }
3169
3170             break;
3171
3172         case 3: /* Label */
3173             k = tvb_get_guint8(tvb, offset+l) & 0x80;
3174             ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3175                                       offset+l, 8,
3176                                       "Label Subobject - %d, %s",
3177                                       tvb_get_ntohl(tvb, offset+l+4),
3178                                       class == RSVP_CLASS_EXPLICIT_ROUTE ? 
3179                                       (k ? "Loose" : "Strict") : "");
3180             rsvp_ro_subtree =
3181                 proto_item_add_subtree(ti2, tree_type);
3182             if (class == RSVP_CLASS_EXPLICIT_ROUTE) 
3183                 proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3184                                     k ? "Loose Hop " : "Strict Hop");
3185             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3186                                 "Type: 3 (Label)");
3187             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
3188                                 "Length: %u",
3189                                 tvb_get_guint8(tvb, offset+l+1));
3190             if (class == RSVP_CLASS_RECORD_ROUTE) {
3191                 flags = tvb_get_guint8(tvb, offset+l+2);
3192                 if (flags&0x01) proto_item_append_text(ti2, ", Local Protection Available");
3193                 if (flags&0x02) proto_item_append_text(ti2, ", Local Protection In Use");
3194                 if (flags&0x04) proto_item_append_text(ti2, ", Backup BW Avail");
3195                 if (flags&0x08) proto_item_append_text(ti2, ", Backup is Next-Next-Hop");
3196                 ti2 = proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+2, 1,
3197                                           "Flags: 0x%02x", flags);
3198                 rsvp_rro_flags_subtree = 
3199                     proto_item_add_subtree(ti2, TREE(TT_RECORD_ROUTE_SUBOBJ_FLAGS)); 
3200                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
3201                                     decode_boolean_bitfield(flags, 0x01, 8, 
3202                                                             "Local Protection Available",
3203                                                             "Local Protection Not Available"));
3204                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
3205                                     decode_boolean_bitfield(flags, 0x02, 8, 
3206                                                             "Local Protection In Use",
3207                                                             "Local Protection Not In Use"));
3208                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
3209                                     decode_boolean_bitfield(flags, 0x04, 8, 
3210                                                             "Backup Tunnel Has Bandwidth",
3211                                                             "Backup Tunnel Does Not Have Bandwidth"));
3212                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
3213                                     decode_boolean_bitfield(flags, 0x08, 8, 
3214                                                             "Backup Tunnel Goes To Next-Next-Hop",
3215                                                             "Backup Tunnel Goes To Next-Hop"));
3216             }
3217             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+3, 1,
3218                                 "C-Type: %u",
3219                                 tvb_get_guint8(tvb, offset+l+3));
3220             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+4, 4,
3221                                 "Label: %d",
3222                                 tvb_get_ntohl(tvb, offset+l+4));
3223             if (i < 4) {
3224                 proto_item_append_text(ti, "Label %d%s",
3225                                        tvb_get_ntohl(tvb, offset+l+4),
3226                                        k ? " [L]":"");
3227             }
3228             break;
3229
3230         case 4: /* Unnumbered Interface-ID */
3231             k = tvb_get_guint8(tvb, offset+l) & 0x80;
3232             ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3233                                       offset+l, 8,
3234                                       "Unnumbered Interface-ID - %s, %d, %s",
3235                                       ip_to_str(tvb_get_ptr(tvb, offset+l+4, 4)),
3236                                       tvb_get_ntohl(tvb, offset+l+8),
3237                                       class == RSVP_CLASS_EXPLICIT_ROUTE ? 
3238                                       (k ? "Loose" : "Strict") : "");
3239             rsvp_ro_subtree =
3240                 proto_item_add_subtree(ti2, tree_type);
3241             if (class == RSVP_CLASS_EXPLICIT_ROUTE) 
3242                 proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3243                                     k ? "Loose Hop " : "Strict Hop");
3244             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3245                                 "Type: 4 (Unnumbered Interface-ID)");
3246             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
3247                                 "Length: %u",
3248                                 tvb_get_guint8(tvb, offset+l+1));
3249             if (class == RSVP_CLASS_RECORD_ROUTE) {
3250                 flags = tvb_get_guint8(tvb, offset+l+2);
3251                 if (flags&0x01) proto_item_append_text(ti2, ", Local Protection Available");
3252                 if (flags&0x02) proto_item_append_text(ti2, ", Local Protection In Use");
3253                 if (flags&0x04) proto_item_append_text(ti2, ", Backup BW Avail");
3254                 if (flags&0x08) proto_item_append_text(ti2, ", Backup is Next-Next-Hop");
3255                 ti2 = proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+2, 1,
3256                                           "Flags: 0x%02x", flags);
3257                 rsvp_rro_flags_subtree = 
3258                     proto_item_add_subtree(ti2, TREE(TT_RECORD_ROUTE_SUBOBJ_FLAGS)); 
3259                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
3260                                     decode_boolean_bitfield(flags, 0x01, 8, 
3261                                                             "Local Protection Available",
3262                                                             "Local Protection Not Available"));
3263                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
3264                                     decode_boolean_bitfield(flags, 0x02, 8, 
3265                                                             "Local Protection In Use",
3266                                                             "Local Protection Not In Use"));
3267                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
3268                                     decode_boolean_bitfield(flags, 0x04, 8, 
3269                                                             "Backup Tunnel Has Bandwidth",
3270                                                             "Backup Tunnel Does Not Have Bandwidth"));
3271                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
3272                                     decode_boolean_bitfield(flags, 0x08, 8, 
3273                                                             "Backup Tunnel Goes To Next-Next-Hop",
3274                                                             "Backup Tunnel Goes To Next-Hop"));
3275             }
3276             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+4, 4,
3277                                 "Router-ID: %s",
3278                                 ip_to_str(tvb_get_ptr(tvb, offset+l+4, 4)));
3279             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+8, 4,
3280                                 "Interface-ID: %d",
3281                                 tvb_get_ntohl(tvb, offset+l+8));
3282             if (i < 4) {
3283                 proto_item_append_text(ti, "Unnum %s/%d%s",
3284                                        ip_to_str(tvb_get_ptr(tvb, offset+l+4, 4)),
3285                                        tvb_get_ntohl(tvb, offset+l+8),
3286                                        k ? " [L]":"");
3287             }
3288
3289             break;
3290
3291         case 32: /* AS */
3292             if (class == RSVP_CLASS_RECORD_ROUTE) goto defaultsub;
3293             k = tvb_get_ntohs(tvb, offset+l+2);
3294             ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3295                                       offset+l, 4,
3296                                       "Autonomous System %u",
3297                                       k);
3298             rsvp_ro_subtree =
3299                 proto_item_add_subtree(ti2, tree_type);
3300             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3301                                 "Type: 32 (Autonomous System Number)");
3302             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
3303                                 "Length: %u",
3304                                 tvb_get_guint8(tvb, offset+l+1));
3305             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+2, 2,
3306                                 "Autonomous System %u", k);
3307             if (i < 4) {
3308                 proto_item_append_text(ti, "AS %d",
3309                                        tvb_get_ntohs(tvb, offset+l+2));
3310             }
3311
3312             break;
3313
3314         default: /* Unknown subobject */
3315         defaultsub:
3316             k = tvb_get_guint8(tvb, offset+l) & 0x80;
3317             ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3318                                       offset+l,
3319                                       tvb_get_guint8(tvb, offset+l+1),
3320                                       "Unknown subobject: %d", j);
3321             rsvp_ro_subtree =
3322                 proto_item_add_subtree(ti2, tree_type);
3323             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3324                                 k ? "Loose Hop " : "Strict Hop");
3325             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3326                                 "Type: %u (Unknown)", j);
3327             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
3328                                 "Length: %u",
3329                                 tvb_get_guint8(tvb, offset+l+1));
3330
3331         }
3332
3333         l += tvb_get_guint8(tvb, offset+l+1);
3334         if (l < obj_length - 4) {
3335             if (i < 4)
3336                 proto_item_append_text(ti, ", ");
3337             else if (i==4)
3338                 proto_item_append_text(ti, "...");
3339         }
3340     }
3341 }
3342     
3343 /*------------------------------------------------------------------------------
3344  * EXPLICIT ROUTE OBJECT
3345  *------------------------------------------------------------------------------*/
3346 static void
3347 dissect_rsvp_explicit_route (proto_tree *ti, tvbuff_t *tvb,
3348                              int offset, int obj_length,
3349                              int class, int type,
3350                              char *type_str)
3351 {
3352     /* int offset2 = offset + 4; */
3353     proto_tree *rsvp_object_tree;
3354     /* int mylen, i, j, k, l; */
3355     /* proto_tree *ti2, *rsvp_ero_subtree; */
3356
3357     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_EXPLICIT_ROUTE));
3358     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3359                         "Length: %u", obj_length);
3360     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
3361                         "Class number: %u - %s",
3362                         class, type_str);
3363     /* mylen = obj_length - 4; */
3364     switch(type) {
3365     case 1: 
3366         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3367                             "C-type: 1");
3368         proto_item_set_text(ti, "EXPLICIT ROUTE: ");
3369
3370         dissect_rsvp_ero_rro_subobjects(ti, rsvp_object_tree, tvb,
3371                                         offset + 4, obj_length, class);
3372         break;
3373
3374     default:
3375         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3376                             "C-type: Unknown (%u)",
3377                             type);
3378         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, obj_length - 4,
3379                             "Data (%d bytes)", obj_length - 4);
3380         break;
3381     }
3382 }
3383
3384 /*------------------------------------------------------------------------------
3385  * RECORD ROUTE OBJECT
3386  *------------------------------------------------------------------------------*/
3387 static void
3388 dissect_rsvp_record_route (proto_tree *ti, tvbuff_t *tvb,
3389                            int offset, int obj_length,
3390                            int class, int type,
3391                            char *type_str)
3392 {
3393     /* int offset2 = offset + 4; */
3394     proto_tree *rsvp_object_tree;
3395     /* int mylen, i, j, l; */
3396     /* proto_tree *ti2, *rsvp_rro_subtree; */
3397
3398     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_RECORD_ROUTE));
3399     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3400                         "Length: %u", obj_length);
3401     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
3402                         "Class number: %u - %s",
3403                         class, type_str);
3404     proto_item_set_text(ti, "RECORD ROUTE: ");
3405     /* mylen = obj_length - 4; */
3406     switch(type) {
3407     case 1: 
3408         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3409                             "C-type: 1");
3410
3411         dissect_rsvp_ero_rro_subobjects(ti, rsvp_object_tree, tvb,
3412                                         offset + 4, obj_length, class);
3413         break;
3414
3415     default: 
3416         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3417                             "C-type: Unknown (%u)",
3418                             type);
3419         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, obj_length - 4,
3420                             "Data (%d bytes)", obj_length - 4);
3421         break;
3422     }
3423 }
3424
3425 /*------------------------------------------------------------------------------
3426  * MESSAGE ID
3427  *------------------------------------------------------------------------------*/
3428 static void
3429 dissect_rsvp_message_id (proto_tree *ti, tvbuff_t *tvb,
3430                          int offset, int obj_length,
3431                          int class, int type,
3432                          char *type_str)
3433 {
3434     int offset2 = offset + 4;
3435     proto_tree *rsvp_object_tree;
3436
3437     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_MESSAGE_ID));
3438     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3439                         "Length: %u", obj_length);
3440     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
3441                         "Class number: %u - %s",
3442                         class, type_str);
3443     switch(type) {
3444     case 1:
3445         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3446                             "C-type: 1");
3447         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1,
3448                             "Flags: %d", tvb_get_guint8(tvb, offset+4));
3449         proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 3,
3450                             "Epoch: %d", tvb_get_ntoh24(tvb, offset+5));
3451         proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
3452                             "Message-ID: %d", tvb_get_ntohl(tvb, offset+8));
3453         proto_item_set_text(ti, "MESSAGE-ID: %d %s",
3454                             tvb_get_ntohl(tvb, offset+8),
3455                             tvb_get_guint8(tvb, offset+4) & 1 ? "(Ack Desired)" : "");
3456         break;
3457
3458     default:
3459         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3460                             "C-type: Unknown (%u)",
3461                             type);
3462         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
3463                             "Data (%d bytes)", obj_length - 4);
3464         break;
3465     }
3466 }
3467
3468 /*------------------------------------------------------------------------------
3469  * MESSAGE ID ACK
3470  *------------------------------------------------------------------------------*/
3471 static void
3472 dissect_rsvp_message_id_ack (proto_tree *ti, tvbuff_t *tvb,
3473                              int offset, int obj_length,
3474                              int class, int type,
3475                              char *type_str)
3476 {
3477     int offset2 = offset + 4;
3478     proto_tree *rsvp_object_tree;
3479
3480     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_MESSAGE_ID_ACK));
3481     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3482                         "Length: %u", obj_length);
3483     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
3484                         "Class number: %u - %s",
3485                         class, type_str);
3486     switch(type) {
3487     case 1:
3488         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3489                             "C-type: 1");
3490         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1,
3491                             "Flags: %d", tvb_get_guint8(tvb, offset+4));
3492         proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 3,
3493                             "Epoch: %d", tvb_get_ntoh24(tvb, offset+5));
3494         proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
3495                             "Message-ID: %d", tvb_get_ntohl(tvb, offset+8));
3496         proto_item_set_text(ti, "MESSAGE-ID ACK: %d", tvb_get_ntohl(tvb, offset+8));
3497         break;
3498
3499     case 2:
3500         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3501                             "C-type: 2");
3502         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1,
3503                             "Flags: %d", tvb_get_guint8(tvb, offset+4));
3504         proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 3,
3505                             "Epoch: %d", tvb_get_ntoh24(tvb, offset+5));
3506         proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
3507                             "Message-ID: %d", tvb_get_ntohl(tvb, offset+8));
3508         proto_item_set_text(ti, "MESSAGE-ID NACK: %d", tvb_get_ntohl(tvb, offset+8));
3509         break;
3510
3511     default:
3512         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3513                             "C-type: Unknown (%u)",
3514                             type);
3515         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
3516                             "Data (%d bytes)", obj_length - 4);
3517         break;
3518     }
3519 }
3520
3521 /*------------------------------------------------------------------------------
3522  * MESSAGE ID LIST
3523  *------------------------------------------------------------------------------*/
3524 static void
3525 dissect_rsvp_message_id_list (proto_tree *ti, tvbuff_t *tvb,
3526                               int offset, int obj_length,
3527                               int class, int type,
3528                               char *type_str)
3529 {
3530     int offset2 = offset + 4;
3531     proto_tree *rsvp_object_tree;
3532     int mylen;
3533
3534     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_MESSAGE_ID_LIST));
3535     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3536                         "Length: %u", obj_length);
3537     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
3538                         "Class number: %u - %s",
3539                         class, type_str);
3540     switch(type) {
3541     case 1:
3542         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3543                             "C-type: 1");
3544         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1,
3545                             "Flags: %d", tvb_get_guint8(tvb, offset+4));
3546         proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 3,
3547                             "Epoch: %d", tvb_get_ntoh24(tvb, offset+5));
3548         for (mylen = 8; mylen < obj_length; mylen += 4)
3549             proto_tree_add_text(rsvp_object_tree, tvb, offset+mylen, 4,
3550                                 "Message-ID: %d", tvb_get_ntohl(tvb, offset+mylen));
3551         proto_item_set_text(ti, "MESSAGE-ID LIST: %d IDs",
3552                             (obj_length - 8)/4);
3553         break;
3554
3555     default:
3556         mylen = obj_length - 4;
3557         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3558                             "C-type: Unknown (%u)",
3559                             type);
3560         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
3561                             "Data (%d bytes)", obj_length - 4);
3562         break;
3563     }
3564 }
3565
3566 /*------------------------------------------------------------------------------
3567  * HELLO
3568  *------------------------------------------------------------------------------*/
3569 static void
3570 dissect_rsvp_hello (proto_tree *ti, tvbuff_t *tvb,
3571                     int offset, int obj_length,
3572                     int class, int type,
3573                     char *type_str)
3574 {
3575     proto_tree *rsvp_object_tree;
3576
3577     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_HELLO_OBJ));
3578     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3579                         "Length: %u", obj_length);
3580     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
3581                         "Class number: %u - %s",
3582                         class, type_str);
3583     switch(type) {
3584     case 1:
3585     case 2:
3586         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3587                             "C-Type: 1 - HELLO %s object",
3588                             type==1 ? "REQUEST" : "ACK");
3589         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 4,
3590                             "Source Instance: 0x%x",tvb_get_ntohl(tvb, offset+4));
3591         proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
3592                             "Destination Instance: 0x%x",tvb_get_ntohl(tvb, offset+8));
3593         proto_item_append_text(ti, ": %s. Src Instance: 0x%0x. Dest Instance: 0x%0x. ", 
3594                                type==1 ? "REQUEST" : "ACK", 
3595                                tvb_get_ntohl(tvb, offset+4),
3596                                tvb_get_ntohl(tvb, offset+8));
3597         break;
3598     default:
3599         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3600                             "C-Type: %d - UNKNOWN", type);
3601         break;
3602     };
3603 }
3604
3605 /*------------------------------------------------------------------------------
3606  * DCLASS
3607  *------------------------------------------------------------------------------*/
3608 static void
3609 dissect_rsvp_dclass (proto_tree *ti, tvbuff_t *tvb,
3610                      int offset, int obj_length,
3611                      int class, int type,
3612                      char *type_str)
3613 {
3614     int offset2 = offset + 4;
3615     proto_tree *rsvp_object_tree;
3616     int mylen;
3617
3618     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_DCLASS));
3619     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3620                         "Length: %u", obj_length);
3621     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
3622                         "Class number: %u - %s",
3623                         class, type_str);
3624     proto_item_set_text(ti, "DCLASS: ");
3625     switch(type) {
3626     case 1:
3627         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3628                             "C-type: 1");
3629         for (mylen = 4; mylen < obj_length; mylen += 4) {
3630             proto_tree_add_text(rsvp_object_tree, tvb, offset+mylen+3, 1,
3631                                 "DSCP: %s",
3632                                 val_to_str(tvb_get_guint8(tvb, offset+mylen+3),
3633                                            dscp_vals, "Unknown (%d)"));
3634             proto_item_append_text(ti, "%d%s",
3635                                    tvb_get_guint8(tvb, offset+mylen+3)>>2,
3636                                    mylen==obj_length-4 ? "":
3637                                    mylen<16 ? ", ":
3638                                    mylen==16 ? ", ..." : "");
3639         }
3640         break;
3641
3642     default:
3643         mylen = obj_length - 4;
3644         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3645                             "C-type: Unknown (%u)",
3646                             type);
3647         proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
3648                             "Data (%d bytes)", mylen);
3649         break;
3650     }
3651 }
3652
3653 /*------------------------------------------------------------------------------
3654  * ADMINISTRATIVE STATUS
3655  *------------------------------------------------------------------------------*/
3656 static void
3657 dissect_rsvp_admin_status (proto_tree *ti, tvbuff_t *tvb,
3658                            int offset, int obj_length,
3659                            int class, int type,
3660                            char *type_str)
3661 {
3662     int offset2 = offset + 4;
3663     proto_tree *rsvp_object_tree;
3664     proto_tree *ti2, *rsvp_admin_subtree;
3665     int mylen;
3666     guint32 status;
3667     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_ADMIN_STATUS));
3668     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3669                         "Length: %u", obj_length);
3670     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
3671                         "Class number: %u - %s",
3672                         class, type_str);
3673     proto_item_set_text(ti, "ADMIN STATUS: ");
3674     switch(type) {
3675     case 1:
3676         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3677                             "C-type: 1");
3678         status = tvb_get_ntohl(tvb, offset2);
3679         ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
3680                                   "Admin Status: 0x%08x", status);
3681         rsvp_admin_subtree =
3682             proto_item_add_subtree(ti2, TREE(TT_ADMIN_STATUS_FLAGS));
3683         proto_tree_add_text(rsvp_admin_subtree, tvb, offset2, 4,
3684                             decode_boolean_bitfield(status, 0x80000000, 32,
3685                                                     "R: Reflect",
3686                                                     "R: Do not reflect"));
3687         proto_tree_add_text(rsvp_admin_subtree, tvb, offset2, 4,
3688                             decode_boolean_bitfield(status, 0x04, 32,
3689                                                     "T: Testing",
3690                                                     "T: "));
3691         proto_tree_add_text(rsvp_admin_subtree, tvb, offset2, 4,
3692                             decode_boolean_bitfield(status, 0x02, 32,
3693                                                     "A: Administratively Down",
3694                                                     "A: "));
3695         proto_tree_add_text(rsvp_admin_subtree, tvb, offset2, 4,
3696                             decode_boolean_bitfield(status, 0x01, 32,
3697                                                     "D: Delete In Progress",
3698                                                     "D: "));
3699         proto_item_set_text(ti, "ADMIN-STATUS: %s %s %s %s",
3700                             (status & (1<<31)) ? "Reflect" : "",
3701                             (status & (1<<2))  ? "Testing" : "",
3702                             (status & (1<<1))  ? "Admin-Down" : "",
3703                             (status & (1<<0))  ? "Deleting" : "");
3704         break;
3705
3706     default:
3707         mylen = obj_length - 4;
3708         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3709                             "C-type: Unknown (%u)",
3710                             type);
3711         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
3712                             "Data (%d bytes)", obj_length - 4);
3713         break;
3714     }
3715 }
3716
3717 /*------------------------------------------------------------------------------
3718  * LSP TUNNEL INTERFACE ID
3719  *------------------------------------------------------------------------------*/
3720 static void
3721 dissect_rsvp_lsp_tunnel_if_id (proto_tree *ti, tvbuff_t *tvb,
3722                                int offset, int obj_length,
3723                                int class, int type,
3724                                char *type_str)
3725 {
3726     int offset2 = offset + 4;
3727     proto_tree *rsvp_object_tree;
3728
3729     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_LSP_TUNNEL_IF_ID));
3730     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3731                         "Length: %u", obj_length);
3732     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
3733                         "Class number: %u - %s",
3734                         class, type_str);
3735     proto_item_set_text(ti, "LSP INTERFACE-ID: ");
3736     switch(type) {
3737     case 1:
3738         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3739                             "C-type: 1 - IPv4");
3740         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
3741                             "Router ID: %s",
3742                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
3743         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
3744                             "Interface ID: %u", tvb_get_ntohl(tvb, offset2+4));
3745         proto_item_set_text(ti, "LSP INTERFACE-ID: IPv4, Router-ID %s, Interface-ID %d",
3746                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)),
3747                             tvb_get_ntohl(tvb, offset2+4));
3748         break;
3749
3750     default:
3751         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3752                             "C-type: Unknown (%u)",
3753                             type);
3754         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
3755                             "Data (%d bytes)", obj_length - 4);
3756         break;
3757     }
3758 }
3759
3760 /*------------------------------------------------------------------------------
3761  * GENERALIZED UNI
3762  *------------------------------------------------------------------------------*/
3763 static void
3764 dissect_rsvp_gen_uni (proto_tree *ti, tvbuff_t *tvb,
3765                       int offset, int obj_length,
3766                       int class, int type,
3767                       char *type_str)
3768 {
3769     int offset2 = offset + 4;
3770     proto_tree *rsvp_object_tree;
3771     int mylen, i, j, k, l, m;
3772     proto_tree *ti2, *rsvp_gen_uni_subtree;
3773     int s_len, s_class, s_type;
3774
3775     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_GEN_UNI));
3776     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3777                         "Length: %u", obj_length);
3778     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
3779                         "Class number: %u - %s",
3780                         class, type_str);
3781     proto_item_set_text(ti, "GENERALIZED UNI: ");
3782
3783     mylen = obj_length - 4;
3784     switch(type) {
3785     case 1: {
3786         char *c;
3787         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3788                             "C-type: 1");
3789         for (i=1, l = 0; l < mylen; i++) {
3790             j = tvb_get_guint8(tvb, offset2+l+2);
3791             switch(j) {
3792             case 1:
3793             case 2: /* We do source and destination TNA together */
3794                 c = (j==1) ? "Source" : "Destination";
3795                 k = tvb_get_guint8(tvb, offset2+l+3);
3796                 switch(k) {
3797                 case 1:
3798                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3799                                               offset2+l, 8,
3800                                               "%s IPv4 TNA - %s", c,
3801                                               ip_to_str(tvb_get_ptr(tvb, offset2+l+4, 4)));
3802                     rsvp_gen_uni_subtree =
3803                         proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
3804                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
3805                                         "Class: %d (%s)", j, c);
3806                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
3807                                         "Type: 1 (IPv4)");
3808                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
3809                                         "Length: %u",
3810                                         tvb_get_ntohs(tvb, offset2+l));
3811                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 4,
3812                                         "IPv4 hop: %s",
3813                                         ip_to_str(tvb_get_ptr(tvb, offset2+l+4, 4)));
3814                     if (i < 4) {
3815                         proto_item_append_text(ti, "%s IPv4 %s", c,
3816                                                ip_to_str(tvb_get_ptr(tvb, offset2+l+2, 4)));
3817                     }
3818                     break;
3819
3820                 case 2:
3821                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3822                                               offset2+l, 20,
3823                                               "%s IPv6 TNA", c);
3824                     rsvp_gen_uni_subtree =
3825                         proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
3826                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
3827                                         "Class: %d (%s)", j, c);
3828                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
3829                                         "Type: 2 (IPv6)");
3830                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
3831                                         "Length: %u",
3832                                         tvb_get_ntohs(tvb, offset2+l));
3833                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 4,
3834                                         "Data");
3835                     if (i < 4) {
3836                         proto_item_append_text(ti, "%s IPv6", c);
3837                     }
3838                     break;
3839
3840                 case 3:
3841                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3842                                               offset2+l, tvb_get_ntohs(tvb, offset2+l),
3843                                               "%s NSAP TNA", c);
3844                     rsvp_gen_uni_subtree =
3845                         proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
3846                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
3847                                         "Class: %d (%s)", j, c);
3848                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
3849                                         "Type: 3 (NSAP)");
3850                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
3851                                         "Length: %u",
3852                                         tvb_get_ntohs(tvb, offset2+l));
3853                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4,
3854                                         tvb_get_ntohs(tvb, offset2+l)-4,
3855                                         "Data");
3856                     if (i < 4) {
3857                         proto_item_append_text(ti, "%s NSAP", c);
3858                     }
3859                     break;
3860
3861                 default:
3862                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3863                                               offset2+l, tvb_get_ntohs(tvb, offset2+l),
3864                                               "%s UNKNOWN TNA", c);
3865                     rsvp_gen_uni_subtree =
3866                         proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
3867                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
3868                                         "Class: %d (%s)", j, c);
3869                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
3870                                         "Type: %d (UNKNOWN)", j);
3871                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
3872                                         "Length: %u",
3873                                         tvb_get_ntohs(tvb, offset2+l));
3874                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4,
3875                                         tvb_get_ntohs(tvb, offset2+l)-4,
3876                                         "Data");
3877                     if (i < 4) {
3878                         proto_item_append_text(ti, "%s UNKNOWN", c);
3879                     }
3880                     break;
3881                 }
3882                 break;
3883
3884             case 3: /* Diversity subobject */
3885                 k = tvb_get_guint8(tvb, offset2+l+3);
3886                 switch(k) {
3887                 default:
3888                 case 1:
3889                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3890                                               offset2+l, tvb_get_ntohs(tvb, offset2+l),
3891                                               "Diversity Subobject");
3892                     rsvp_gen_uni_subtree =
3893                         proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
3894                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
3895                                         "Class: %d (Diversity)", j);
3896                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
3897                                         "Type: %d", tvb_get_guint8(tvb, offset2+l+3));
3898                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
3899                                         "Length: %u",
3900                                         tvb_get_ntohs(tvb, offset2+l));
3901                     m = tvb_get_guint8(tvb, offset2+l+4) >> 4;
3902                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 1,
3903                                         "Diversity: %d - %s", m,
3904                                         val_to_str(m, ouni_guni_diversity_str, "Unknown"));
3905                     s_len = tvb_get_ntohs(tvb, offset2+l+8);
3906                     s_class = tvb_get_guint8(tvb, offset2+l+10);
3907                     s_type = tvb_get_guint8(tvb, offset2+l+11);
3908                     ti2 = proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+8,
3909                                               s_len, "Session");
3910                     dissect_rsvp_session(ti2, tvb, offset2+l+8, s_len, s_class, s_type,
3911                                          val_to_str(s_class, rsvp_class_vals, "Unknown"));
3912                     offset2 += s_len;
3913                     s_len = tvb_get_ntohs(tvb, offset2+l+8);
3914                     s_class = tvb_get_guint8(tvb, offset2+l+10);
3915                     s_type = tvb_get_guint8(tvb, offset2+l+11);
3916                     ti2 = proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+8,
3917                                               s_len, "Template");
3918                     dissect_rsvp_template_filter(ti2, tvb, offset2+l+8, s_len, s_class, s_type,
3919                                                  val_to_str(s_class, rsvp_class_vals, "Unknown"));
3920
3921                     if (i < 4) {
3922                         proto_item_append_text(ti, "Diversity");
3923                     }
3924                     break;
3925
3926                 }
3927                 break;
3928
3929             case 4: /* Egress Label */
3930                 k = tvb_get_guint8(tvb, offset2+l+3);
3931                 if (k == 1)             /* Egress label sub-type */
3932                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3933                                               offset2+l, tvb_get_ntohs(tvb, offset2+l),
3934                                               "Egress Label Subobject");
3935                 else if (k == 2)        /* SPC_label sub-type (see G.7713.2) */
3936                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3937                                               offset2+l, tvb_get_ntohs(tvb, offset2+l),
3938                                               "SPC Label Subobject");
3939                 else
3940                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3941                                               offset2+l, tvb_get_ntohs(tvb, offset2+l),
3942                                               "Unknown Label Subobject");
3943                 rsvp_gen_uni_subtree = proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
3944                 proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
3945                                     "Class: %d (Egress/SPC Label)", j);
3946                 proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
3947                                     "Type: %d", k);
3948                 proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
3949                                     "Length: %u",
3950                                     tvb_get_ntohs(tvb, offset2+l));
3951                 proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 1,
3952                                     "Direction: %s",
3953                                     decode_boolean_bitfield(
3954                                         tvb_get_guint8(tvb, offset2+l+4), 0x80, 8,
3955                                         "U: 1 - Upstream label/port ID",
3956                                         "U: 0 - Downstream label/port ID"));
3957                 proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+7, 1,
3958                                     "Label type: %u", tvb_get_guint8(tvb, offset2+l+7));
3959                 proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+8, 4,
3960                                     "Logical Port ID: %u", tvb_get_ntohl(tvb, offset2+l+8));
3961                 proto_item_append_text(ti2, ": %s, Label type %d, Port ID %d, Label ",
3962                                        tvb_get_guint8(tvb, offset2+l+4) & 0x80 ?
3963                                        "Upstream" : "Downstream",
3964                                        tvb_get_guint8(tvb, offset2+l+7),
3965                                        tvb_get_ntohl(tvb, offset2+l+8));
3966                 for (j=12; j < tvb_get_ntohs(tvb, offset2+l); j+=4) {
3967                         proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+8, 4,
3968                                             "Label: %u", tvb_get_ntohl(tvb, offset2+l+j));
3969                         proto_item_append_text(ti2, "%u ", tvb_get_ntohl(tvb, offset2+l+j));
3970                 }
3971                 if (i < 4) {
3972                         if (k == 1)
3973                             proto_item_append_text(ti, "Egress Label");
3974                         else if (k == 2)
3975                             proto_item_append_text(ti, "SPC Label");
3976                 }
3977                 break;
3978
3979             case 5: /* Service Level */
3980                 k = tvb_get_guint8(tvb, offset2+l+3);
3981                 switch(k) {
3982                 default:
3983                 case 1:
3984                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3985                                               offset2+l, tvb_get_ntohs(tvb, offset2+l),
3986                                               "Service Level Subobject");
3987                     rsvp_gen_uni_subtree =
3988                         proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
3989                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
3990                                         "Class: %d (Egress Label)", j);
3991                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
3992                                         "Type: %d", tvb_get_guint8(tvb, offset2+l+3));
3993                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
3994                                         "Length: %u",
3995                                         tvb_get_ntohs(tvb, offset2+l));
3996                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 1,
3997                                         "Service Level: %u", tvb_get_guint8(tvb, offset2+l+4));
3998                     proto_item_append_text(ti2, ": %u", tvb_get_guint8(tvb, offset2+l+4));
3999                     if (i < 4) {
4000                         proto_item_append_text(ti, "Service Level %d", tvb_get_guint8(tvb, offset2+l+4));
4001                     }
4002                     break;
4003                 }
4004                 break;
4005
4006             default: /* Unknown subobject */
4007                 ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
4008                                           offset2+l,
4009                                           tvb_get_ntohs(tvb, offset2+l),
4010                                           "Unknown subobject: %u",
4011                                           j);
4012                 rsvp_gen_uni_subtree =
4013                     proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
4014                 proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 1,
4015                                     "Type: %u (Unknown)", j);
4016                 proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+1, 1,
4017                                     "Length: %u",
4018                                     tvb_get_guint8(tvb, offset2+l+1));
4019
4020             }
4021
4022             l += tvb_get_guint8(tvb, offset2+l+1);
4023             if (l < mylen) {
4024                 if (i < 4)
4025                     proto_item_append_text(ti, ", ");
4026                 else if (i==4)
4027                     proto_item_append_text(ti, "...");
4028             }
4029         }
4030         break;
4031     }
4032
4033     default:
4034         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4035                             "C-type: Unknown (%u)",
4036                             type);
4037         proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
4038                             "Data (%d bytes)", mylen);
4039         break;
4040     }
4041 }
4042
4043 /*------------------------------------------------------------------------------
4044  * CALL_ID
4045  *------------------------------------------------------------------------------*/
4046 static void
4047 dissect_rsvp_call_id (proto_tree *ti, tvbuff_t *tvb,
4048                           int offset, int obj_length,
4049                           int class, int c_type,
4050                           char *type_str)
4051 {
4052     int type;
4053     char *str;
4054     int offset2 = offset + 4;
4055     int offset3, offset4, len;
4056     proto_tree *rsvp_object_tree;
4057
4058     static value_string address_type_vals[] = {
4059       {1, "1 (IPv4)"},
4060       {2, "2 (IPv6)"},
4061       {3, "3 (NSAP)"},
4062       {4, "4 (MAC)"},
4063       {0x7f, "0x7f (Vendor-defined)"},
4064       {0, NULL}
4065 };
4066
4067     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_CALL_ID));
4068     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
4069                         "Length: %u", obj_length);
4070     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
4071                         "Class number: %u - %s",
4072                         class, type_str);
4073     proto_item_set_text(ti, "CALL-ID");
4074     type = tvb_get_guint8 (tvb, offset2);
4075     switch(c_type) {
4076     case 1:
4077     case 2:
4078         if (c_type == 1) {
4079           offset3 = offset2 + 4;
4080           len = obj_length - 16;
4081           proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4082                             "C-type: 1 (operator specific)");
4083           proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1, "Address type: %s",
4084                               val_to_str(type, address_type_vals, "Unknown (%u)"));
4085           proto_tree_add_text(rsvp_object_tree, tvb, offset2+1, 3, "Reserved: %u",
4086                               tvb_get_ntoh24(tvb, offset2+1));
4087         }
4088         else {
4089           offset3 = offset2 + 16;
4090           len = obj_length - 28;
4091           proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4092                             "C-type: 2 (globally unique)");
4093           proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1, "Address type: %s",
4094                               val_to_str(type, address_type_vals, "Unknown (%u)"));
4095           str = tvb_get_string (tvb, offset2 + 1, 3);  
4096           proto_tree_add_text(rsvp_object_tree, tvb, offset2 + 1, 3,
4097                               "International Segment: %s", str); 
4098           g_free (str);
4099           str = tvb_get_string (tvb, offset2 + 4, 12);  
4100           proto_tree_add_text(rsvp_object_tree, tvb, offset2 + 4, 12,
4101                               "National Segment: %s", str); 
4102           g_free (str);
4103         }
4104
4105         switch(type) {
4106         case 1:
4107           offset4 = offset3 + 4;
4108           proto_tree_add_text(rsvp_object_tree, tvb, offset3, 4, "Source Transport Network addr: %s",
4109                               ip_to_str(tvb_get_ptr(tvb, offset3, 4)));
4110           break;
4111           
4112         case 2:
4113           offset4 = offset3 + 16;
4114           proto_tree_add_text(rsvp_object_tree, tvb, offset3, 16, "Source Transport Network addr: %s",
4115                               ip6_to_str((const struct e_in6_addr *) tvb_get_ptr(tvb, offset3, 16)));
4116           break;
4117           
4118         case 3:
4119           offset4 = offset3 + 20;
4120           proto_tree_add_text(rsvp_object_tree, tvb, offset3, 20, "Source Transport Network addr: %s",
4121                               tvb_bytes_to_str(tvb, offset3, 20));
4122           break;
4123           
4124         case 4:
4125           offset4 = offset3 + 6;
4126           proto_tree_add_text(rsvp_object_tree, tvb, offset3, 6, "Source Transport Network addr: %s",
4127                               tvb_bytes_to_str(tvb, offset3, 6));
4128           break;
4129           
4130         case 0x7F:
4131           offset4 = offset3 + len;
4132           proto_tree_add_text(rsvp_object_tree, tvb, offset3, len, "Source Transport Network addr: %s",
4133                               tvb_bytes_to_str(tvb, offset3, len));
4134           break;
4135
4136         default:
4137           offset4 = offset3 + len;
4138           proto_tree_add_text(rsvp_object_tree, tvb, offset3, len, "Unknow Transport Network type: %d",
4139                               type);
4140         }
4141
4142         proto_tree_add_text(rsvp_object_tree, tvb, offset4, 8, "Local Identifier: %s",
4143                             tvb_bytes_to_str(tvb, offset4, 8));
4144         break;
4145
4146     default:
4147         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4148                             "C-type: Unknown (%u)", type);
4149         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
4150                             "Data (%d bytes)", obj_length - 4);
4151         break;
4152     }
4153 }
4154
4155 /*------------------------------------------------------------------------------
4156  * RESTART CAPABILITY
4157  *------------------------------------------------------------------------------*/
4158 static void
4159 dissect_rsvp_restart_cap (proto_tree *ti, tvbuff_t *tvb,
4160                           int offset, int obj_length,
4161                           int class, int type,
4162                           char *type_str)
4163 {
4164     int offset2 = offset + 4;
4165     proto_tree *rsvp_object_tree;
4166
4167     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_RESTART_CAP));
4168     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
4169                         "Length: %u", obj_length);
4170     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
4171                         "Class number: %u - %s",
4172                         class, type_str);
4173     proto_item_set_text(ti, "RESTART CAPABILITY: ");
4174     switch(type) {
4175     case 1:
4176         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4177                             "C-type: 1");
4178         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
4179                             "Restart Time: %d ms", 
4180                             tvb_get_ntohl(tvb, offset2));
4181         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
4182                             "Recovery Time: %d ms", 
4183                             tvb_get_ntohl(tvb, offset2+4));
4184         proto_item_append_text(ti, "Restart Time: %d ms. Recovery Time: %d ms.",
4185                             tvb_get_ntohl(tvb, offset2), tvb_get_ntohl(tvb, offset2+4));
4186         break;
4187
4188     default:
4189         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4190                             "C-type: Unknown (%u)",
4191                             type);
4192         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
4193                             "Data (%d bytes)", obj_length - 4);
4194         break;
4195     }
4196 }
4197
4198 /*------------------------------------------------------------------------------
4199  * PROTECTION INFORMATION
4200  *------------------------------------------------------------------------------*/
4201 static void
4202 dissect_rsvp_protection_info (proto_tree *ti, tvbuff_t *tvb,
4203                               int offset, int obj_length,
4204                               int class, int type,
4205                               char *type_str)
4206 {
4207     int offset2 = offset + 4;
4208     proto_tree *rsvp_object_tree;
4209
4210     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_PROTECTION_INFO));
4211     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
4212                         "Length: %u", obj_length);
4213     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
4214                         "Class number: %u - %s",
4215                         class, type_str);
4216     proto_item_set_text(ti, "PROTECTION_INFO: ");
4217     switch(type) {
4218     case 1:
4219         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4220                             "C-type: 1 - IPv4");
4221         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
4222                             "Router ID: %s",
4223                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
4224         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
4225                             "Interface ID: %u", tvb_get_ntohl(tvb, offset2+4));
4226         proto_item_append_text(ti, "Router-ID %s, Interface-ID %d",
4227                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)),
4228                             tvb_get_ntohl(tvb, offset2+4));
4229         break;
4230
4231     default:
4232         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4233                             "C-type: Unknown (%u)",
4234                             type);
4235         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
4236                             "Data (%d bytes)", obj_length - 4);
4237         break;
4238     }
4239 }
4240
4241 /*------------------------------------------------------------------------------
4242  * FAST REROUTE
4243  *------------------------------------------------------------------------------*/
4244 static void
4245 dissect_rsvp_fast_reroute (proto_tree *ti, tvbuff_t *tvb,
4246                            int offset, int obj_length,
4247                            int class, int type,
4248                            char *type_str)
4249 {
4250     proto_tree *rsvp_object_tree;
4251     guint8 flags;
4252     proto_tree *ti2, *rsvp_frr_flags_tree;
4253
4254     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_FAST_REROUTE));
4255     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
4256                         "Length: %u", obj_length);
4257     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
4258                         "Class number: %u - %s",
4259                         class, type_str);
4260     proto_item_set_text(ti, "FAST_REROUTE: ");
4261     switch(type) {
4262     case 1:
4263     case 7:
4264         if ((type==1 && obj_length!=24) || (type==7 && obj_length!=20)) {
4265             proto_tree_add_text(rsvp_object_tree, tvb, offset, obj_length, 
4266                                 "<<<Invalid length: cannot decode>>>");
4267             proto_item_append_text(ti, "Invalid length");
4268             break;
4269         }
4270         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4271                             "C-type: %u", type);
4272         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1, 
4273                             "Setup Priority: %d", tvb_get_guint8(tvb, offset+4));
4274         proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 1, 
4275                             "Hold Priority: %d", tvb_get_guint8(tvb, offset+5));
4276         proto_tree_add_text(rsvp_object_tree, tvb, offset+6, 1, 
4277                             "Hop Limit: %d", tvb_get_guint8(tvb, offset+6));
4278
4279         flags = tvb_get_guint8(tvb, offset+7);
4280         ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset+7, 1, 
4281                                   "Flags: 0x%02x", flags);
4282         rsvp_frr_flags_tree = proto_item_add_subtree(ti2,
4283                                                      TREE(TT_FAST_REROUTE_FLAGS));
4284         proto_tree_add_text(rsvp_frr_flags_tree, tvb, offset+7, 1,
4285                             decode_boolean_bitfield(flags, 0x01, 8,
4286                                                     "One-to-One Backup desired",
4287                                                     "One-to-One Backup not desired"));
4288         proto_tree_add_text(rsvp_frr_flags_tree, tvb, offset+7, 1,
4289                             decode_boolean_bitfield(flags, 0x02, 8,
4290                                                     "Facility Backup desired",
4291                                                     "Facility Backup not desired"));
4292         proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4, 
4293                             "Bandwidth: %.10g", tvb_get_ntohieee_float(tvb, offset+8));
4294         proto_tree_add_text(rsvp_object_tree, tvb, offset+12, 4, 
4295                             "Exclude-Any: 0x%0x", tvb_get_ntohl(tvb, offset+12));
4296         proto_tree_add_text(rsvp_object_tree, tvb, offset+16, 4, 
4297                             "Include-Any: 0x%0x", tvb_get_ntohl(tvb, offset+16));
4298         if (type==1) {
4299             proto_tree_add_text(rsvp_object_tree, tvb, offset+20, 4, 
4300                                 "Include-All: 0x%0x", tvb_get_ntohl(tvb, offset+20));
4301         }
4302
4303         proto_item_append_text(ti, "%s%s",
4304                                flags &0x01 ? "One-to-One Backup, " : "",
4305                                flags &0x02 ? "Facility Backup" : "");
4306         break;
4307
4308     default:
4309         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4310                             "C-type: Unknown (%u)",
4311                             type);
4312         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, obj_length - 4,
4313                             "Data (%d bytes)", obj_length - 4);
4314         break;
4315     }
4316 }
4317
4318 /*------------------------------------------------------------------------------
4319  * DETOUR
4320  *------------------------------------------------------------------------------*/
4321 static void
4322 dissect_rsvp_detour (proto_tree *ti, tvbuff_t *tvb,
4323                      int offset, int obj_length,
4324                      int class, int type,
4325                      char *type_str)
4326 {
4327     proto_tree *rsvp_object_tree;
4328     int remaining_length, count;
4329     int iter;
4330
4331     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_DETOUR));
4332     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
4333                         "Length: %u", obj_length);
4334     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
4335                         "Class number: %u - %s",
4336                         class, type_str);
4337     proto_item_set_text(ti, "DETOUR: ");
4338     switch(type) {
4339     case 7:
4340         iter = 0;
4341         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4342                             "C-type: %u", type);
4343         for (remaining_length = obj_length - 4, count = 1;
4344              remaining_length > 0; remaining_length -= 8, count++) {
4345             if (remaining_length < 8) {
4346                 proto_tree_add_text(rsvp_object_tree, tvb, offset+remaining_length, 
4347                                     obj_length-remaining_length, 
4348                                     "<<<Invalid length: cannot decode>>>");
4349                 proto_item_append_text(ti, "Invalid length");
4350                 break;
4351             }
4352             iter++;
4353             proto_tree_add_text(rsvp_object_tree, tvb, offset+(4*iter), 4,
4354                                 "PLR ID %d: %s", count, 
4355                                 ip_to_str(tvb_get_ptr(tvb, offset+(4*iter), 4)));
4356             iter++;
4357             proto_tree_add_text(rsvp_object_tree, tvb, offset+(4*iter), 4,
4358                                 "Avoid Node ID %d: %s", count, 
4359                                 ip_to_str(tvb_get_ptr(tvb, offset+(4*iter), 4)));
4360         }
4361         break;
4362
4363     default:
4364         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4365                             "C-type: Unknown (%u)",
4366                             type);
4367         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, obj_length - 4,
4368                             "Data (%d bytes)", obj_length - 4);
4369         break;
4370     }
4371 }
4372
4373 /*------------------------------------------------------------------------------
4374  * DIFFSERV
4375  *------------------------------------------------------------------------------*/
4376 static void
4377 dissect_rsvp_diffserv (proto_tree *ti, tvbuff_t *tvb,
4378                        int offset, int obj_length,
4379                        int class, int type,
4380                        char *type_str
4381                        )
4382 {
4383     proto_tree *rsvp_object_tree;
4384     int mapnb, count;
4385     int *hfindexes[] = {
4386         &rsvp_filter[RSVPF_DIFFSERV_MAP],
4387         &rsvp_filter[RSVPF_DIFFSERV_MAP_EXP],
4388         &rsvp_filter[RSVPF_DIFFSERV_PHBID],
4389         &rsvp_filter[RSVPF_DIFFSERV_PHBID_DSCP],
4390         &rsvp_filter[RSVPF_DIFFSERV_PHBID_CODE],
4391         &rsvp_filter[RSVPF_DIFFSERV_PHBID_BIT14],
4392         &rsvp_filter[RSVPF_DIFFSERV_PHBID_BIT15]
4393     };
4394     gint *etts[] = {
4395         &TREE(TT_DIFFSERV_MAP),
4396         &TREE(TT_DIFFSERV_MAP_PHBID)
4397     };
4398
4399     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_DIFFSERV));
4400     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
4401                         "Length: %u", obj_length);
4402     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
4403                         "Class number: %u - %s",
4404                         class, type_str);
4405     proto_item_set_text(ti, "DIFFSERV: ");
4406     offset += 3;
4407     switch (type) {
4408     case 1:
4409         proto_tree_add_text(rsvp_object_tree, tvb, offset, 1,
4410                             "C-type: 1 - E-LSP");
4411         proto_tree_add_uint(rsvp_object_tree, rsvp_filter[RSVPF_DIFFSERV_MAPNB],
4412                             tvb, offset + 4, 1,
4413                             mapnb = tvb_get_guint8(tvb, offset + 4) & 15);
4414         proto_item_append_text(ti, "E-LSP, %u MAP%s", mapnb,
4415                                (mapnb == 0) ? "" : "s");
4416         offset += 5;
4417
4418         for (count = 0; count < mapnb; count++) {
4419             dissect_diffserv_mpls_common(tvb, rsvp_object_tree, type,
4420                                          offset, hfindexes, etts);
4421             offset += 4;
4422         }
4423         break;
4424     case 2:
4425         proto_item_append_text(ti, "L-LSP");
4426         proto_tree_add_text(rsvp_object_tree, tvb, offset, 1,
4427                             "C-type: 2 - L-LSP");
4428         dissect_diffserv_mpls_common(tvb, rsvp_object_tree, type,
4429                                      offset + 3, hfindexes, etts);
4430         break;
4431     default:
4432         proto_tree_add_text(rsvp_object_tree, tvb, offset, 1,
4433                             "C-type: Unknown (%u)", type);
4434         proto_tree_add_text(rsvp_object_tree, tvb, offset + 1, obj_length - 4,
4435                             "Data (%d bytes)", obj_length - 4);
4436     }
4437 }
4438
4439 /*------------------------------------------------------------------------------
4440  * Dissect a single RSVP message in a tree
4441  *------------------------------------------------------------------------------*/
4442 static void
4443 dissect_rsvp_msg_tree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4444                       int tree_mode)
4445 {
4446     proto_tree *rsvp_tree = NULL;
4447     proto_tree *rsvp_header_tree;
4448     proto_tree *rsvp_object_tree;
4449     proto_tree *ti;
4450     guint16 cksum, computed_cksum;
4451     vec_t cksum_vec[1];
4452     int offset = 0;
4453     int len;
4454     guint8 ver_flags;
4455     guint8 message_type;
4456     int session_off, tempfilt_off;
4457     int msg_length;
4458     int obj_length;
4459     int offset2;
4460
4461     offset = 0;
4462     len = 0;
4463     ver_flags = tvb_get_guint8(tvb, 0);
4464     msg_length = tvb_get_ntohs(tvb, 6);
4465     message_type = tvb_get_guint8(tvb, 1);
4466
4467     ti = proto_tree_add_item(tree, proto_rsvp, tvb, offset, msg_length,
4468                              FALSE);
4469     rsvp_tree = proto_item_add_subtree(ti, tree_mode);
4470     proto_item_append_text(rsvp_tree, ": ");
4471     proto_item_append_text(rsvp_tree, val_to_str(message_type, message_type_vals,
4472                                                  "Unknown (%u). "));
4473     find_rsvp_session_tempfilt(tvb, 0, &session_off, &tempfilt_off);
4474     if (session_off)
4475         proto_item_append_text(rsvp_tree, summary_session(tvb, session_off));
4476     if (tempfilt_off)
4477         proto_item_append_text(rsvp_tree, summary_template(tvb, tempfilt_off));
4478
4479     ti = proto_tree_add_text(rsvp_tree, tvb, offset, 8, "RSVP Header. %s",
4480                              val_to_str(message_type, message_type_vals,
4481                                         "Unknown Message (%u). "));
4482     rsvp_header_tree = proto_item_add_subtree(ti, TREE(TT_HDR));
4483
4484     proto_tree_add_text(rsvp_header_tree, tvb, offset, 1, "RSVP Version: %u",
4485                         (ver_flags & 0xf0)>>4);
4486     proto_tree_add_text(rsvp_header_tree, tvb, offset, 1, "Flags: %02x",
4487                         ver_flags & 0xf);
4488     proto_tree_add_uint(rsvp_header_tree, rsvp_filter[RSVPF_MSG], tvb,
4489                         offset+1, 1, message_type);
4490     switch (RSVPF_MSG + message_type) {
4491
4492     case RSVPF_PATH:
4493     case RSVPF_RESV:
4494     case RSVPF_PATHERR:
4495     case RSVPF_RESVERR:
4496     case RSVPF_PATHTEAR:
4497     case RSVPF_RESVTEAR:
4498     case RSVPF_RCONFIRM:
4499     case RSVPF_RTEARCONFIRM:
4500     case RSVPF_BUNDLE:
4501     case RSVPF_ACK:
4502     case RSVPF_SREFRESH:
4503     case RSVPF_HELLO:
4504         proto_tree_add_boolean_hidden(rsvp_header_tree, rsvp_filter[RSVPF_MSG + message_type], tvb,
4505                                       offset+1, 1, 1);
4506         break;
4507
4508     default:
4509         proto_tree_add_protocol_format(rsvp_header_tree, proto_malformed, tvb, offset+1, 1,
4510                                        "Invalid message type: %u", message_type);
4511         return;
4512     }
4513
4514     cksum = tvb_get_ntohs(tvb, offset+2);
4515     if (!pinfo->fragmented && (int) tvb_length(tvb) >= msg_length) {
4516         /* The packet isn't part of a fragmented datagram and isn't
4517            truncated, so we can checksum it. */
4518         cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, msg_length);
4519         cksum_vec[0].len = msg_length;
4520         computed_cksum = in_cksum(&cksum_vec[0], 1);
4521         if (computed_cksum == 0) {
4522             proto_tree_add_text(rsvp_header_tree, tvb, offset+2, 2,
4523                                 "Message Checksum: 0x%04x (correct)",
4524                                 cksum);
4525         } else {
4526             proto_tree_add_text(rsvp_header_tree, tvb, offset+2, 2,
4527                                 "Message Checksum: 0x%04x (incorrect, should be 0x%04x)",
4528                                 cksum,
4529                                 in_cksum_shouldbe(cksum, computed_cksum));
4530         }
4531     } else {
4532         proto_tree_add_text(rsvp_header_tree, tvb, offset+2, 2,
4533                             "Message Checksum: 0x%04x",
4534                             cksum);
4535     }
4536     proto_tree_add_text(rsvp_header_tree, tvb, offset+4, 1,
4537                         "Sending TTL: %u",
4538                         tvb_get_guint8(tvb, offset+4));
4539     proto_tree_add_text(rsvp_header_tree, tvb, offset+6, 2,
4540                         "Message length: %u", msg_length);
4541
4542     offset = 8;
4543     len = 8;
4544
4545     if (message_type == RSVP_MSG_BUNDLE) {
4546         /* Bundle message. Dissect component messages */
4547         if (rsvp_bundle_dissect) {
4548             int len = 8;
4549             while (len < msg_length) {
4550                 gint sub_len;
4551                 tvbuff_t *tvb_sub;
4552                 sub_len = tvb_get_ntohs(tvb, len+6);
4553                 tvb_sub = tvb_new_subset(tvb, len, sub_len, sub_len);
4554                 dissect_rsvp_msg_tree(tvb_sub, pinfo, rsvp_tree, TREE(TT_BUNDLE_COMPMSG));
4555                 len += sub_len;
4556             }
4557         } else {
4558             proto_tree_add_text(rsvp_tree, tvb, offset, msg_length - len,
4559                                 "Bundle Component Messages Not Dissected");
4560         }
4561         return;
4562     }
4563
4564     while (len < msg_length) {
4565         guint8 class;
4566         guint8 type;
4567         char *type_str;
4568
4569         obj_length = tvb_get_ntohs(tvb, offset);
4570         class = tvb_get_guint8(tvb, offset+2);
4571         type = tvb_get_guint8(tvb, offset+3);
4572         type_str = val_to_str(class, rsvp_class_vals, "Unknown");
4573         proto_tree_add_uint_hidden(rsvp_tree, rsvp_filter[RSVPF_OBJECT], tvb,
4574                                    offset, obj_length, class);
4575         ti = proto_tree_add_item(rsvp_tree, rsvp_filter[rsvp_class_to_filter_num(class)],
4576                                  tvb, offset, obj_length, FALSE);
4577
4578         offset2 = offset+4;
4579
4580         switch(class) {
4581
4582         case RSVP_CLASS_SESSION:
4583             dissect_rsvp_session(ti, tvb, offset, obj_length, class, type, type_str);
4584             break;
4585
4586         case RSVP_CLASS_HOP:
4587             dissect_rsvp_hop(ti, tvb, offset, obj_length, class, type, type_str);
4588             break;
4589
4590         case RSVP_CLASS_TIME_VALUES:
4591             dissect_rsvp_time_values(ti, tvb, offset, obj_length, class, type, type_str);
4592             break;
4593
4594         case RSVP_CLASS_ERROR:
4595             dissect_rsvp_error(ti, tvb, offset, obj_length, class, type, type_str);
4596             break;
4597
4598         case RSVP_CLASS_SCOPE:
4599             dissect_rsvp_scope(ti, tvb, offset, obj_length, class, type, type_str);
4600             break;
4601
4602         case RSVP_CLASS_STYLE:
4603             dissect_rsvp_style(ti, tvb, offset, obj_length, class, type, type_str);
4604             break;
4605
4606         case RSVP_CLASS_CONFIRM:
4607             dissect_rsvp_confirm(ti, tvb, offset, obj_length, class, type, type_str);
4608             break;
4609
4610         case RSVP_CLASS_SENDER_TEMPLATE:
4611         case RSVP_CLASS_FILTER_SPEC:
4612             dissect_rsvp_template_filter(ti, tvb, offset, obj_length, class, type, type_str);
4613             break;
4614
4615         case RSVP_CLASS_SENDER_TSPEC:
4616             dissect_rsvp_tspec(ti, tvb, offset, obj_length, class, type, type_str);
4617             break;
4618
4619         case RSVP_CLASS_FLOWSPEC:
4620             dissect_rsvp_flowspec(ti, tvb, offset, obj_length, class, type, type_str);
4621             break;
4622
4623         case RSVP_CLASS_ADSPEC:
4624             dissect_rsvp_adspec(ti, tvb, offset, obj_length, class, type, type_str);
4625             break;
4626
4627         case RSVP_CLASS_INTEGRITY:
4628             dissect_rsvp_integrity(ti, tvb, offset, obj_length, class, type, type_str);
4629             break;
4630
4631         case RSVP_CLASS_POLICY:
4632             dissect_rsvp_policy(ti, tvb, offset, obj_length, class, type, type_str);
4633             break;
4634
4635         case RSVP_CLASS_LABEL_REQUEST:
4636             dissect_rsvp_label_request(ti, tvb, offset, obj_length, class, type, type_str);
4637             break;
4638
4639         case RSVP_CLASS_UPSTREAM_LABEL:
4640         case RSVP_CLASS_SUGGESTED_LABEL:
4641         case RSVP_CLASS_LABEL:
4642             dissect_rsvp_label(ti, tvb, offset, obj_length, class, type, type_str);
4643             break;
4644
4645         case RSVP_CLASS_LABEL_SET:
4646             dissect_rsvp_label_set(ti, tvb, offset, obj_length, class, type, type_str);
4647             break;
4648
4649         case RSVP_CLASS_SESSION_ATTRIBUTE:
4650             dissect_rsvp_session_attribute(ti, tvb, offset, obj_length, class, type, type_str);
4651             break;
4652
4653         case RSVP_CLASS_EXPLICIT_ROUTE:
4654             dissect_rsvp_explicit_route(ti, tvb, offset, obj_length, class, type, type_str);
4655             break;
4656
4657         case RSVP_CLASS_RECORD_ROUTE:
4658             dissect_rsvp_record_route(ti, tvb, offset, obj_length, class, type, type_str);
4659             break;
4660
4661         case RSVP_CLASS_MESSAGE_ID:
4662             dissect_rsvp_message_id(ti, tvb, offset, obj_length, class, type, type_str);
4663             break;
4664
4665         case RSVP_CLASS_MESSAGE_ID_ACK:
4666             dissect_rsvp_message_id_ack(ti, tvb, offset, obj_length, class, type, type_str);
4667             break;
4668
4669         case RSVP_CLASS_MESSAGE_ID_LIST:
4670             dissect_rsvp_message_id_list(ti, tvb, offset, obj_length, class, type, type_str);
4671             break;
4672
4673         case RSVP_CLASS_HELLO:
4674             dissect_rsvp_hello(ti, tvb, offset, obj_length, class, type, type_str);
4675             break;
4676
4677         case RSVP_CLASS_DCLASS:
4678             dissect_rsvp_dclass(ti, tvb, offset, obj_length, class, type, type_str);
4679             break;
4680
4681         case RSVP_CLASS_ADMIN_STATUS:
4682             dissect_rsvp_admin_status(ti, tvb, offset, obj_length, class, type, type_str);
4683             break;
4684
4685         case RSVP_CLASS_LSP_TUNNEL_IF_ID:
4686             dissect_rsvp_lsp_tunnel_if_id(ti, tvb, offset, obj_length, class, type, type_str);
4687             break;
4688
4689         case RSVP_CLASS_GENERALIZED_UNI:
4690             dissect_rsvp_gen_uni(ti, tvb, offset, obj_length, class, type, type_str);
4691             break;
4692
4693         case RSVP_CLASS_CALL_ID:
4694             dissect_rsvp_call_id(ti, tvb, offset, obj_length, class, type, type_str);
4695             break;
4696
4697         case RSVP_CLASS_RESTART_CAP:
4698             dissect_rsvp_restart_cap(ti, tvb, offset, obj_length, class, type, type_str);
4699             break;
4700
4701         case RSVP_CLASS_PROTECTION:
4702             dissect_rsvp_protection_info(ti, tvb, offset, obj_length, class, type, type_str);
4703             break;
4704
4705         case RSVP_CLASS_FAST_REROUTE:
4706             dissect_rsvp_fast_reroute(ti, tvb, offset, obj_length, class, type, type_str);
4707             break;
4708
4709         case RSVP_CLASS_DETOUR:
4710             dissect_rsvp_detour(ti, tvb, offset, obj_length, class, type, type_str);
4711             break;
4712
4713         case RSVP_CLASS_DIFFSERV:
4714             dissect_rsvp_diffserv(ti, tvb, offset, obj_length, class, type, type_str);
4715             break;
4716
4717         case RSVP_CLASS_NULL:
4718         default:
4719             rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_UNKNOWN_CLASS));
4720             proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
4721                                 "Length: %u", obj_length);
4722             proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
4723                                 "Class number: %u - %s",
4724                                 class, type_str);
4725             proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
4726                                 "Data (%d bytes)", obj_length - 4);
4727             break;
4728         }
4729
4730         if (obj_length == 0)
4731             break;
4732         offset += obj_length;
4733         len += obj_length;
4734     }
4735 }
4736
4737 /*------------------------------------------------------------------------------
4738  * The main loop
4739  *------------------------------------------------------------------------------*/
4740 static void
4741 dissect_rsvp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4742 {
4743     guint8 ver_flags;
4744     guint8 message_type;
4745     int msg_length;
4746     int session_off, tempfilt_off;
4747
4748     if (check_col(pinfo->cinfo, COL_PROTOCOL))
4749         col_set_str(pinfo->cinfo, COL_PROTOCOL, "RSVP");
4750     if (check_col(pinfo->cinfo, COL_INFO))
4751         col_clear(pinfo->cinfo, COL_INFO);
4752
4753     ver_flags = tvb_get_guint8(tvb, 0);
4754     message_type = tvb_get_guint8(tvb, 1);
4755     msg_length = tvb_get_ntohs(tvb, 6);
4756
4757     if (check_col(pinfo->cinfo, COL_INFO)) {
4758         col_add_str(pinfo->cinfo, COL_INFO,
4759             val_to_str(message_type, message_type_vals, "Unknown (%u). "));
4760         find_rsvp_session_tempfilt(tvb, 0, &session_off, &tempfilt_off);
4761         if (session_off)
4762             col_append_str(pinfo->cinfo, COL_INFO, summary_session(tvb, session_off));
4763         if (tempfilt_off)
4764             col_append_str(pinfo->cinfo, COL_INFO, summary_template(tvb, tempfilt_off));
4765     }
4766
4767     if (check_col(pinfo->cinfo, COL_INFO)) {
4768         col_add_str(pinfo->cinfo, COL_INFO,
4769                     val_to_str(message_type, message_type_vals, "Unknown (%u). "));
4770         if (message_type == RSVP_MSG_BUNDLE) {
4771             col_add_str(pinfo->cinfo, COL_INFO,
4772                         rsvp_bundle_dissect ?
4773                         "Component Messages Dissected" :
4774                         "Component Messages Not Dissected");
4775         } else {
4776             find_rsvp_session_tempfilt(tvb, 0, &session_off, &tempfilt_off);
4777             if (session_off)
4778                 col_append_str(pinfo->cinfo, COL_INFO, summary_session(tvb, session_off));
4779             if (tempfilt_off)
4780                 col_append_str(pinfo->cinfo, COL_INFO, summary_template(tvb, tempfilt_off));
4781         }
4782     }
4783
4784     if (tree) {
4785         dissect_rsvp_msg_tree(tvb, pinfo, tree, TREE(TT_RSVP));
4786     }
4787 }
4788
4789 static void
4790 register_rsvp_prefs (void)
4791 {
4792     module_t *rsvp_module;
4793
4794     rsvp_module = prefs_register_protocol(proto_rsvp, NULL);
4795     prefs_register_bool_preference(
4796         rsvp_module, "process_bundle",
4797         "Dissect sub-messages in BUNDLE message",
4798         "Specifies whether Ethereal should decode and display sub-messages within BUNDLE messages",
4799         &rsvp_bundle_dissect);
4800 }
4801
4802 void
4803 proto_register_rsvp(void)
4804 {
4805     gint i;
4806
4807     /* Build the tree array */
4808     for (i=0; i<TT_MAX; i++)
4809         ett_tree[i] = &(ett_treelist[i]);
4810
4811     proto_rsvp = proto_register_protocol("Resource ReserVation Protocol (RSVP)",
4812                                          "RSVP", "rsvp");
4813     proto_register_field_array(proto_rsvp, rsvpf_info, array_length(rsvpf_info));
4814     proto_register_subtree_array(ett_tree, array_length(ett_tree));
4815     register_rsvp_prefs();
4816 }
4817
4818 void
4819 proto_reg_handoff_rsvp(void)
4820 {
4821         dissector_handle_t rsvp_handle;
4822
4823         rsvp_handle = create_dissector_handle(dissect_rsvp, proto_rsvp);
4824         dissector_add("ip.proto", IP_PROTO_RSVP, rsvp_handle);
4825 }