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