There's no need to keep a "FILE *" for the file being printed to in a
[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.87 2004/01/23 09:40:37 jmayer 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_GENERALIZED_UNI,
242     RSVP_CLASS_DCLASS = 225,
243     RSVP_CLASS_LSP_TUNNEL_IF_ID = 227
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                             name_len,
2892                             tvb_get_ptr(tvb, offset2+4, name_len));
2893
2894         proto_item_set_text(ti, "SESSION ATTRIBUTE: SetupPrio %d, HoldPrio %d, %s%s%s%s%s [%s]",
2895                             tvb_get_guint8(tvb, offset2),
2896                             tvb_get_guint8(tvb, offset2+1),
2897                             flags &0x01 ? "Local Protection, " : "",
2898                             flags &0x02 ? "Label Recording, " : "",
2899                             flags &0x04 ? "SE Style, " : "",
2900                             flags &0x08 ? "Bandwidth Protection, " : "",
2901                             flags &0x10 ? "Node Protection, " : "",
2902                             name_len ? tvb_format_text(tvb, offset2+4, name_len) : "");
2903         break;
2904
2905     default:
2906         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2907                             "C-type: Unknown (%u)",
2908                             type);
2909         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
2910                             "Data (%d bytes)", obj_length - 4);
2911         break;
2912     }
2913 }
2914
2915 /*------------------------------------------------------------------------------
2916  * EXPLICIT ROUTE AND RECORD ROUTE SUBOBJECTS
2917  *------------------------------------------------------------------------------*/
2918 static void
2919 dissect_rsvp_ero_rro_subobjects (proto_tree *ti, proto_tree *rsvp_object_tree, 
2920                                  tvbuff_t *tvb,
2921                                  int offset, int obj_length, int class)
2922 {
2923     int i, j, k, l, flags;
2924     proto_tree *ti2, *rsvp_ro_subtree, *rsvp_rro_flags_subtree;
2925     int tree_type;
2926
2927     switch(class) {
2928     case RSVP_CLASS_EXPLICIT_ROUTE:
2929         tree_type = TREE(TT_EXPLICIT_ROUTE_SUBOBJ); 
2930         break;
2931     case RSVP_CLASS_RECORD_ROUTE:
2932         tree_type = TREE(TT_RECORD_ROUTE_SUBOBJ); 
2933         break;
2934     default:
2935         /* Bail out */
2936         return;
2937     }
2938
2939     for (i=1, l = 0; l < obj_length - 4; i++) {
2940         j = tvb_get_guint8(tvb, offset+l) & 0x7f;
2941         switch(j) {
2942         case 1: /* IPv4 */
2943             k = tvb_get_guint8(tvb, offset+l) & 0x80;
2944             ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
2945                                       offset+l, 8,
2946                                       "IPv4 Subobject - %s%s",
2947                                       ip_to_str(tvb_get_ptr(tvb, offset+l+2, 4)),
2948                                       class == RSVP_CLASS_EXPLICIT_ROUTE ? 
2949                                       (k ? ", Loose" : ", Strict") : "");
2950             rsvp_ro_subtree =
2951                 proto_item_add_subtree(ti2, tree_type);
2952             if (class == RSVP_CLASS_EXPLICIT_ROUTE) 
2953                 proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
2954                                     k ? "Loose Hop " : "Strict Hop");
2955             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
2956                                 "Type: 1 (IPv4)");
2957             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
2958                                 "Length: %u",
2959                                 tvb_get_guint8(tvb, offset+l+1));
2960             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+2, 4,
2961                                 "IPv4 hop: %s",
2962                                 ip_to_str(tvb_get_ptr(tvb, offset+l+2, 4)));
2963             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+6, 1,
2964                                 "Prefix length: %u",
2965                                 tvb_get_guint8(tvb, offset+l+6));
2966             if (i < 4) {
2967                 proto_item_append_text(ti, "IPv4 %s%s",
2968                                        ip_to_str(tvb_get_ptr(tvb, offset+l+2, 4)),
2969                                        k ? " [L]" : "");
2970             }
2971             if (class == RSVP_CLASS_RECORD_ROUTE) {
2972                 flags = tvb_get_guint8(tvb, offset+l+7);
2973                 if (flags&0x10) {
2974                     proto_item_append_text(ti,  " (Node-id)");
2975                     proto_item_append_text(ti2, " (Node-id)");
2976                 }
2977                 if (flags&0x01) proto_item_append_text(ti2, ", Local Protection Available");
2978                 if (flags&0x02) proto_item_append_text(ti2, ", Local Protection In Use");
2979                 if (flags&0x04) proto_item_append_text(ti2, ", Backup BW Avail");
2980                 if (flags&0x08) proto_item_append_text(ti2, ", Backup is Next-Next-Hop");
2981                 ti2 = proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+7, 1,
2982                                           "Flags: 0x%02x", flags);
2983                 rsvp_rro_flags_subtree = 
2984                     proto_item_add_subtree(ti2, TREE(TT_RECORD_ROUTE_SUBOBJ_FLAGS)); 
2985                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
2986                                     decode_boolean_bitfield(flags, 0x01, 8, 
2987                                                             "Local Protection Available",
2988                                                             "Local Protection Not Available"));
2989                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
2990                                     decode_boolean_bitfield(flags, 0x02, 8, 
2991                                                             "Local Protection In Use",
2992                                                             "Local Protection Not In Use"));
2993                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
2994                                     decode_boolean_bitfield(flags, 0x04, 8, 
2995                                                             "Bandwidth Protection Available",
2996                                                             "Bandwidth Protection Not Available"));
2997                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
2998                                     decode_boolean_bitfield(flags, 0x08, 8, 
2999                                                             "Node Protection Available",
3000                                                             "Node Protection Not Available"));
3001                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
3002                                     decode_boolean_bitfield(flags, 0x10, 8,
3003                                                             "Address Specifies a Node-id Address",
3004                                                             "Address Doesn't Specify a Node-id Address"));
3005             }
3006
3007             break;
3008
3009         case 2: /* IPv6 */
3010             ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3011                                       offset+l, 20,
3012                                       "IPv6 Subobject");
3013             rsvp_ro_subtree =
3014                 proto_item_add_subtree(ti2, tree_type);
3015             k = tvb_get_guint8(tvb, offset+l) & 0x80;
3016             if (class == RSVP_CLASS_EXPLICIT_ROUTE) 
3017                 proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3018                                     k ? "Loose Hop " : "Strict Hop");
3019             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3020                                 "Type: 2 (IPv6)");
3021             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
3022                                 "Length: %u",
3023                                 tvb_get_guint8(tvb, offset+l+1));
3024             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+2, 16,
3025                                 "IPv6 hop: %s",
3026                                 ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset+l+2, 16)));
3027             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+18, 1,
3028                                 "Prefix length: %u",
3029                                 tvb_get_guint8(tvb, offset+l+18));
3030             if (i < 4) {
3031                 proto_item_append_text(ti, "IPv6 [...]%s", k ? " [L]":"");
3032             }
3033             if (class == RSVP_CLASS_RECORD_ROUTE) {
3034                 flags = tvb_get_guint8(tvb, offset+l+19);
3035                 if (flags&0x10) {
3036                     proto_item_append_text(ti,  " (Node-id)");
3037                     proto_item_append_text(ti2, " (Node-id)");
3038                 }
3039                 if (flags&0x01) proto_item_append_text(ti2, ", Local Protection Available");
3040                 if (flags&0x02) proto_item_append_text(ti2, ", Local Protection In Use");
3041                 if (flags&0x04) proto_item_append_text(ti2, ", Backup BW Avail");
3042                 if (flags&0x08) proto_item_append_text(ti2, ", Backup is Next-Next-Hop");
3043                 ti2 = proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+19, 1,
3044                                           "Flags: 0x%02x", flags);
3045                 rsvp_rro_flags_subtree = 
3046                     proto_item_add_subtree(ti2, TREE(TT_RECORD_ROUTE_SUBOBJ_FLAGS)); 
3047                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
3048                                     decode_boolean_bitfield(flags, 0x01, 8, 
3049                                                             "Local Protection Available",
3050                                                             "Local Protection Not Available"));
3051                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
3052                                     decode_boolean_bitfield(flags, 0x02, 8, 
3053                                                             "Local Protection In Use",
3054                                                             "Local Protection Not In Use"));
3055                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
3056                                     decode_boolean_bitfield(flags, 0x04, 8, 
3057                                                             "Backup Tunnel Has Bandwidth",
3058                                                             "Backup Tunnel Does Not Have Bandwidth"));
3059                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
3060                                     decode_boolean_bitfield(flags, 0x08, 8, 
3061                                                             "Backup Tunnel Goes To Next-Next-Hop",
3062                                                             "Backup Tunnel Goes To Next-Hop"));
3063                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
3064                                     decode_boolean_bitfield(flags, 0x10, 8,
3065                                                             "Address Specifies a Node-id Address",
3066                                                             "Address Doesn't Specify a Node-id Address"));
3067             }
3068
3069             break;
3070
3071         case 3: /* Label */
3072             k = tvb_get_guint8(tvb, offset+l) & 0x80;
3073             ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3074                                       offset+l, 8,
3075                                       "Label Subobject - %d, %s",
3076                                       tvb_get_ntohl(tvb, offset+l+4),
3077                                       class == RSVP_CLASS_EXPLICIT_ROUTE ? 
3078                                       (k ? "Loose" : "Strict") : "");
3079             rsvp_ro_subtree =
3080                 proto_item_add_subtree(ti2, tree_type);
3081             if (class == RSVP_CLASS_EXPLICIT_ROUTE) 
3082                 proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3083                                     k ? "Loose Hop " : "Strict Hop");
3084             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3085                                 "Type: 3 (Label)");
3086             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
3087                                 "Length: %u",
3088                                 tvb_get_guint8(tvb, offset+l+1));
3089             if (class == RSVP_CLASS_RECORD_ROUTE) {
3090                 flags = tvb_get_guint8(tvb, offset+l+2);
3091                 if (flags&0x01) proto_item_append_text(ti2, ", Local Protection Available");
3092                 if (flags&0x02) proto_item_append_text(ti2, ", Local Protection In Use");
3093                 if (flags&0x04) proto_item_append_text(ti2, ", Backup BW Avail");
3094                 if (flags&0x08) proto_item_append_text(ti2, ", Backup is Next-Next-Hop");
3095                 ti2 = proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+2, 1,
3096                                           "Flags: 0x%02x", flags);
3097                 rsvp_rro_flags_subtree = 
3098                     proto_item_add_subtree(ti2, TREE(TT_RECORD_ROUTE_SUBOBJ_FLAGS)); 
3099                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
3100                                     decode_boolean_bitfield(flags, 0x01, 8, 
3101                                                             "Local Protection Available",
3102                                                             "Local Protection Not Available"));
3103                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
3104                                     decode_boolean_bitfield(flags, 0x02, 8, 
3105                                                             "Local Protection In Use",
3106                                                             "Local Protection Not In Use"));
3107                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
3108                                     decode_boolean_bitfield(flags, 0x04, 8, 
3109                                                             "Backup Tunnel Has Bandwidth",
3110                                                             "Backup Tunnel Does Not Have Bandwidth"));
3111                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
3112                                     decode_boolean_bitfield(flags, 0x08, 8, 
3113                                                             "Backup Tunnel Goes To Next-Next-Hop",
3114                                                             "Backup Tunnel Goes To Next-Hop"));
3115             }
3116             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+3, 1,
3117                                 "C-Type: %u",
3118                                 tvb_get_guint8(tvb, offset+l+3));
3119             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+4, 4,
3120                                 "Label: %d",
3121                                 tvb_get_ntohl(tvb, offset+l+4));
3122             if (i < 4) {
3123                 proto_item_append_text(ti, "Label %d%s",
3124                                        tvb_get_ntohl(tvb, offset+l+4),
3125                                        k ? " [L]":"");
3126             }
3127             break;
3128
3129         case 4: /* Unnumbered Interface-ID */
3130             k = tvb_get_guint8(tvb, offset+l) & 0x80;
3131             ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3132                                       offset+l, 8,
3133                                       "Unnumbered Interface-ID - %s, %d, %s",
3134                                       ip_to_str(tvb_get_ptr(tvb, offset+l+4, 4)),
3135                                       tvb_get_ntohl(tvb, offset+l+8),
3136                                       class == RSVP_CLASS_EXPLICIT_ROUTE ? 
3137                                       (k ? "Loose" : "Strict") : "");
3138             rsvp_ro_subtree =
3139                 proto_item_add_subtree(ti2, tree_type);
3140             if (class == RSVP_CLASS_EXPLICIT_ROUTE) 
3141                 proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3142                                     k ? "Loose Hop " : "Strict Hop");
3143             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3144                                 "Type: 4 (Unnumbered Interface-ID)");
3145             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
3146                                 "Length: %u",
3147                                 tvb_get_guint8(tvb, offset+l+1));
3148             if (class == RSVP_CLASS_RECORD_ROUTE) {
3149                 flags = tvb_get_guint8(tvb, offset+l+2);
3150                 if (flags&0x01) proto_item_append_text(ti2, ", Local Protection Available");
3151                 if (flags&0x02) proto_item_append_text(ti2, ", Local Protection In Use");
3152                 if (flags&0x04) proto_item_append_text(ti2, ", Backup BW Avail");
3153                 if (flags&0x08) proto_item_append_text(ti2, ", Backup is Next-Next-Hop");
3154                 ti2 = proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+2, 1,
3155                                           "Flags: 0x%02x", flags);
3156                 rsvp_rro_flags_subtree = 
3157                     proto_item_add_subtree(ti2, TREE(TT_RECORD_ROUTE_SUBOBJ_FLAGS)); 
3158                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
3159                                     decode_boolean_bitfield(flags, 0x01, 8, 
3160                                                             "Local Protection Available",
3161                                                             "Local Protection Not Available"));
3162                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
3163                                     decode_boolean_bitfield(flags, 0x02, 8, 
3164                                                             "Local Protection In Use",
3165                                                             "Local Protection Not In Use"));
3166                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
3167                                     decode_boolean_bitfield(flags, 0x04, 8, 
3168                                                             "Backup Tunnel Has Bandwidth",
3169                                                             "Backup Tunnel Does Not Have Bandwidth"));
3170                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
3171                                     decode_boolean_bitfield(flags, 0x08, 8, 
3172                                                             "Backup Tunnel Goes To Next-Next-Hop",
3173                                                             "Backup Tunnel Goes To Next-Hop"));
3174             }
3175             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+4, 4,
3176                                 "Router-ID: %s",
3177                                 ip_to_str(tvb_get_ptr(tvb, offset+l+4, 4)));
3178             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+8, 4,
3179                                 "Interface-ID: %d",
3180                                 tvb_get_ntohl(tvb, offset+l+8));
3181             if (i < 4) {
3182                 proto_item_append_text(ti, "Unnum %s/%d%s",
3183                                        ip_to_str(tvb_get_ptr(tvb, offset+l+4, 4)),
3184                                        tvb_get_ntohl(tvb, offset+l+8),
3185                                        k ? " [L]":"");
3186             }
3187
3188             break;
3189
3190         case 32: /* AS */
3191             if (class == RSVP_CLASS_RECORD_ROUTE) goto defaultsub;
3192             k = tvb_get_ntohs(tvb, offset+l+2);
3193             ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3194                                       offset+l, 4,
3195                                       "Autonomous System %u",
3196                                       k);
3197             rsvp_ro_subtree =
3198                 proto_item_add_subtree(ti2, tree_type);
3199             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3200                                 "Type: 32 (Autonomous System Number)");
3201             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
3202                                 "Length: %u",
3203                                 tvb_get_guint8(tvb, offset+l+1));
3204             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+2, 2,
3205                                 "Autonomous System %u", k);
3206             if (i < 4) {
3207                 proto_item_append_text(ti, "AS %d",
3208                                        tvb_get_ntohs(tvb, offset+l+2));
3209             }
3210
3211             break;
3212
3213         default: /* Unknown subobject */
3214         defaultsub:
3215             k = tvb_get_guint8(tvb, offset+l) & 0x80;
3216             ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3217                                       offset+l,
3218                                       tvb_get_guint8(tvb, offset+l+1),
3219                                       "Unknown subobject: %d", j);
3220             rsvp_ro_subtree =
3221                 proto_item_add_subtree(ti2, tree_type);
3222             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3223                                 k ? "Loose Hop " : "Strict Hop");
3224             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3225                                 "Type: %u (Unknown)", j);
3226             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
3227                                 "Length: %u",
3228                                 tvb_get_guint8(tvb, offset+l+1));
3229
3230         }
3231
3232         l += tvb_get_guint8(tvb, offset+l+1);
3233         if (l < obj_length - 4) {
3234             if (i < 4)
3235                 proto_item_append_text(ti, ", ");
3236             else if (i==4)
3237                 proto_item_append_text(ti, "...");
3238         }
3239     }
3240 }
3241     
3242 /*------------------------------------------------------------------------------
3243  * EXPLICIT ROUTE OBJECT
3244  *------------------------------------------------------------------------------*/
3245 static void
3246 dissect_rsvp_explicit_route (proto_tree *ti, tvbuff_t *tvb,
3247                              int offset, int obj_length,
3248                              int class, int type,
3249                              char *type_str)
3250 {
3251     /* int offset2 = offset + 4; */
3252     proto_tree *rsvp_object_tree;
3253     /* int mylen, i, j, k, l; */
3254     /* proto_tree *ti2, *rsvp_ero_subtree; */
3255
3256     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_EXPLICIT_ROUTE));
3257     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3258                         "Length: %u", obj_length);
3259     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
3260                         "Class number: %u - %s",
3261                         class, type_str);
3262     /* mylen = obj_length - 4; */
3263     switch(type) {
3264     case 1: 
3265         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3266                             "C-type: 1");
3267         proto_item_set_text(ti, "EXPLICIT ROUTE: ");
3268
3269         dissect_rsvp_ero_rro_subobjects(ti, rsvp_object_tree, tvb,
3270                                         offset + 4, obj_length, class);
3271         break;
3272
3273     default:
3274         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3275                             "C-type: Unknown (%u)",
3276                             type);
3277         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, obj_length - 4,
3278                             "Data (%d bytes)", obj_length - 4);
3279         break;
3280     }
3281 }
3282
3283 /*------------------------------------------------------------------------------
3284  * RECORD ROUTE OBJECT
3285  *------------------------------------------------------------------------------*/
3286 static void
3287 dissect_rsvp_record_route (proto_tree *ti, tvbuff_t *tvb,
3288                            int offset, int obj_length,
3289                            int class, int type,
3290                            char *type_str)
3291 {
3292     /* int offset2 = offset + 4; */
3293     proto_tree *rsvp_object_tree;
3294     /* int mylen, i, j, l; */
3295     /* proto_tree *ti2, *rsvp_rro_subtree; */
3296
3297     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_RECORD_ROUTE));
3298     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3299                         "Length: %u", obj_length);
3300     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
3301                         "Class number: %u - %s",
3302                         class, type_str);
3303     proto_item_set_text(ti, "RECORD ROUTE: ");
3304     /* mylen = obj_length - 4; */
3305     switch(type) {
3306     case 1: 
3307         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3308                             "C-type: 1");
3309
3310         dissect_rsvp_ero_rro_subobjects(ti, rsvp_object_tree, tvb,
3311                                         offset + 4, obj_length, class);
3312         break;
3313
3314     default: 
3315         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3316                             "C-type: Unknown (%u)",
3317                             type);
3318         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, obj_length - 4,
3319                             "Data (%d bytes)", obj_length - 4);
3320         break;
3321     }
3322 }
3323
3324 /*------------------------------------------------------------------------------
3325  * MESSAGE ID
3326  *------------------------------------------------------------------------------*/
3327 static void
3328 dissect_rsvp_message_id (proto_tree *ti, tvbuff_t *tvb,
3329                          int offset, int obj_length,
3330                          int class, int type,
3331                          char *type_str)
3332 {
3333     int offset2 = offset + 4;
3334     proto_tree *rsvp_object_tree;
3335
3336     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_MESSAGE_ID));
3337     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3338                         "Length: %u", obj_length);
3339     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
3340                         "Class number: %u - %s",
3341                         class, type_str);
3342     switch(type) {
3343     case 1:
3344         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3345                             "C-type: 1");
3346         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1,
3347                             "Flags: %d", tvb_get_guint8(tvb, offset+4));
3348         proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 3,
3349                             "Epoch: %d", tvb_get_ntoh24(tvb, offset+5));
3350         proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
3351                             "Message-ID: %d", tvb_get_ntohl(tvb, offset+8));
3352         proto_item_set_text(ti, "MESSAGE-ID: %d %s",
3353                             tvb_get_ntohl(tvb, offset+8),
3354                             tvb_get_guint8(tvb, offset+4) & 1 ? "(Ack Desired)" : "");
3355         break;
3356
3357     default:
3358         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3359                             "C-type: Unknown (%u)",
3360                             type);
3361         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
3362                             "Data (%d bytes)", obj_length - 4);
3363         break;
3364     }
3365 }
3366
3367 /*------------------------------------------------------------------------------
3368  * MESSAGE ID ACK
3369  *------------------------------------------------------------------------------*/
3370 static void
3371 dissect_rsvp_message_id_ack (proto_tree *ti, tvbuff_t *tvb,
3372                              int offset, int obj_length,
3373                              int class, int type,
3374                              char *type_str)
3375 {
3376     int offset2 = offset + 4;
3377     proto_tree *rsvp_object_tree;
3378
3379     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_MESSAGE_ID_ACK));
3380     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3381                         "Length: %u", obj_length);
3382     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
3383                         "Class number: %u - %s",
3384                         class, type_str);
3385     switch(type) {
3386     case 1:
3387         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3388                             "C-type: 1");
3389         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1,
3390                             "Flags: %d", tvb_get_guint8(tvb, offset+4));
3391         proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 3,
3392                             "Epoch: %d", tvb_get_ntoh24(tvb, offset+5));
3393         proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
3394                             "Message-ID: %d", tvb_get_ntohl(tvb, offset+8));
3395         proto_item_set_text(ti, "MESSAGE-ID ACK: %d", tvb_get_ntohl(tvb, offset+8));
3396         break;
3397
3398     case 2:
3399         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3400                             "C-type: 2");
3401         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1,
3402                             "Flags: %d", tvb_get_guint8(tvb, offset+4));
3403         proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 3,
3404                             "Epoch: %d", tvb_get_ntoh24(tvb, offset+5));
3405         proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
3406                             "Message-ID: %d", tvb_get_ntohl(tvb, offset+8));
3407         proto_item_set_text(ti, "MESSAGE-ID NACK: %d", tvb_get_ntohl(tvb, offset+8));
3408         break;
3409
3410     default:
3411         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3412                             "C-type: Unknown (%u)",
3413                             type);
3414         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
3415                             "Data (%d bytes)", obj_length - 4);
3416         break;
3417     }
3418 }
3419
3420 /*------------------------------------------------------------------------------
3421  * MESSAGE ID LIST
3422  *------------------------------------------------------------------------------*/
3423 static void
3424 dissect_rsvp_message_id_list (proto_tree *ti, tvbuff_t *tvb,
3425                               int offset, int obj_length,
3426                               int class, int type,
3427                               char *type_str)
3428 {
3429     int offset2 = offset + 4;
3430     proto_tree *rsvp_object_tree;
3431     int mylen;
3432
3433     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_MESSAGE_ID_LIST));
3434     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3435                         "Length: %u", obj_length);
3436     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
3437                         "Class number: %u - %s",
3438                         class, type_str);
3439     switch(type) {
3440     case 1:
3441         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3442                             "C-type: 1");
3443         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1,
3444                             "Flags: %d", tvb_get_guint8(tvb, offset+4));
3445         proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 3,
3446                             "Epoch: %d", tvb_get_ntoh24(tvb, offset+5));
3447         for (mylen = 8; mylen < obj_length; mylen += 4)
3448             proto_tree_add_text(rsvp_object_tree, tvb, offset+mylen, 4,
3449                                 "Message-ID: %d", tvb_get_ntohl(tvb, offset+mylen));
3450         proto_item_set_text(ti, "MESSAGE-ID LIST: %d IDs",
3451                             (obj_length - 8)/4);
3452         break;
3453
3454     default:
3455         mylen = obj_length - 4;
3456         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3457                             "C-type: Unknown (%u)",
3458                             type);
3459         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
3460                             "Data (%d bytes)", obj_length - 4);
3461         break;
3462     }
3463 }
3464
3465 /*------------------------------------------------------------------------------
3466  * HELLO
3467  *------------------------------------------------------------------------------*/
3468 static void
3469 dissect_rsvp_hello (proto_tree *ti, tvbuff_t *tvb,
3470                     int offset, int obj_length,
3471                     int class, int type,
3472                     char *type_str)
3473 {
3474     proto_tree *rsvp_object_tree;
3475
3476     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_HELLO_OBJ));
3477     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3478                         "Length: %u", obj_length);
3479     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
3480                         "Class number: %u - %s",
3481                         class, type_str);
3482     switch(type) {
3483     case 1:
3484     case 2:
3485         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3486                             "C-Type: 1 - HELLO %s object",
3487                             type==1 ? "REQUEST" : "ACK");
3488         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 4,
3489                             "Source Instance: 0x%x",tvb_get_ntohl(tvb, offset+4));
3490         proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
3491                             "Destination Instance: 0x%x",tvb_get_ntohl(tvb, offset+8));
3492         proto_item_append_text(ti, ": %s. Src Instance: 0x%0x. Dest Instance: 0x%0x. ", 
3493                                type==1 ? "REQUEST" : "ACK", 
3494                                tvb_get_ntohl(tvb, offset+4),
3495                                tvb_get_ntohl(tvb, offset+8));
3496         break;
3497     default:
3498         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3499                             "C-Type: %d - UNKNOWN", type);
3500         break;
3501     };
3502 }
3503
3504 /*------------------------------------------------------------------------------
3505  * DCLASS
3506  *------------------------------------------------------------------------------*/
3507 static void
3508 dissect_rsvp_dclass (proto_tree *ti, tvbuff_t *tvb,
3509                      int offset, int obj_length,
3510                      int class, int type,
3511                      char *type_str)
3512 {
3513     int offset2 = offset + 4;
3514     proto_tree *rsvp_object_tree;
3515     int mylen;
3516
3517     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_DCLASS));
3518     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3519                         "Length: %u", obj_length);
3520     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
3521                         "Class number: %u - %s",
3522                         class, type_str);
3523     proto_item_set_text(ti, "DCLASS: ");
3524     switch(type) {
3525     case 1:
3526         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3527                             "C-type: 1");
3528         for (mylen = 4; mylen < obj_length; mylen += 4) {
3529             proto_tree_add_text(rsvp_object_tree, tvb, offset+mylen+3, 1,
3530                                 "DSCP: %s",
3531                                 val_to_str(tvb_get_guint8(tvb, offset+mylen+3),
3532                                            dscp_vals, "Unknown (%d)"));
3533             proto_item_append_text(ti, "%d%s",
3534                                    tvb_get_guint8(tvb, offset+mylen+3)>>2,
3535                                    mylen==obj_length-4 ? "":
3536                                    mylen<16 ? ", ":
3537                                    mylen==16 ? ", ..." : "");
3538         }
3539         break;
3540
3541     default:
3542         mylen = obj_length - 4;
3543         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3544                             "C-type: Unknown (%u)",
3545                             type);
3546         proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
3547                             "Data (%d bytes)", mylen);
3548         break;
3549     }
3550 }
3551
3552 /*------------------------------------------------------------------------------
3553  * ADMINISTRATIVE STATUS
3554  *------------------------------------------------------------------------------*/
3555 static void
3556 dissect_rsvp_admin_status (proto_tree *ti, tvbuff_t *tvb,
3557                            int offset, int obj_length,
3558                            int class, int type,
3559                            char *type_str)
3560 {
3561     int offset2 = offset + 4;
3562     proto_tree *rsvp_object_tree;
3563     proto_tree *ti2, *rsvp_admin_subtree;
3564     int mylen;
3565     guint32 status;
3566     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_ADMIN_STATUS));
3567     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3568                         "Length: %u", obj_length);
3569     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
3570                         "Class number: %u - %s",
3571                         class, type_str);
3572     proto_item_set_text(ti, "ADMIN STATUS: ");
3573     switch(type) {
3574     case 1:
3575         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3576                             "C-type: 1");
3577         status = tvb_get_ntohl(tvb, offset2);
3578         ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
3579                                   "Admin Status: 0x%08x", status);
3580         rsvp_admin_subtree =
3581             proto_item_add_subtree(ti2, TREE(TT_ADMIN_STATUS_FLAGS));
3582         proto_tree_add_text(rsvp_admin_subtree, tvb, offset2, 4,
3583                             decode_boolean_bitfield(status, 0x80000000, 32,
3584                                                     "R: Reflect",
3585                                                     "R: Do not reflect"));
3586         proto_tree_add_text(rsvp_admin_subtree, tvb, offset2, 4,
3587                             decode_boolean_bitfield(status, 0x04, 32,
3588                                                     "T: Testing",
3589                                                     "T: "));
3590         proto_tree_add_text(rsvp_admin_subtree, tvb, offset2, 4,
3591                             decode_boolean_bitfield(status, 0x02, 32,
3592                                                     "A: Administratively Down",
3593                                                     "A: "));
3594         proto_tree_add_text(rsvp_admin_subtree, tvb, offset2, 4,
3595                             decode_boolean_bitfield(status, 0x01, 32,
3596                                                     "D: Delete In Progress",
3597                                                     "D: "));
3598         proto_item_set_text(ti, "ADMIN-STATUS: %s %s %s %s",
3599                             (status & (1<<31)) ? "Reflect" : "",
3600                             (status & (1<<2))  ? "Testing" : "",
3601                             (status & (1<<1))  ? "Admin-Down" : "",
3602                             (status & (1<<0))  ? "Deleting" : "");
3603         break;
3604
3605     default:
3606         mylen = obj_length - 4;
3607         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3608                             "C-type: Unknown (%u)",
3609                             type);
3610         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
3611                             "Data (%d bytes)", obj_length - 4);
3612         break;
3613     }
3614 }
3615
3616 /*------------------------------------------------------------------------------
3617  * LSP TUNNEL INTERFACE ID
3618  *------------------------------------------------------------------------------*/
3619 static void
3620 dissect_rsvp_lsp_tunnel_if_id (proto_tree *ti, tvbuff_t *tvb,
3621                                int offset, int obj_length,
3622                                int class, int type,
3623                                char *type_str)
3624 {
3625     int offset2 = offset + 4;
3626     proto_tree *rsvp_object_tree;
3627
3628     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_LSP_TUNNEL_IF_ID));
3629     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3630                         "Length: %u", obj_length);
3631     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
3632                         "Class number: %u - %s",
3633                         class, type_str);
3634     proto_item_set_text(ti, "LSP INTERFACE-ID: ");
3635     switch(type) {
3636     case 1:
3637         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3638                             "C-type: 1 - IPv4");
3639         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
3640                             "Router ID: %s",
3641                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
3642         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
3643                             "Interface ID: %u", tvb_get_ntohl(tvb, offset2+4));
3644         proto_item_set_text(ti, "LSP INTERFACE-ID: IPv4, Router-ID %s, Interface-ID %d",
3645                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)),
3646                             tvb_get_ntohl(tvb, offset2+4));
3647         break;
3648
3649     default:
3650         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3651                             "C-type: Unknown (%u)",
3652                             type);
3653         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
3654                             "Data (%d bytes)", obj_length - 4);
3655         break;
3656     }
3657 }
3658
3659 /*------------------------------------------------------------------------------
3660  * GENERALIZED UNI
3661  *------------------------------------------------------------------------------*/
3662 static void
3663 dissect_rsvp_gen_uni (proto_tree *ti, tvbuff_t *tvb,
3664                       int offset, int obj_length,
3665                       int class, int type,
3666                       char *type_str)
3667 {
3668     int offset2 = offset + 4;
3669     proto_tree *rsvp_object_tree;
3670     int mylen, i, j, k, l, m;
3671     proto_tree *ti2, *rsvp_gen_uni_subtree;
3672     int s_len, s_class, s_type;
3673
3674     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_GEN_UNI));
3675     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3676                         "Length: %u", obj_length);
3677     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
3678                         "Class number: %u - %s",
3679                         class, type_str);
3680     proto_item_set_text(ti, "GENERALIZED UNI: ");
3681
3682     mylen = obj_length - 4;
3683     switch(type) {
3684     case 1: {
3685         char *c;
3686         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3687                             "C-type: 1");
3688         for (i=1, l = 0; l < mylen; i++) {
3689             j = tvb_get_guint8(tvb, offset2+l+2);
3690             switch(j) {
3691             case 1:
3692             case 2: /* We do source and destination TNA together */
3693                 c = (j==1) ? "Source" : "Destination";
3694                 k = tvb_get_guint8(tvb, offset2+l+3);
3695                 switch(k) {
3696                 case 1:
3697                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3698                                               offset2+l, 8,
3699                                               "%s IPv4 TNA - %s", c,
3700                                               ip_to_str(tvb_get_ptr(tvb, offset2+l+4, 4)));
3701                     rsvp_gen_uni_subtree =
3702                         proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
3703                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
3704                                         "Class: %d (%s)", j, c);
3705                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
3706                                         "Type: 1 (IPv4)");
3707                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
3708                                         "Length: %u",
3709                                         tvb_get_ntohs(tvb, offset2+l));
3710                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 4,
3711                                         "IPv4 hop: %s",
3712                                         ip_to_str(tvb_get_ptr(tvb, offset2+l+4, 4)));
3713                     if (i < 4) {
3714                         proto_item_append_text(ti, "%s IPv4 %s", c,
3715                                                ip_to_str(tvb_get_ptr(tvb, offset2+l+2, 4)));
3716                     }
3717                     break;
3718
3719                 case 2:
3720                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3721                                               offset2+l, 20,
3722                                               "%s IPv6 TNA", c);
3723                     rsvp_gen_uni_subtree =
3724                         proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
3725                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
3726                                         "Class: %d (%s)", j, c);
3727                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
3728                                         "Type: 2 (IPv6)");
3729                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
3730                                         "Length: %u",
3731                                         tvb_get_ntohs(tvb, offset2+l));
3732                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 4,
3733                                         "Data");
3734                     if (i < 4) {
3735                         proto_item_append_text(ti, "%s IPv6", c);
3736                     }
3737                     break;
3738
3739                 case 3:
3740                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3741                                               offset2+l, tvb_get_ntohs(tvb, offset2+l),
3742                                               "%s NSAP TNA", c);
3743                     rsvp_gen_uni_subtree =
3744                         proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
3745                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
3746                                         "Class: %d (%s)", j, c);
3747                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
3748                                         "Type: 3 (NSAP)");
3749                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
3750                                         "Length: %u",
3751                                         tvb_get_ntohs(tvb, offset2+l));
3752                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4,
3753                                         tvb_get_ntohs(tvb, offset2+l)-4,
3754                                         "Data");
3755                     if (i < 4) {
3756                         proto_item_append_text(ti, "%s NSAP", c);
3757                     }
3758                     break;
3759
3760                 default:
3761                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3762                                               offset2+l, tvb_get_ntohs(tvb, offset2+l),
3763                                               "%s UNKNOWN TNA", c);
3764                     rsvp_gen_uni_subtree =
3765                         proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
3766                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
3767                                         "Class: %d (%s)", j, c);
3768                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
3769                                         "Type: %d (UNKNOWN)", j);
3770                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
3771                                         "Length: %u",
3772                                         tvb_get_ntohs(tvb, offset2+l));
3773                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4,
3774                                         tvb_get_ntohs(tvb, offset2+l)-4,
3775                                         "Data");
3776                     if (i < 4) {
3777                         proto_item_append_text(ti, "%s UNKNOWN", c);
3778                     }
3779                     break;
3780                 }
3781                 break;
3782
3783             case 3: /* Diversity subobject */
3784                 k = tvb_get_guint8(tvb, offset2+l+3);
3785                 switch(k) {
3786                 default:
3787                 case 1:
3788                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3789                                               offset2+l, tvb_get_ntohs(tvb, offset2+l),
3790                                               "Diversity Subobject");
3791                     rsvp_gen_uni_subtree =
3792                         proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
3793                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
3794                                         "Class: %d (Diversity)", j);
3795                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
3796                                         "Type: %d", tvb_get_guint8(tvb, offset2+l+3));
3797                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
3798                                         "Length: %u",
3799                                         tvb_get_ntohs(tvb, offset2+l));
3800                     m = tvb_get_guint8(tvb, offset2+l+4) >> 4;
3801                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 1,
3802                                         "Diversity: %d - %s", m,
3803                                         val_to_str(m, ouni_guni_diversity_str, "Unknown"));
3804                     s_len = tvb_get_ntohs(tvb, offset2+l+8);
3805                     s_class = tvb_get_guint8(tvb, offset2+l+10);
3806                     s_type = tvb_get_guint8(tvb, offset2+l+11);
3807                     ti2 = proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+8,
3808                                               s_len, "Session");
3809                     dissect_rsvp_session(ti2, tvb, offset2+l+8, s_len, s_class, s_type,
3810                                          val_to_str(s_class, rsvp_class_vals, "Unknown"));
3811                     offset2 += s_len;
3812                     s_len = tvb_get_ntohs(tvb, offset2+l+8);
3813                     s_class = tvb_get_guint8(tvb, offset2+l+10);
3814                     s_type = tvb_get_guint8(tvb, offset2+l+11);
3815                     ti2 = proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+8,
3816                                               s_len, "Template");
3817                     dissect_rsvp_template_filter(ti2, tvb, offset2+l+8, s_len, s_class, s_type,
3818                                                  val_to_str(s_class, rsvp_class_vals, "Unknown"));
3819
3820                     if (i < 4) {
3821                         proto_item_append_text(ti, "Diversity");
3822                     }
3823                     break;
3824
3825                 }
3826                 break;
3827
3828             case 4: /* Egress Label */
3829                 k = tvb_get_guint8(tvb, offset2+l+3);
3830                 switch(k) {
3831                 default:
3832                 case 1:
3833                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3834                                               offset2+l, tvb_get_ntohs(tvb, offset2+l),
3835                                               "Egress Label Subobject");
3836                     rsvp_gen_uni_subtree =
3837                         proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
3838                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
3839                                         "Class: %d (Egress Label)", j);
3840                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
3841                                         "Type: %d", tvb_get_guint8(tvb, offset2+l+3));
3842                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
3843                                         "Length: %u",
3844                                         tvb_get_ntohs(tvb, offset2+l));
3845                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 1,
3846                                         "Direction: %s",
3847                                         decode_boolean_bitfield(
3848                                             tvb_get_guint8(tvb, offset2+l+4), 0x80, 8,
3849                                             "U: 1 - Upstream label/port ID",
3850                                             "U: 0 - Downstream label/port ID"));
3851                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+7, 1,
3852                                         "Label type: %u", tvb_get_guint8(tvb, offset2+l+7));
3853                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+8, 4,
3854                                         "Logical Port ID: %u", tvb_get_ntohl(tvb, offset2+l+8));
3855                     proto_item_append_text(ti2, ": %s, Label type %d, Port ID %d, Label ",
3856                                            tvb_get_guint8(tvb, offset2+l+4) & 0x80 ?
3857                                            "Upstream" : "Downstream",
3858                                            tvb_get_guint8(tvb, offset2+l+7),
3859                                            tvb_get_ntohl(tvb, offset2+l+8));
3860                     for (j=12; j < tvb_get_ntohs(tvb, offset2+l); j+=4) {
3861                         proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+8, 4,
3862                                             "Label: %u", tvb_get_ntohl(tvb, offset2+l+j));
3863                         proto_item_append_text(ti2, "%u ", tvb_get_ntohl(tvb, offset2+l+j));
3864                     }
3865                     if (i < 4) {
3866                         proto_item_append_text(ti, "Egress Label");
3867                     }
3868                     break;
3869                 }
3870                 break;
3871
3872             case 5: /* Service Level */
3873                 k = tvb_get_guint8(tvb, offset2+l+3);
3874                 switch(k) {
3875                 default:
3876                 case 1:
3877                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3878                                               offset2+l, tvb_get_ntohs(tvb, offset2+l),
3879                                               "Service Level Subobject");
3880                     rsvp_gen_uni_subtree =
3881                         proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
3882                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
3883                                         "Class: %d (Egress Label)", j);
3884                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
3885                                         "Type: %d", tvb_get_guint8(tvb, offset2+l+3));
3886                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
3887                                         "Length: %u",
3888                                         tvb_get_ntohs(tvb, offset2+l));
3889                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 1,
3890                                         "Service Level: %u", tvb_get_guint8(tvb, offset2+l+4));
3891                     proto_item_append_text(ti2, ": %u", tvb_get_guint8(tvb, offset2+l+4));
3892                     if (i < 4) {
3893                         proto_item_append_text(ti, "Service Level %d", tvb_get_guint8(tvb, offset2+l+4));
3894                     }
3895                     break;
3896                 }
3897                 break;
3898
3899             default: /* Unknown subobject */
3900                 ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3901                                           offset2+l,
3902                                           tvb_get_ntohs(tvb, offset2+l),
3903                                           "Unknown subobject: %u",
3904                                           j);
3905                 rsvp_gen_uni_subtree =
3906                     proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
3907                 proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 1,
3908                                     "Type: %u (Unknown)", j);
3909                 proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+1, 1,
3910                                     "Length: %u",
3911                                     tvb_get_guint8(tvb, offset2+l+1));
3912
3913             }
3914
3915             l += tvb_get_guint8(tvb, offset2+l+1);
3916             if (l < mylen) {
3917                 if (i < 4)
3918                     proto_item_append_text(ti, ", ");
3919                 else if (i==4)
3920                     proto_item_append_text(ti, "...");
3921             }
3922         }
3923         break;
3924     }
3925
3926     default:
3927         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3928                             "C-type: Unknown (%u)",
3929                             type);
3930         proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
3931                             "Data (%d bytes)", mylen);
3932         break;
3933     }
3934 }
3935
3936 /*------------------------------------------------------------------------------
3937  * RESTART CAPABILITY
3938  *------------------------------------------------------------------------------*/
3939 static void
3940 dissect_rsvp_restart_cap (proto_tree *ti, tvbuff_t *tvb,
3941                           int offset, int obj_length,
3942                           int class, int type,
3943                           char *type_str)
3944 {
3945     int offset2 = offset + 4;
3946     proto_tree *rsvp_object_tree;
3947
3948     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_RESTART_CAP));
3949     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3950                         "Length: %u", obj_length);
3951     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
3952                         "Class number: %u - %s",
3953                         class, type_str);
3954     proto_item_set_text(ti, "RESTART CAPABILITY: ");
3955     switch(type) {
3956     case 1:
3957         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3958                             "C-type: 1");
3959         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
3960                             "Restart Time: %d ms", 
3961                             tvb_get_ntohl(tvb, offset2));
3962         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
3963                             "Recovery Time: %d ms", 
3964                             tvb_get_ntohl(tvb, offset2+4));
3965         proto_item_append_text(ti, "Restart Time: %d ms. Recovery Time: %d ms.",
3966                             tvb_get_ntohl(tvb, offset2), tvb_get_ntohl(tvb, offset2+4));
3967         break;
3968
3969     default:
3970         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3971                             "C-type: Unknown (%u)",
3972                             type);
3973         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
3974                             "Data (%d bytes)", obj_length - 4);
3975         break;
3976     }
3977 }
3978
3979 /*------------------------------------------------------------------------------
3980  * PROTECTION INFORMATION
3981  *------------------------------------------------------------------------------*/
3982 static void
3983 dissect_rsvp_protection_info (proto_tree *ti, tvbuff_t *tvb,
3984                               int offset, int obj_length,
3985                               int class, int type,
3986                               char *type_str)
3987 {
3988     int offset2 = offset + 4;
3989     proto_tree *rsvp_object_tree;
3990
3991     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_PROTECTION_INFO));
3992     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
3993                         "Length: %u", obj_length);
3994     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
3995                         "Class number: %u - %s",
3996                         class, type_str);
3997     proto_item_set_text(ti, "PROTECTION_INFO: ");
3998     switch(type) {
3999     case 1:
4000         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4001                             "C-type: 1 - IPv4");
4002         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
4003                             "Router ID: %s",
4004                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
4005         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
4006                             "Interface ID: %u", tvb_get_ntohl(tvb, offset2+4));
4007         proto_item_append_text(ti, "Router-ID %s, Interface-ID %d",
4008                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)),
4009                             tvb_get_ntohl(tvb, offset2+4));
4010         break;
4011
4012     default:
4013         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4014                             "C-type: Unknown (%u)",
4015                             type);
4016         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
4017                             "Data (%d bytes)", obj_length - 4);
4018         break;
4019     }
4020 }
4021
4022 /*------------------------------------------------------------------------------
4023  * FAST REROUTE
4024  *------------------------------------------------------------------------------*/
4025 static void
4026 dissect_rsvp_fast_reroute (proto_tree *ti, tvbuff_t *tvb,
4027                            int offset, int obj_length,
4028                            int class, int type,
4029                            char *type_str)
4030 {
4031     proto_tree *rsvp_object_tree;
4032     guint8 flags;
4033     proto_tree *ti2, *rsvp_frr_flags_tree;
4034
4035     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_FAST_REROUTE));
4036     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
4037                         "Length: %u", obj_length);
4038     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
4039                         "Class number: %u - %s",
4040                         class, type_str);
4041     proto_item_set_text(ti, "FAST_REROUTE: ");
4042     switch(type) {
4043     case 1:
4044     case 7:
4045         if ((type==1 && obj_length!=24) || (type==7 && obj_length!=20)) {
4046             proto_tree_add_text(rsvp_object_tree, tvb, offset, obj_length, 
4047                                 "<<<Invalid length: cannot decode>>>");
4048             proto_item_append_text(ti, "Invalid length");
4049             break;
4050         }
4051         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4052                             "C-type: %u", type);
4053         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1, 
4054                             "Setup Priority: %d", tvb_get_guint8(tvb, offset+4));
4055         proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 1, 
4056                             "Hold Priority: %d", tvb_get_guint8(tvb, offset+5));
4057         proto_tree_add_text(rsvp_object_tree, tvb, offset+6, 1, 
4058                             "Hop Limit: %d", tvb_get_guint8(tvb, offset+6));
4059
4060         flags = tvb_get_guint8(tvb, offset+7);
4061         ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset+7, 1, 
4062                                   "Flags: 0x%02x", flags);
4063         rsvp_frr_flags_tree = proto_item_add_subtree(ti2,
4064                                                      TREE(TT_FAST_REROUTE_FLAGS));
4065         proto_tree_add_text(rsvp_frr_flags_tree, tvb, offset+7, 1,
4066                             decode_boolean_bitfield(flags, 0x01, 8,
4067                                                     "One-to-One Backup desired",
4068                                                     "One-to-One Backup not desired"));
4069         proto_tree_add_text(rsvp_frr_flags_tree, tvb, offset+7, 1,
4070                             decode_boolean_bitfield(flags, 0x02, 8,
4071                                                     "Facility Backup desired",
4072                                                     "Facility Backup not desired"));
4073         proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4, 
4074                             "Bandwidth: %.10g", tvb_get_ntohieee_float(tvb, offset+8));
4075         proto_tree_add_text(rsvp_object_tree, tvb, offset+12, 4, 
4076                             "Exclude-Any: 0x%0x", tvb_get_ntohl(tvb, offset+12));
4077         proto_tree_add_text(rsvp_object_tree, tvb, offset+16, 4, 
4078                             "Include-Any: 0x%0x", tvb_get_ntohl(tvb, offset+16));
4079         if (type==1) {
4080             proto_tree_add_text(rsvp_object_tree, tvb, offset+20, 4, 
4081                                 "Include-All: 0x%0x", tvb_get_ntohl(tvb, offset+20));
4082         }
4083
4084         proto_item_append_text(ti, "%s%s",
4085                                flags &0x01 ? "One-to-One Backup, " : "",
4086                                flags &0x02 ? "Facility Backup" : "");
4087         break;
4088
4089     default:
4090         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4091                             "C-type: Unknown (%u)",
4092                             type);
4093         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, obj_length - 4,
4094                             "Data (%d bytes)", obj_length - 4);
4095         break;
4096     }
4097 }
4098
4099 /*------------------------------------------------------------------------------
4100  * DETOUR
4101  *------------------------------------------------------------------------------*/
4102 static void
4103 dissect_rsvp_detour (proto_tree *ti, tvbuff_t *tvb,
4104                      int offset, int obj_length,
4105                      int class, int type,
4106                      char *type_str)
4107 {
4108     proto_tree *rsvp_object_tree;
4109     int remaining_length, count;
4110     int iter;
4111
4112     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_DETOUR));
4113     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
4114                         "Length: %u", obj_length);
4115     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
4116                         "Class number: %u - %s",
4117                         class, type_str);
4118     proto_item_set_text(ti, "DETOUR: ");
4119     switch(type) {
4120     case 7:
4121         iter = 0;
4122         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4123                             "C-type: %u", type);
4124         for (remaining_length = obj_length - 4, count = 1;
4125              remaining_length > 0; remaining_length -= 8, count++) {
4126             if (remaining_length < 8) {
4127                 proto_tree_add_text(rsvp_object_tree, tvb, offset+remaining_length, 
4128                                     obj_length-remaining_length, 
4129                                     "<<<Invalid length: cannot decode>>>");
4130                 proto_item_append_text(ti, "Invalid length");
4131                 break;
4132             }
4133             iter++;
4134             proto_tree_add_text(rsvp_object_tree, tvb, offset+(4*iter), 4,
4135                                 "PLR ID %d: %s", count, 
4136                                 ip_to_str(tvb_get_ptr(tvb, offset+(4*iter), 4)));
4137             iter++;
4138             proto_tree_add_text(rsvp_object_tree, tvb, offset+(4*iter), 4,
4139                                 "Avoid Node ID %d: %s", count, 
4140                                 ip_to_str(tvb_get_ptr(tvb, offset+(4*iter), 4)));
4141         }
4142         break;
4143
4144     default:
4145         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4146                             "C-type: Unknown (%u)",
4147                             type);
4148         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, obj_length - 4,
4149                             "Data (%d bytes)", obj_length - 4);
4150         break;
4151     }
4152 }
4153
4154 /*------------------------------------------------------------------------------
4155  * DIFFSERV
4156  *------------------------------------------------------------------------------*/
4157 static void
4158 dissect_rsvp_diffserv (proto_tree *ti, tvbuff_t *tvb,
4159                        int offset, int obj_length,
4160                        int class, int type,
4161                        char *type_str
4162                        )
4163 {
4164     proto_tree *rsvp_object_tree;
4165     int mapnb, count;
4166     int *hfindexes[] = {
4167         &rsvp_filter[RSVPF_DIFFSERV_MAP],
4168         &rsvp_filter[RSVPF_DIFFSERV_MAP_EXP],
4169         &rsvp_filter[RSVPF_DIFFSERV_PHBID],
4170         &rsvp_filter[RSVPF_DIFFSERV_PHBID_DSCP],
4171         &rsvp_filter[RSVPF_DIFFSERV_PHBID_CODE],
4172         &rsvp_filter[RSVPF_DIFFSERV_PHBID_BIT14],
4173         &rsvp_filter[RSVPF_DIFFSERV_PHBID_BIT15]
4174     };
4175     gint *etts[] = {
4176         &TREE(TT_DIFFSERV_MAP),
4177         &TREE(TT_DIFFSERV_MAP_PHBID)
4178     };
4179
4180     rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_DIFFSERV));
4181     proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
4182                         "Length: %u", obj_length);
4183     proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
4184                         "Class number: %u - %s",
4185                         class, type_str);
4186     proto_item_set_text(ti, "DIFFSERV: ");
4187     offset += 3;
4188     switch (type) {
4189     case 1:
4190         proto_tree_add_text(rsvp_object_tree, tvb, offset, 1,
4191                             "C-type: 1 - E-LSP");
4192         proto_tree_add_uint(rsvp_object_tree, rsvp_filter[RSVPF_DIFFSERV_MAPNB],
4193                             tvb, offset + 4, 1,
4194                             mapnb = tvb_get_guint8(tvb, offset + 4) & 15);
4195         proto_item_append_text(ti, "E-LSP, %u MAP%s", mapnb,
4196                                (mapnb == 0) ? "" : "s");
4197         offset += 5;
4198
4199         for (count = 0; count < mapnb; count++) {
4200             dissect_diffserv_mpls_common(tvb, rsvp_object_tree, type,
4201                                          offset, hfindexes, etts);
4202             offset += 4;
4203         }
4204         break;
4205     case 2:
4206         proto_item_append_text(ti, "L-LSP");
4207         proto_tree_add_text(rsvp_object_tree, tvb, offset, 1,
4208                             "C-type: 2 - L-LSP");
4209         dissect_diffserv_mpls_common(tvb, rsvp_object_tree, type,
4210                                      offset + 3, hfindexes, etts);
4211         break;
4212     default:
4213         proto_tree_add_text(rsvp_object_tree, tvb, offset, 1,
4214                             "C-type: Unknown (%u)", type);
4215         proto_tree_add_text(rsvp_object_tree, tvb, offset + 1, obj_length - 4,
4216                             "Data (%d bytes)", obj_length - 4);
4217     }
4218 }
4219
4220 /*------------------------------------------------------------------------------
4221  * Dissect a single RSVP message in a tree
4222  *------------------------------------------------------------------------------*/
4223 static void
4224 dissect_rsvp_msg_tree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4225                       int tree_mode)
4226 {
4227     proto_tree *rsvp_tree = NULL;
4228     proto_tree *rsvp_header_tree;
4229     proto_tree *rsvp_object_tree;
4230     proto_tree *ti;
4231     guint16 cksum, computed_cksum;
4232     vec_t cksum_vec[1];
4233     int offset = 0;
4234     int len;
4235     guint8 ver_flags;
4236     guint8 message_type;
4237     int session_off, tempfilt_off;
4238     int msg_length;
4239     int obj_length;
4240     int offset2;
4241
4242     offset = 0;
4243     len = 0;
4244     ver_flags = tvb_get_guint8(tvb, 0);
4245     msg_length = tvb_get_ntohs(tvb, 6);
4246     message_type = tvb_get_guint8(tvb, 1);
4247
4248     ti = proto_tree_add_item(tree, proto_rsvp, tvb, offset, msg_length,
4249                              FALSE);
4250     rsvp_tree = proto_item_add_subtree(ti, tree_mode);
4251     proto_item_append_text(rsvp_tree, ": ");
4252     proto_item_append_text(rsvp_tree, val_to_str(message_type, message_type_vals,
4253                                                  "Unknown (%u). "));
4254     find_rsvp_session_tempfilt(tvb, 0, &session_off, &tempfilt_off);
4255     if (session_off)
4256         proto_item_append_text(rsvp_tree, summary_session(tvb, session_off));
4257     if (tempfilt_off)
4258         proto_item_append_text(rsvp_tree, summary_template(tvb, tempfilt_off));
4259
4260     ti = proto_tree_add_text(rsvp_tree, tvb, offset, 8, "RSVP Header. %s",
4261                              val_to_str(message_type, message_type_vals,
4262                                         "Unknown Message (%u). "));
4263     rsvp_header_tree = proto_item_add_subtree(ti, TREE(TT_HDR));
4264
4265     proto_tree_add_text(rsvp_header_tree, tvb, offset, 1, "RSVP Version: %u",
4266                         (ver_flags & 0xf0)>>4);
4267     proto_tree_add_text(rsvp_header_tree, tvb, offset, 1, "Flags: %02x",
4268                         ver_flags & 0xf);
4269     proto_tree_add_uint(rsvp_header_tree, rsvp_filter[RSVPF_MSG], tvb,
4270                         offset+1, 1, message_type);
4271     switch (RSVPF_MSG + message_type) {
4272
4273     case RSVPF_PATH:
4274     case RSVPF_RESV:
4275     case RSVPF_PATHERR:
4276     case RSVPF_RESVERR:
4277     case RSVPF_PATHTEAR:
4278     case RSVPF_RESVTEAR:
4279     case RSVPF_RCONFIRM:
4280     case RSVPF_RTEARCONFIRM:
4281     case RSVPF_BUNDLE:
4282     case RSVPF_ACK:
4283     case RSVPF_SREFRESH:
4284     case RSVPF_HELLO:
4285         proto_tree_add_boolean_hidden(rsvp_header_tree, rsvp_filter[RSVPF_MSG + message_type], tvb,
4286                                       offset+1, 1, 1);
4287         break;
4288
4289     default:
4290         proto_tree_add_protocol_format(rsvp_header_tree, proto_malformed, tvb, offset+1, 1,
4291                                        "Invalid message type: %u", message_type);
4292         return;
4293     }
4294
4295     cksum = tvb_get_ntohs(tvb, offset+2);
4296     if (!pinfo->fragmented && (int) tvb_length(tvb) >= msg_length) {
4297         /* The packet isn't part of a fragmented datagram and isn't
4298            truncated, so we can checksum it. */
4299         cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, msg_length);
4300         cksum_vec[0].len = msg_length;
4301         computed_cksum = in_cksum(&cksum_vec[0], 1);
4302         if (computed_cksum == 0) {
4303             proto_tree_add_text(rsvp_header_tree, tvb, offset+2, 2,
4304                                 "Message Checksum: 0x%04x (correct)",
4305                                 cksum);
4306         } else {
4307             proto_tree_add_text(rsvp_header_tree, tvb, offset+2, 2,
4308                                 "Message Checksum: 0x%04x (incorrect, should be 0x%04x)",
4309                                 cksum,
4310                                 in_cksum_shouldbe(cksum, computed_cksum));
4311         }
4312     } else {
4313         proto_tree_add_text(rsvp_header_tree, tvb, offset+2, 2,
4314                             "Message Checksum: 0x%04x",
4315                             cksum);
4316     }
4317     proto_tree_add_text(rsvp_header_tree, tvb, offset+4, 1,
4318                         "Sending TTL: %u",
4319                         tvb_get_guint8(tvb, offset+4));
4320     proto_tree_add_text(rsvp_header_tree, tvb, offset+6, 2,
4321                         "Message length: %u", msg_length);
4322
4323     offset = 8;
4324     len = 8;
4325
4326     if (message_type == RSVP_MSG_BUNDLE) {
4327         /* Bundle message. Dissect component messages */
4328         if (rsvp_bundle_dissect) {
4329             int len = 8;
4330             while (len < msg_length) {
4331                 gint sub_len;
4332                 tvbuff_t *tvb_sub;
4333                 sub_len = tvb_get_ntohs(tvb, len+6);
4334                 tvb_sub = tvb_new_subset(tvb, len, sub_len, sub_len);
4335                 dissect_rsvp_msg_tree(tvb_sub, pinfo, rsvp_tree, TREE(TT_BUNDLE_COMPMSG));
4336                 len += sub_len;
4337             }
4338         } else {
4339             proto_tree_add_text(rsvp_tree, tvb, offset, msg_length - len,
4340                                 "Bundle Component Messages Not Dissected");
4341         }
4342         return;
4343     }
4344
4345     while (len < msg_length) {
4346         guint8 class;
4347         guint8 type;
4348         char *type_str;
4349
4350         obj_length = tvb_get_ntohs(tvb, offset);
4351         class = tvb_get_guint8(tvb, offset+2);
4352         type = tvb_get_guint8(tvb, offset+3);
4353         type_str = val_to_str(class, rsvp_class_vals, "Unknown");
4354         proto_tree_add_uint_hidden(rsvp_tree, rsvp_filter[RSVPF_OBJECT], tvb,
4355                                    offset, obj_length, class);
4356         ti = proto_tree_add_item(rsvp_tree, rsvp_filter[rsvp_class_to_filter_num(class)],
4357                                  tvb, offset, obj_length, FALSE);
4358
4359         offset2 = offset+4;
4360
4361         switch(class) {
4362
4363         case RSVP_CLASS_SESSION:
4364             dissect_rsvp_session(ti, tvb, offset, obj_length, class, type, type_str);
4365             break;
4366
4367         case RSVP_CLASS_HOP:
4368             dissect_rsvp_hop(ti, tvb, offset, obj_length, class, type, type_str);
4369             break;
4370
4371         case RSVP_CLASS_TIME_VALUES:
4372             dissect_rsvp_time_values(ti, tvb, offset, obj_length, class, type, type_str);
4373             break;
4374
4375         case RSVP_CLASS_ERROR:
4376             dissect_rsvp_error(ti, tvb, offset, obj_length, class, type, type_str);
4377             break;
4378
4379         case RSVP_CLASS_SCOPE:
4380             dissect_rsvp_scope(ti, tvb, offset, obj_length, class, type, type_str);
4381             break;
4382
4383         case RSVP_CLASS_STYLE:
4384             dissect_rsvp_style(ti, tvb, offset, obj_length, class, type, type_str);
4385             break;
4386
4387         case RSVP_CLASS_CONFIRM:
4388             dissect_rsvp_confirm(ti, tvb, offset, obj_length, class, type, type_str);
4389             break;
4390
4391         case RSVP_CLASS_SENDER_TEMPLATE:
4392         case RSVP_CLASS_FILTER_SPEC:
4393             dissect_rsvp_template_filter(ti, tvb, offset, obj_length, class, type, type_str);
4394             break;
4395
4396         case RSVP_CLASS_SENDER_TSPEC:
4397             dissect_rsvp_tspec(ti, tvb, offset, obj_length, class, type, type_str);
4398             break;
4399
4400         case RSVP_CLASS_FLOWSPEC:
4401             dissect_rsvp_flowspec(ti, tvb, offset, obj_length, class, type, type_str);
4402             break;
4403
4404         case RSVP_CLASS_ADSPEC:
4405             dissect_rsvp_adspec(ti, tvb, offset, obj_length, class, type, type_str);
4406             break;
4407
4408         case RSVP_CLASS_INTEGRITY:
4409             dissect_rsvp_integrity(ti, tvb, offset, obj_length, class, type, type_str);
4410             break;
4411
4412         case RSVP_CLASS_POLICY:
4413             dissect_rsvp_policy(ti, tvb, offset, obj_length, class, type, type_str);
4414             break;
4415
4416         case RSVP_CLASS_LABEL_REQUEST:
4417             dissect_rsvp_label_request(ti, tvb, offset, obj_length, class, type, type_str);
4418             break;
4419
4420         case RSVP_CLASS_UPSTREAM_LABEL:
4421         case RSVP_CLASS_SUGGESTED_LABEL:
4422         case RSVP_CLASS_LABEL:
4423             dissect_rsvp_label(ti, tvb, offset, obj_length, class, type, type_str);
4424             break;
4425
4426         case RSVP_CLASS_SESSION_ATTRIBUTE:
4427             dissect_rsvp_session_attribute(ti, tvb, offset, obj_length, class, type, type_str);
4428             break;
4429
4430         case RSVP_CLASS_EXPLICIT_ROUTE:
4431             dissect_rsvp_explicit_route(ti, tvb, offset, obj_length, class, type, type_str);
4432             break;
4433
4434         case RSVP_CLASS_RECORD_ROUTE:
4435             dissect_rsvp_record_route(ti, tvb, offset, obj_length, class, type, type_str);
4436             break;
4437
4438         case RSVP_CLASS_MESSAGE_ID:
4439             dissect_rsvp_message_id(ti, tvb, offset, obj_length, class, type, type_str);
4440             break;
4441
4442         case RSVP_CLASS_MESSAGE_ID_ACK:
4443             dissect_rsvp_message_id_ack(ti, tvb, offset, obj_length, class, type, type_str);
4444             break;
4445
4446         case RSVP_CLASS_MESSAGE_ID_LIST:
4447             dissect_rsvp_message_id_list(ti, tvb, offset, obj_length, class, type, type_str);
4448             break;
4449
4450         case RSVP_CLASS_HELLO:
4451             dissect_rsvp_hello(ti, tvb, offset, obj_length, class, type, type_str);
4452             break;
4453
4454         case RSVP_CLASS_DCLASS:
4455             dissect_rsvp_dclass(ti, tvb, offset, obj_length, class, type, type_str);
4456             break;
4457
4458         case RSVP_CLASS_ADMIN_STATUS:
4459             dissect_rsvp_admin_status(ti, tvb, offset, obj_length, class, type, type_str);
4460             break;
4461
4462         case RSVP_CLASS_LSP_TUNNEL_IF_ID:
4463             dissect_rsvp_lsp_tunnel_if_id(ti, tvb, offset, obj_length, class, type, type_str);
4464             break;
4465
4466         case RSVP_CLASS_GENERALIZED_UNI:
4467             dissect_rsvp_gen_uni(ti, tvb, offset, obj_length, class, type, type_str);
4468             break;
4469
4470         case RSVP_CLASS_RESTART_CAP:
4471             dissect_rsvp_restart_cap(ti, tvb, offset, obj_length, class, type, type_str);
4472             break;
4473
4474         case RSVP_CLASS_PROTECTION:
4475             dissect_rsvp_protection_info(ti, tvb, offset, obj_length, class, type, type_str);
4476             break;
4477
4478         case RSVP_CLASS_FAST_REROUTE:
4479             dissect_rsvp_fast_reroute(ti, tvb, offset, obj_length, class, type, type_str);
4480             break;
4481
4482         case RSVP_CLASS_DETOUR:
4483             dissect_rsvp_detour(ti, tvb, offset, obj_length, class, type, type_str);
4484             break;
4485
4486         case RSVP_CLASS_DIFFSERV:
4487             dissect_rsvp_diffserv(ti, tvb, offset, obj_length, class, type, type_str);
4488             break;
4489
4490         case RSVP_CLASS_NULL:
4491         default:
4492             rsvp_object_tree = proto_item_add_subtree(ti, TREE(TT_UNKNOWN_CLASS));
4493             proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
4494                                 "Length: %u", obj_length);
4495             proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1,
4496                                 "Class number: %u - %s",
4497                                 class, type_str);
4498             proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
4499                                 "Data (%d bytes)", obj_length - 4);
4500             break;
4501         }
4502
4503         if (obj_length == 0)
4504             break;
4505         offset += obj_length;
4506         len += obj_length;
4507     }
4508 }
4509
4510 /*------------------------------------------------------------------------------
4511  * The main loop
4512  *------------------------------------------------------------------------------*/
4513 static void
4514 dissect_rsvp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4515 {
4516     guint8 ver_flags;
4517     guint8 message_type;
4518     int msg_length;
4519     int session_off, tempfilt_off;
4520
4521     if (check_col(pinfo->cinfo, COL_PROTOCOL))
4522         col_set_str(pinfo->cinfo, COL_PROTOCOL, "RSVP");
4523     if (check_col(pinfo->cinfo, COL_INFO))
4524         col_clear(pinfo->cinfo, COL_INFO);
4525
4526     ver_flags = tvb_get_guint8(tvb, 0);
4527     message_type = tvb_get_guint8(tvb, 1);
4528     msg_length = tvb_get_ntohs(tvb, 6);
4529
4530     if (check_col(pinfo->cinfo, COL_INFO)) {
4531         col_add_str(pinfo->cinfo, COL_INFO,
4532             val_to_str(message_type, message_type_vals, "Unknown (%u). "));
4533         find_rsvp_session_tempfilt(tvb, 0, &session_off, &tempfilt_off);
4534         if (session_off)
4535             col_append_str(pinfo->cinfo, COL_INFO, summary_session(tvb, session_off));
4536         if (tempfilt_off)
4537             col_append_str(pinfo->cinfo, COL_INFO, summary_template(tvb, tempfilt_off));
4538     }
4539
4540     if (check_col(pinfo->cinfo, COL_INFO)) {
4541         col_add_str(pinfo->cinfo, COL_INFO,
4542                     val_to_str(message_type, message_type_vals, "Unknown (%u). "));
4543         if (message_type == RSVP_MSG_BUNDLE) {
4544             col_add_str(pinfo->cinfo, COL_INFO,
4545                         rsvp_bundle_dissect ?
4546                         "Component Messages Dissected" :
4547                         "Component Messages Not Dissected");
4548         } else {
4549             find_rsvp_session_tempfilt(tvb, 0, &session_off, &tempfilt_off);
4550             if (session_off)
4551                 col_append_str(pinfo->cinfo, COL_INFO, summary_session(tvb, session_off));
4552             if (tempfilt_off)
4553                 col_append_str(pinfo->cinfo, COL_INFO, summary_template(tvb, tempfilt_off));
4554         }
4555     }
4556
4557     if (tree) {
4558         dissect_rsvp_msg_tree(tvb, pinfo, tree, TREE(TT_RSVP));
4559     }
4560 }
4561
4562 static void
4563 register_rsvp_prefs (void)
4564 {
4565     module_t *rsvp_module;
4566
4567     rsvp_module = prefs_register_protocol(proto_rsvp, NULL);
4568     prefs_register_bool_preference(
4569         rsvp_module, "process_bundle",
4570         "Dissect sub-messages in BUNDLE message",
4571         "Specifies whether Ethereal should decode and display sub-messages within BUNDLE messages",
4572         &rsvp_bundle_dissect);
4573 }
4574
4575 void
4576 proto_register_rsvp(void)
4577 {
4578     gint i;
4579
4580     /* Build the tree array */
4581     for (i=0; i<TT_MAX; i++)
4582         ett_tree[i] = &(ett_treelist[i]);
4583
4584     proto_rsvp = proto_register_protocol("Resource ReserVation Protocol (RSVP)",
4585                                          "RSVP", "rsvp");
4586     proto_register_field_array(proto_rsvp, rsvpf_info, array_length(rsvpf_info));
4587     proto_register_subtree_array(ett_tree, array_length(ett_tree));
4588     register_rsvp_prefs();
4589 }
4590
4591 void
4592 proto_reg_handoff_rsvp(void)
4593 {
4594         dissector_handle_t rsvp_handle;
4595
4596         rsvp_handle = create_dissector_handle(dissect_rsvp, proto_rsvp);
4597         dissector_add("ip.proto", IP_PROTO_RSVP, rsvp_handle);
4598 }