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