02f5e8e761cff9ff88a544811c3d6f96b664880a
[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  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 /*
28  * NOTES
29  *
30  * This module defines routines to disassemble RSVP packets, as defined in
31  * RFC 2205. All objects from RFC2205 are supported, in IPv4 and IPv6 mode.
32  * In addition, the Integrated Services traffic specification objects
33  * defined in RFC2210 are also supported.
34  *
35  * IPv6 support is not completely tested
36  *
37  * Mar 3, 2000: Added support for MPLS/TE objects, as defined in
38  * <draft-ietf-mpls-rsvp-lsp-tunnel-04.txt>
39  *
40  * May 6, 2004: Added support for E-NNI objects, as defined in
41  * <OIF-E-NNI-01.0>   (Roberto Morro)
42  * <roberto.morro[AT]tilab.com>
43  *
44  * May 6, 2004: Modified some UNI objects, as defined in
45  * <OIF2003.249.09>   (Roberto Morro)
46  * <roberto.morro[AT]tilab.com>
47  *
48  * June 2, 2005: Modified more UNI objects to show correct TNA
49  * addresses; Fixed LSP interface ID subobject (Richard Rabbat)
50  * <richard[AT]us.fujitsu.com>
51  *
52  * July 25, 2005: improved ERROR and LABEL_SET objects dissector;
53  * new ASSOCIATION object dissector (Roberto Morro)
54  * <roberto.morro[AT]tilab.com>
55  *
56  * August 22, 2005: added support for tapping and conversations.
57  * (Manu Pathak) <mapathak[AT]cisco.com>
58  *
59  * July 4, 2006: added support for RFC4124; new CLASSTYPE object dissector
60  * (FF) <francesco.fondelli[AT]gmail.com>
61  *
62  * June 9, 2007: added support for draft-ietf-ccamp-ethernet-traffic-parameters-02
63  * and draft-ietf-ccamp-lsp-hierarchy-bis-02; added support for NOTIFY_REQUEST
64  * and RECOVERY_LABEL objects (Roberto Morro) * <roberto.morro[AT]tilab.com>
65  */
66
67
68 #ifdef HAVE_CONFIG_H
69 # include "config.h"
70 #endif
71
72 #include <stdio.h>
73
74 #ifdef HAVE_UNISTD_H
75 #include <unistd.h>
76 #endif
77
78 #include <stdlib.h>
79 #include <string.h>
80
81 #include <glib.h>
82
83 #include <epan/tvbuff.h>
84 #include <epan/packet.h>
85 #include <prefs.h>
86 #include <epan/in_cksum.h>
87 #include <epan/etypes.h>
88 #include <epan/ipproto.h>
89 #include <epan/conversation.h>
90 #include <epan/tap.h>
91 #include <epan/emem.h>
92
93 #include "packet-rsvp.h"
94 #include "packet-ip.h"
95 #include "packet-frame.h"
96 #include "packet-diffserv-mpls-common.h"
97
98 /* RSVP over UDP encapsulation */
99 #define UDP_PORT_PRSVP 3455
100
101 static int proto_rsvp = -1;
102
103 static dissector_table_t rsvp_dissector_table;
104 static dissector_handle_t data_handle;
105
106 static int rsvp_tap = -1;
107
108 /*
109  * All RSVP packets belonging to a particular flow  belong to the same
110  * conversation. The following structure definitions are for auxillary
111  * structures which have all the relevant flow information to make up the
112  * RSVP five-tuple. Note that the values of the five-tuple are determined
113  * from the session object and sender template/filter spec for PATH/RESV
114  * messages.
115  * Update rsvp_request_equal() when you add stuff here. You might also
116  * have to update rsvp_request_hash().
117  * TODO: Support for IPv6 conversations.
118  */
119
120 typedef struct rsvp_session_ipv4_info {
121     address destination;
122     guint8 protocol;
123     guint16 udp_dest_port;
124 } rsvp_session_ipv4_info;
125
126 typedef struct rsvp_session_ipv6_info {
127     /* not supported yet */
128
129         guint8 dummy;
130 } rsvp_session_ipv6_info;
131
132 typedef struct rsvp_session_ipv4_lsp_info {
133     address destination;
134     guint16 udp_dest_port;
135     guint32 ext_tunnel_id;
136 } rsvp_session_ipv4_lsp_info;
137
138 typedef struct rsvp_session_agg_ipv4_info {
139     address destination;
140     guint8 dscp;
141 } rsvp_session_agg_ipv4_info;
142
143 typedef struct rsvp_session_ipv4_uni_info {
144     address destination;
145     guint16 udp_dest_port;
146     guint32 ext_tunnel_id;
147 } rsvp_session_ipv4_uni_info;
148
149 typedef struct rsvp_session_ipv4_enni_info {
150     address destination;
151     guint16 udp_dest_port;
152     guint32 ext_tunnel_id;
153 } rsvp_session_ipv4_enni_info;
154
155 typedef struct rsvp_template_filter_info {
156     address source;
157     guint16 udp_source_port;
158 } rsvp_template_filter_info;
159
160 /*
161  * The actual request key consists of a union of the various session objects
162  * (which are uniquely identified based on the session type), and the
163  * source_info structure, which has the information derived from the sender
164  * template or the filter spec.
165  * The request key is populated by copying the information from the
166  * rsvp_conversation_info structure (rsvph), which in turn is populated when
167  * the session, filter and sender template objects are dissected.
168  */
169 struct rsvp_request_key {
170     guint32 session_type;
171
172     union { /* differentiated by session_type field */
173         rsvp_session_ipv4_info session_ipv4;
174         rsvp_session_ipv6_info session_ipv6;
175         rsvp_session_ipv4_lsp_info session_ipv4_lsp;
176         rsvp_session_agg_ipv4_info session_agg_ipv4;
177         rsvp_session_ipv4_uni_info session_ipv4_uni;
178         rsvp_session_ipv4_enni_info session_ipv4_enni;
179     } u;
180
181     rsvp_template_filter_info source_info;
182     guint32 conversation;
183 };
184
185 /*
186  * At present, there is nothing particularly important that we need to
187  * store for the request value for each rsvp_request_key, so we just
188  * store the unique 32-bit identifier internally allocated for the key
189  * (and stored in the conversation attribute of rsvp_request_key above.
190  * If this changes in the future, then other stuff can be added here.
191  */
192 struct rsvp_request_val {
193     guint32 value;
194 };
195
196 /*
197  * Initialize the conversation related data structures.
198  */
199 static GHashTable *rsvp_request_hash = NULL;
200
201 /*
202  * The list of tree types
203  */
204 enum {
205     TT_RSVP,
206     TT_HDR,
207     TT_SESSION,
208     TT_HOP,
209     TT_HOP_SUBOBJ,
210     TT_TIME_VALUES,
211     TT_ERROR,
212     TT_ERROR_SUBOBJ,
213     TT_ERROR_FLAGS,
214     TT_SCOPE,
215     TT_STYLE,
216     TT_CONFIRM,
217     TT_SENDER_TEMPLATE,
218     TT_FILTER_SPEC,
219     TT_TSPEC,
220     TT_TSPEC_SUBTREE,
221     TT_FLOWSPEC,
222     TT_FLOWSPEC_SUBTREE,
223     TT_ETHSPEC_SUBTREE,
224     TT_ADSPEC,
225     TT_ADSPEC_SUBTREE,
226     TT_INTEGRITY,
227     TT_INTEGRITY_FLAGS,
228     TT_DCLASS,
229     TT_LSP_TUNNEL_IF_ID,
230     TT_LSP_TUNNEL_IF_ID_SUBTREE,
231     TT_POLICY,
232     TT_MESSAGE_ID,
233     TT_MESSAGE_ID_ACK,
234     TT_MESSAGE_ID_LIST,
235     TT_LABEL,
236     TT_LABEL_SET,
237     TT_LABEL_REQUEST,
238     TT_SESSION_ATTRIBUTE,
239     TT_SESSION_ATTRIBUTE_FLAGS,
240     TT_HELLO_OBJ,
241     TT_EXPLICIT_ROUTE,
242     TT_EXPLICIT_ROUTE_SUBOBJ,
243     TT_RECORD_ROUTE,
244     TT_RECORD_ROUTE_SUBOBJ,
245     TT_RECORD_ROUTE_SUBOBJ_FLAGS,
246     TT_ADMIN_STATUS,
247     TT_ADMIN_STATUS_FLAGS,
248     TT_ASSOCIATION,
249     TT_GEN_UNI,
250     TT_GEN_UNI_SUBOBJ,
251     TT_CALL_ID,
252     TT_BUNDLE_COMPMSG,
253     TT_RESTART_CAP,
254     TT_PROTECTION_INFO,
255     TT_FAST_REROUTE,
256     TT_FAST_REROUTE_FLAGS,
257     TT_DETOUR,
258     TT_DIFFSERV,
259     TT_DIFFSERV_MAP,
260     TT_DIFFSERV_MAP_PHBID,
261     TT_CLASSTYPE,
262     TT_UNKNOWN_CLASS,
263
264     TT_MAX
265 };
266 static gint ett_treelist[TT_MAX];
267 static gint *ett_tree[TT_MAX];
268 #define TREE(X) ett_treelist[(X)]
269
270 /* Should we dissect bundle messages? */
271 static gboolean rsvp_bundle_dissect = TRUE;
272
273 /*
274  * RSVP message types.
275  * See
276  *
277  *      http://www.iana.org/assignments/rsvp-parameters
278  */
279 typedef enum {
280     RSVP_MSG_PATH=1,                    /* RFC 2205 */
281     RSVP_MSG_RESV,                              /* RFC 2205 */
282     RSVP_MSG_PERR,                              /* RFC 2205 */
283     RSVP_MSG_RERR,                              /* RFC 2205 */
284     RSVP_MSG_PTEAR,                             /* RFC 2205 */
285     RSVP_MSG_RTEAR,                             /* RFC 2205 */
286     RSVP_MSG_CONFIRM,                   /* XXX - DREQ, RFC 2745? */
287                                                         /* 9 is DREP, RFC 2745 */
288     RSVP_MSG_RTEAR_CONFIRM=10,  /* from Fred Baker at Cisco */
289                                                         /* 11 is unassigned */
290     RSVP_MSG_BUNDLE = 12,               /* RFC 2961 */
291     RSVP_MSG_ACK,                               /* RFC 2961 */
292                                                         /* 14 is reserved */
293     RSVP_MSG_SREFRESH = 15,             /* RFC 2961 */
294                                                         /* 16, 17, 18, 19 not listed */
295     RSVP_MSG_HELLO = 20,                /* RFC 3209 */
296     RSVP_MSG_NOTIFY                             /* [RFC3473] */
297                                                                 /* 25 is Integrity Challenge RFC 2747, RFC 3097 */
298                                                         /* 26 is Integrity Response RFC 2747, RFC 3097 */
299                                                         /* 66 is DSBM_willing [SBM] */
300                                                         /* 67 is I_AM_DSBM [SBM] */
301                                                         /* [SBM] is Subnet Bandwidth Manager ID from July 1997 */
302 } rsvp_message_types;
303
304 static const value_string message_type_vals[] = {
305     {RSVP_MSG_PATH,                     "PATH Message. "},
306     {RSVP_MSG_RESV,                     "RESV Message. "},
307     {RSVP_MSG_PERR,                     "PATH ERROR Message. "},
308     {RSVP_MSG_RERR,                     "RESV ERROR Message. "},
309     {RSVP_MSG_PTEAR,            "PATH TEAR Message. "},
310     {RSVP_MSG_RTEAR,            "RESV TEAR Message. "},
311     {RSVP_MSG_CONFIRM,          "CONFIRM Message. "},
312     {RSVP_MSG_RTEAR_CONFIRM, "RESV TEAR CONFIRM Message. "},
313     {RSVP_MSG_BUNDLE,           "BUNDLE Message. "},
314     {RSVP_MSG_ACK,                      "ACK Message. "},
315     {RSVP_MSG_SREFRESH,         "SREFRESH Message. "},
316     {RSVP_MSG_HELLO,            "HELLO Message. "},
317         {RSVP_MSG_NOTIFY,               "NOTIFY Message. "},
318     {0, NULL}
319 };
320
321 /*
322  * RSVP classes
323  */
324 #define MAX_RSVP_CLASS 15
325
326 enum rsvp_classes {
327     RSVP_CLASS_NULL=0,
328     RSVP_CLASS_SESSION,
329
330     RSVP_CLASS_HOP=3,
331     RSVP_CLASS_INTEGRITY,
332     RSVP_CLASS_TIME_VALUES,
333     RSVP_CLASS_ERROR,
334     RSVP_CLASS_SCOPE,
335     RSVP_CLASS_STYLE,
336     RSVP_CLASS_FLOWSPEC,
337     RSVP_CLASS_FILTER_SPEC,
338     RSVP_CLASS_SENDER_TEMPLATE,
339     RSVP_CLASS_SENDER_TSPEC,
340     RSVP_CLASS_ADSPEC,
341     RSVP_CLASS_POLICY,
342     RSVP_CLASS_CONFIRM,
343     RSVP_CLASS_LABEL,
344         RSVP_CLASS_HOP_COUNT,
345         RSVP_CLASS_STRICT_SOURCE_ROUTE,
346     RSVP_CLASS_LABEL_REQUEST=19,
347     RSVP_CLASS_EXPLICIT_ROUTE,
348     RSVP_CLASS_RECORD_ROUTE,
349
350     RSVP_CLASS_HELLO,
351
352     RSVP_CLASS_MESSAGE_ID,
353     RSVP_CLASS_MESSAGE_ID_ACK,
354     RSVP_CLASS_MESSAGE_ID_LIST,
355
356         /* 26-29  Unassigned */
357
358         RSVP_CLASS_DIAGNOSTIC = 30,
359         RSVP_CLASS_ROUTE,
360         RSVP_CLASS_DIAG_RESPONSE,
361         RSVP_CLASS_DIAG_SELECT,
362     RSVP_CLASS_RECOVERY_LABEL,
363     RSVP_CLASS_UPSTREAM_LABEL,
364     RSVP_CLASS_LABEL_SET,
365     RSVP_CLASS_PROTECTION,
366
367         /* 38-41  Unassigned */
368         RSVP_CLASS_DSBM_IP_ADDRESS = 42,
369         RSVP_CLASS_SBM_PRIORITY,
370         RSVP_CLASS_DSBM_TIMER_INTERVALS,
371         RSVP_CLASS_SBM_INFO,
372
373         /* 46-62  Unassigned */
374
375     RSVP_CLASS_DETOUR = 63,
376         RSVP_CLASS_CHALLENGE,
377     RSVP_CLASS_DIFFSERV,
378     RSVP_CLASS_CLASSTYPE, /* FF: RFC4124 */
379         RSVP_CLASS_LSP_REQUIRED_ATTRIBUTES,
380
381         /* 68-127  Unassigned */
382
383         RSVP_CLASS_NODE_CHAR = 128,
384     RSVP_CLASS_SUGGESTED_LABEL,
385     RSVP_CLASS_ACCEPTABLE_LABEL_SET,
386     RSVP_CLASS_RESTART_CAP,
387
388         /* 132-160 Unassigned */
389
390         /* 166-191 Unassigned */
391
392         RSVP_CLASS_SESSION_ASSOC = 192,
393     RSVP_CLASS_LSP_TUNNEL_IF_ID,
394         /* 194 Unassigned */
395     RSVP_CLASS_NOTIFY_REQUEST = 195,
396     RSVP_CLASS_ADMIN_STATUS,
397         RSVP_CLASS_LSP_ATTRIBUTES,
398         /* IANA has this as 198  ALARM_SPEC ??? */
399     RSVP_CLASS_ASSOCIATION = 198,
400
401         /* 199-204  Unassigned */
402     RSVP_CLASS_FAST_REROUTE = 205,
403         /* 206 Unassigned */
404     RSVP_CLASS_SESSION_ATTRIBUTE = 207,
405         /* 208-223 Unassigned */
406         /*
407                 Class Numbers 224-255 are assigned by IANA using FCFS allocation.
408                 RSVP will silently ignore, but FORWARD an object with a Class Number
409                 in this range that it does not understand.
410         */
411         /* 224  Unassigned */
412     RSVP_CLASS_DCLASS = 225,
413         RSVP_CLASS_PACKETCABLE_EXTENSIONS,
414         RSVP_CLASS_ATM_SERVICECLASS,
415         RSVP_CLASS_CALL_OPS,
416     RSVP_CLASS_GENERALIZED_UNI,
417     RSVP_CLASS_CALL_ID,
418         RSVP_CLASS_3GPP2_OBJECT
419         /* 232-254 Unassigned */
420         /* 255  Reserved */
421
422 };
423
424 static const value_string rsvp_class_vals[] = {
425     {RSVP_CLASS_NULL, "NULL object"},
426     {RSVP_CLASS_SESSION, "SESSION object"},
427     {RSVP_CLASS_HOP, "HOP object"},
428     {RSVP_CLASS_INTEGRITY, "INTEGRITY object"},
429     {RSVP_CLASS_TIME_VALUES, "TIME VALUES object"},
430     {RSVP_CLASS_ERROR, "ERROR object"},
431     {RSVP_CLASS_SCOPE, "SCOPE object"},
432     {RSVP_CLASS_STYLE, "STYLE object"},
433     {RSVP_CLASS_FLOWSPEC, "FLOWSPEC object"},
434     {RSVP_CLASS_FILTER_SPEC, "FILTER SPEC object"},
435     {RSVP_CLASS_SENDER_TEMPLATE, "SENDER TEMPLATE object"},
436     {RSVP_CLASS_SENDER_TSPEC, "SENDER TSPEC object"},
437     {RSVP_CLASS_ADSPEC, "ADSPEC object"},
438     {RSVP_CLASS_POLICY, "POLICY object"},
439     {RSVP_CLASS_CONFIRM, "CONFIRM object"},
440     {RSVP_CLASS_LABEL, "LABEL object"},
441         {RSVP_CLASS_HOP_COUNT, "HOP_COUNT object"},
442         {RSVP_CLASS_STRICT_SOURCE_ROUTE, "STRICT_SOURCE_ROUTE object"},
443     {RSVP_CLASS_LABEL_REQUEST, "LABEL REQUEST object"},
444     {RSVP_CLASS_EXPLICIT_ROUTE, "EXPLICIT ROUTE object"},
445     {RSVP_CLASS_RECORD_ROUTE, "RECORD ROUTE object"},
446     {RSVP_CLASS_SESSION_ATTRIBUTE, "SESSION ATTRIBUTE object"},
447     {RSVP_CLASS_MESSAGE_ID, "MESSAGE-ID object"},
448     {RSVP_CLASS_MESSAGE_ID_ACK, "MESSAGE-ID ACK/NACK object"},
449     {RSVP_CLASS_MESSAGE_ID_LIST, "MESSAGE-ID LIST object"},
450     {RSVP_CLASS_HELLO, "HELLO object"},
451     {RSVP_CLASS_RECOVERY_LABEL, "RECOVERY-LABEL object"},
452     {RSVP_CLASS_UPSTREAM_LABEL, "UPSTREAM-LABEL object"},
453     {RSVP_CLASS_LABEL_SET, "LABEL-SET object"},
454     {RSVP_CLASS_PROTECTION, "PROTECTION object"},
455     {RSVP_CLASS_DIFFSERV, "DIFFSERV object"},
456     {RSVP_CLASS_CLASSTYPE, "CLASSTYPE object"},
457     {RSVP_CLASS_SUGGESTED_LABEL, "SUGGESTED-LABEL object"},
458     {RSVP_CLASS_ACCEPTABLE_LABEL_SET, "ACCEPTABLE-LABEL-SET object"},
459     {RSVP_CLASS_RESTART_CAP, "RESTART-CAPABILITY object"},
460     {RSVP_CLASS_DCLASS, "DCLASS object"},
461     {RSVP_CLASS_LSP_TUNNEL_IF_ID, "LSP-TUNNEL INTERFACE-ID object"},
462     {RSVP_CLASS_NOTIFY_REQUEST, "NOTIFY-REQUEST object"},
463     {RSVP_CLASS_ADMIN_STATUS, "ADMIN-STATUS object"},
464     {RSVP_CLASS_ASSOCIATION, "ASSOCIATION object"},
465     {RSVP_CLASS_GENERALIZED_UNI, "GENERALIZED-UNI object"},
466     {RSVP_CLASS_CALL_ID, "CALL-ID object"},
467     {RSVP_CLASS_DETOUR, "DETOUR object"},
468     {RSVP_CLASS_FAST_REROUTE, "FAST-REROUTE object"},
469     {0, NULL}
470 };
471
472 /*
473  * RSVP error values
474  */
475 enum rsvp_error_types {
476     RSVP_ERROR_CONFIRM = 0,
477     RSVP_ERROR_ADMISSION,
478     RSVP_ERROR_POLICY,
479     RSVP_ERROR_NO_PATH,
480     RSVP_ERROR_NO_SENDER,
481     RSVP_ERROR_CONFLICT_RESV_STYLE,
482     RSVP_ERROR_UNKNOWN_RESV_STYLE,
483     RSVP_ERROR_CONFLICT_DEST_PORTS,
484     RSVP_ERROR_CONFLICT_SRC_PORTS,
485     RSVP_ERROR_PREEMPTED=12,
486     RSVP_ERROR_UNKNOWN_CLASS,
487     RSVP_ERROR_UNKNOWN_C_TYPE,
488     RSVP_ERROR_TRAFFIC = 21,
489     RSVP_ERROR_TRAFFIC_SYSTEM, /* 22 */
490     RSVP_ERROR_SYSTEM,         /* 23 */
491     RSVP_ERROR_ROUTING,        /* 24 */
492     RSVP_ERROR_NOTIFY,         /* 25 */
493     RSVP_ERROR_DIFFSERV = 27,
494     RSVP_ERROR_DSTE = 28 /* FF: RFC4124 */
495     /*missing (11-2006) :
496       - 29 : Unknown Attributes TLV ,  RFC4420
497       - 30 : Unknown Attributes Bit RFC4420
498       - 31 : Alarms RFC-ietf-ccamp-gmpls-alarm-spec-06.txt
499     */
500 };
501
502 enum {
503     RSVP_AC_ERROR_DELAY_BOUND_ERROR = 1,
504     RSVP_AC_ERROR_BANDWITH_UNAVAILABLE,
505     RSVP_AC_ERROR_LARGE_MTU
506 };
507
508 enum {
509     RSVP_TRAFFIC_CONTROL_ERROR_SERVICE_CONFLICT = 1,
510     RSVP_TRAFFIC_CONTROL_ERROR_SERVIEC_UNSUPPORTED,
511     RSVP_TRAFFIC_CONTROL_ERROR_BAD_FLOWSPEC,
512     RSVP_TRAFFIC_CONTROL_ERROR_BAD_TSPEC,
513     RSVP_TRAFFIC_CONTROL_ERROR_BAD_ADSPEC
514 };
515
516 enum {
517     RSVP_ROUTING_ERROR_BAD_ERO = 1,
518     RSVP_ROUTING_ERROR_BAD_STRICT,
519     RSVP_ROUTING_ERROR_BAD_LOOSE,
520     RSVP_ROUTING_ERROR_BAD_INITIAL_SUBOBJ,
521     RSVP_ROUTING_ERROR_NO_ROUTE,
522     RSVP_ROUTING_ERROR_UNACCEPTABLE_LABEL,
523     RSVP_ROUTING_ERROR_RRO_LOOP,
524     RSVP_ROUTING_ERROR_NON_RSVP_CAPABLE_ROUTER,
525     RSVP_ROUTING_ERROR_LABEL_ALLOC_FAIL,
526     RSVP_ROUTING_ERROR_UNSUPPORTED_L3PID
527 };
528
529 enum {
530     RSVP_NOTIFY_ERROR_RRO_TOO_LARGE = 1,
531     RSVP_NOTIFY_ERROR_RRO_NOTIFICATION,
532     RSVP_NOTIFY_ERROR_RRO_TUNNEL_LOCAL_REPAIRED,
533     RSVP_NOTIFY_ERROR_RRO_CC_ACTIVE_STATE, /* RFC3473*/
534     RSVP_NOTIFY_ERROR_RRO_CC_DEGRADED_STATE, /* RFC3473*/
535     RSVP_NOTIFY_ERROR_LSP_FAILURE,  /* Private */
536     RSVP_NOTIFY_ERROR_LSP_RECOVERED,/* Private */
537     RSVP_NOTIFY_ERROR_LSP_LOCAL_FAILURE/* Private */
538
539 };
540
541 enum {
542     RSVP_DIFFSERV_ERROR_UNEXPECTED_DIFFSERVOBJ = 1,
543     RSVP_DIFFSERV_ERROR_UNSUPPORTED_PHB,
544     RSVP_DIFFSERV_ERROR_INVALID_EXP_PHB_MAPPING,
545     RSVP_DIFFSERV_ERROR_UNSUPPORTED_PSC,
546     RSVP_DIFFSERV_ERROR_PERLSP_CONTEXT_ALLOC_FAIL
547 };
548
549 /* FF: RFC4124 */
550 enum {
551     RSVP_DSTE_ERROR_UNEXPECTED_CLASSTYPEOBJ = 1,
552     RSVP_DSTE_ERROR_UNSUPPORTED_CLASSTYPE,
553     RSVP_DSTE_ERROR_INVALID_CLASSTYPE_VALUE,
554     RSVP_DSTE_ERROR_CT_SETUP_PRIO_NOT_CONFIGURED,
555     RSVP_DSTE_ERROR_CT_HOLDING_PRIO_NOT_CONFIGURED,
556     RSVP_DSTE_ERROR_CT_SETUP_PRIO_AND_CT_HOLDING_PRIO_NOT_CONFIGURED,
557     RSVP_DSTE_ERROR_INCONSISTENCY_PSC_CT,
558     RSVP_DSTE_ERROR_INCONSISTENCY_PHB_CT
559 };
560
561 static const value_string rsvp_error_codes[] = {
562     {RSVP_ERROR_CONFIRM, "Confirmation"},
563     {RSVP_ERROR_ADMISSION, "Admission Control Failure "},
564     {RSVP_ERROR_POLICY, "Policy Control Failure"},
565     {RSVP_ERROR_NO_PATH, "No PATH information for this RESV message"},
566     {RSVP_ERROR_NO_SENDER, "No sender information for this RESV message"},
567     {RSVP_ERROR_CONFLICT_RESV_STYLE, "Conflicting reservation styles"},
568     {RSVP_ERROR_UNKNOWN_RESV_STYLE, "Unknown reservation style"},
569     {RSVP_ERROR_CONFLICT_DEST_PORTS, "Conflicting destination ports"},
570     {RSVP_ERROR_CONFLICT_SRC_PORTS, "Conflicting source ports"},
571     {RSVP_ERROR_PREEMPTED, "Service preempted"},
572     {RSVP_ERROR_UNKNOWN_CLASS, "Unknown object class"},
573     {RSVP_ERROR_UNKNOWN_C_TYPE, "Unknown object C-type"},
574     {RSVP_ERROR_TRAFFIC, "Traffic Control Error"},
575     {RSVP_ERROR_TRAFFIC_SYSTEM, "Traffic Control System Error"},
576     {RSVP_ERROR_SYSTEM, "RSVP System Error"},
577     {RSVP_ERROR_ROUTING, "Routing Error"},
578     {RSVP_ERROR_NOTIFY, "RSVP Notify Error"},
579     {RSVP_ERROR_DIFFSERV, "RSVP Diff-Serv Error"},
580     {RSVP_ERROR_DSTE, "RSVP DiffServ-aware TE Error"},
581     {0, NULL}
582 };
583
584 static const value_string rsvp_admission_control_error_vals[] = {
585     {RSVP_AC_ERROR_DELAY_BOUND_ERROR, "Delay bound cannot be met"},
586     {RSVP_AC_ERROR_BANDWITH_UNAVAILABLE, "Requested bandwidth unavailable"},
587     {RSVP_AC_ERROR_LARGE_MTU, "MTU in flowspec larger than interface MTU"},
588     {0, NULL}
589 };
590
591 static const value_string rsvp_traffic_control_error_vals[] = {
592     {RSVP_TRAFFIC_CONTROL_ERROR_SERVICE_CONFLICT, "Service conflict"},
593     {RSVP_TRAFFIC_CONTROL_ERROR_SERVIEC_UNSUPPORTED, "Service unsupported"},
594     {RSVP_TRAFFIC_CONTROL_ERROR_BAD_FLOWSPEC, "Bad Flowspec value"},
595     {RSVP_TRAFFIC_CONTROL_ERROR_BAD_TSPEC, "Bad Tspec value"},
596     {RSVP_TRAFFIC_CONTROL_ERROR_BAD_ADSPEC, "Bad Adspec value"},
597     {0, NULL}
598 };
599
600 static const value_string rsvp_routing_error_vals[] = {
601     {RSVP_ROUTING_ERROR_BAD_ERO, "Bad EXPLICIT_ROUTE object"},
602     {RSVP_ROUTING_ERROR_BAD_STRICT, "Bad strict node"},
603     {RSVP_ROUTING_ERROR_BAD_LOOSE, "Bad loose node"},
604     {RSVP_ROUTING_ERROR_BAD_INITIAL_SUBOBJ, "Bad initial subobject"},
605     {RSVP_ROUTING_ERROR_NO_ROUTE, "No route available toward destination"},
606     {RSVP_ROUTING_ERROR_UNACCEPTABLE_LABEL, "Unacceptable label value"},
607     {RSVP_ROUTING_ERROR_RRO_LOOP, "RRO indicated routing loops"},
608     {RSVP_ROUTING_ERROR_NON_RSVP_CAPABLE_ROUTER, "non-RSVP-capable router stands in the path"},
609     {RSVP_ROUTING_ERROR_LABEL_ALLOC_FAIL, "MPLS label allocation failure"},
610     {RSVP_ROUTING_ERROR_UNSUPPORTED_L3PID, "Unsupported L3PID"},
611     {0, NULL}
612 };
613
614 static const value_string rsvp_notify_error_vals[] = {
615     {RSVP_NOTIFY_ERROR_RRO_TOO_LARGE, "RRO too large for MTU"},
616     {RSVP_NOTIFY_ERROR_RRO_NOTIFICATION, "RRO Notification"},
617     {RSVP_NOTIFY_ERROR_RRO_TUNNEL_LOCAL_REPAIRED, "Tunnel locally repaired"},
618     {RSVP_NOTIFY_ERROR_RRO_CC_ACTIVE_STATE, "Control Channel Active State"},/* RFC3473*/
619     {RSVP_NOTIFY_ERROR_RRO_CC_DEGRADED_STATE,"Control Channel Degraded State"}, /* RFC3473*/
620     {RSVP_NOTIFY_ERROR_LSP_FAILURE,  "Private : LSP Failure"},/* Private */
621     {RSVP_NOTIFY_ERROR_LSP_RECOVERED,"Private : LSP recovered"},/* Private */
622     {RSVP_NOTIFY_ERROR_LSP_LOCAL_FAILURE,"Private : LSP Local Failure"},/* Private */
623     {0, NULL}
624 };
625
626 static const value_string rsvp_diffserv_error_vals[] = {
627     {RSVP_DIFFSERV_ERROR_UNEXPECTED_DIFFSERVOBJ, "Unexpected DIFFSERV object"},
628     {RSVP_DIFFSERV_ERROR_UNSUPPORTED_PHB, "Unsupported PHB"},
629     {RSVP_DIFFSERV_ERROR_INVALID_EXP_PHB_MAPPING, "Invalid `EXP<->PHB mapping'"},
630     {RSVP_DIFFSERV_ERROR_UNSUPPORTED_PSC, "Unsupported PSC"},
631     {RSVP_DIFFSERV_ERROR_PERLSP_CONTEXT_ALLOC_FAIL, "Per-LSP context allocation failure"},
632     {0, NULL}
633 };
634
635 /* FF: RFC4124 */
636 static const value_string rsvp_diffserv_aware_te_error_vals[] = {
637     {RSVP_DSTE_ERROR_UNEXPECTED_CLASSTYPEOBJ, "Unexpected CLASSTYPE object"},
638     {RSVP_DSTE_ERROR_UNSUPPORTED_CLASSTYPE, "Unsupported Class-Type"},
639     {RSVP_DSTE_ERROR_INVALID_CLASSTYPE_VALUE, "Invalid Class-Type value"},
640     {RSVP_DSTE_ERROR_CT_SETUP_PRIO_NOT_CONFIGURED, "CT and setup priority do not form a configured TE-Class"},
641     {RSVP_DSTE_ERROR_CT_HOLDING_PRIO_NOT_CONFIGURED, "CT and holding priority do not form a configured TE-Class"},
642     {RSVP_DSTE_ERROR_CT_SETUP_PRIO_AND_CT_HOLDING_PRIO_NOT_CONFIGURED,
643      "CT and setup priority do not form a configured TE-Class AND CT and holding priority do not form a configured TE-Class"},
644     {RSVP_DSTE_ERROR_INCONSISTENCY_PSC_CT, "Inconsistency between signaled PSC and signaled CT"},
645     {RSVP_DSTE_ERROR_INCONSISTENCY_PHB_CT, "Inconsistency between signaled PHBs and signaled CT"},
646     {0, NULL}
647 };
648
649 /*
650  * Defines the reservation style plus style-specific information that
651  * is not a FLOWSPEC or FILTER_SPEC object, in a RESV message.
652  */
653 #define RSVP_DISTINCT (1 << 3)
654 #define RSVP_SHARED (2 << 3)
655 #define RSVP_SHARING_MASK (RSVP_DISTINCT | RSVP_SHARED)
656
657 #define RSVP_SCOPE_WILD 1
658 #define RSVP_SCOPE_EXPLICIT 2
659 #define RSVP_SCOPE_MASK 0x07
660
661 #define RSVP_WF (RSVP_SHARED | RSVP_SCOPE_WILD)
662 #define RSVP_FF (RSVP_DISTINCT | RSVP_SCOPE_EXPLICIT)
663 #define RSVP_SE (RSVP_SHARED | RSVP_SCOPE_EXPLICIT)
664
665 static const value_string style_vals[] = {
666     { RSVP_WF, "Wildcard Filter" },
667     { RSVP_FF, "Fixed Filter" },
668     { RSVP_SE, "Shared-Explicit" },
669     { 0,       NULL }
670 };
671
672 enum {
673     RSVP_SESSION_TYPE_IPV4 = 1,
674     RSVP_SESSION_TYPE_IPV6,
675
676     RSVP_SESSION_TYPE_IPV4_LSP = 7,
677     RSVP_SESSION_TYPE_IPV6_LSP,
678
679     RSVP_SESSION_TYPE_AGGREGATE_IPV4 = 9,
680     RSVP_SESSION_TYPE_AGGREGATE_IPV6,
681
682     RSVP_SESSION_TYPE_IPV4_UNI = 11,
683     RSVP_SESSION_TYPE_IPV4_E_NNI = 15
684 };
685
686 /*
687  * Defines a desired QoS, in a RESV message.
688  */
689 enum    qos_service_type {
690     QOS_QUALITATIVE =     128,          /* Qualitative service */
691     QOS_NULL =              6,          /* Null service (RFC2997) */
692     QOS_CONTROLLED_LOAD=    5,          /* Controlled Load Service */
693     QOS_GUARANTEED =        2,          /* Guaranteed service */
694     QOS_TSPEC =             1           /* Traffic specification */
695     };
696
697 static const value_string qos_vals[] = {
698     { QOS_QUALITATIVE, "Qualitative QoS" },
699     { QOS_NULL, "Null-Service QoS" },
700     { QOS_CONTROLLED_LOAD, "Controlled-load QoS" },
701     { QOS_GUARANTEED, "Guaranteed rate QoS" },
702     { QOS_TSPEC, "Traffic specification" },
703     { 0, NULL }
704 };
705
706 static const value_string svc_vals[] = {
707     { 126, "Compression Hint" },
708     { 127, "Token bucket" },
709     { 128, "Null Service" },
710     { 130, "Guaranteed-rate RSpec" },
711     { 0, NULL }
712 };
713
714 enum rsvp_spec_types { INTSRV = 2 };
715
716 enum intsrv_services {
717         INTSRV_GENERAL = 1,
718         INTSRV_GTD = 2,
719         INTSRV_CLOAD = 5,
720         INTSRV_NULL = 6,
721         INTSRV_QUALITATIVE = 128
722 };
723
724 static const value_string intsrv_services_str[] = {
725     {INTSRV_GENERAL, "Default General Parameters"},
726     {INTSRV_GTD, "Guaranteed Rate"},
727     {INTSRV_CLOAD, "Controlled Load"},
728     {INTSRV_NULL, "Null Service"},
729     {INTSRV_QUALITATIVE, "Null Service"},
730     { 0, NULL }
731 };
732
733 #if 0
734 enum intsrv_field_name {
735         INTSRV_NON_IS_HOPS = 1, INTSRV_COMPOSED_NON_IS_HOPS,
736         INTSRV_IS_HOPS, INTSRV_COMPOSED_IS_HOPS,
737         INTSRV_PATH_BANDWIDTH, INTSRV_MIN_PATH_BANDWIDTH,
738         INTSRV_IF_LATENCY, INTSRV_PATH_LATENCY,
739         INTSRV_MTU, INTSRV_COMPOSED_MTU,
740
741         INTSRV_TOKEN_BUCKET_TSPEC = 127,
742         INTSRV_QUALITATIVE_TSPEC = 128,
743         INTSRV_GTD_RSPEC = 130,
744
745         INTSRV_DELAY = 131,     /* Gtd Parameter C - Max Delay Bound - bytes */
746         INTSRV_MAX_JITTER,      /* Gtd Parameter D - Max Jitter */
747         INTSRV_E2E_DELAY,       /* Gtd Parameter Ctot */
748         INTSRV_E2E_MAX_JITTER,  /* Gtd Parameter Dtot */
749         INTSRV_SHP_DELAY,       /* Gtd Parameter Csum */
750         INTSRV_SHP_MAX_JITTER   /* Gtd Parameter Dsum */
751 };
752 #endif
753
754 static const value_string adspec_params[] = {
755     {4, "IS Hop Count"},
756     {6, "Path b/w estimate"},
757     {8, "Minimum path latency"},
758     {10, "Composed MTU"},
759     {133, "End-to-end composed value for C"},
760     {134, "End-to-end composed value for D"},
761     {135, "Since-last-reshaping point composed C"},
762     {136, "Since-last-reshaping point composed D"},
763     { 0, NULL }
764 };
765
766 const value_string gmpls_lsp_enc_str[] = {
767     { 1, "Packet"},
768     { 2, "Ethernet v2/DIX"},
769     { 3, "ANSI PDH"},
770     { 5, "SONET/SDH"},
771     { 6, "VCAT"},               /* provisional value */
772     { 7, "Digital Wrapper"},
773     { 8, "Lambda (photonic)"},
774     { 9, "Fiber"},
775     {11, "FiberChannel"},
776     { 0, NULL }
777 };
778
779 const value_string gmpls_switching_type_str[] = {
780     {  1, "Packet-Switch Capable-1 (PSC-1)"},
781     {  2, "Packet-Switch Capable-2 (PSC-2)"},
782     {  3, "Packet-Switch Capable-3 (PSC-3)"},
783     {  4, "Packet-Switch Capable-4 (PSC-4)"},
784     { 51, "Layer-2 Switch Capable (L2SC)"},
785     {100, "Time-Division-Multiplex Capable (TDM)"},
786     {150, "Lambda-Switch Capable (LSC)"},
787     {200, "Fiber-Switch Capable (FSC)"},
788     { 0, NULL }
789 };
790
791 const value_string gmpls_protection_cap_str[] = {
792     { 1, "Extra Traffic"},
793     { 2, "Unprotected"},
794     { 4, "Shared"},
795     { 8, "Dedicated 1:1"},
796     {16, "Dedicated 1+1"},
797     {32, "Enhanced"},
798     {64, "Reserved"},
799     {128,"Reserved"},
800     { 0, NULL }
801 };
802
803 static const value_string gmpls_gpid_str[] = {
804     { 5, "Asynchronous mapping of E3 (SDH)"},
805     { 8, "Bit synchronous mapping of E3 (SDH)"},
806     { 9, "Byte synchronous mapping of E3 (SDH)"},
807     {10, "Asynchronous mapping of DS2/T2 (SDH)"},
808     {11, "Bit synchronous mapping of DS2/T2 (SONET, SDH)"},
809     {13, "Asynchronous mapping of E1 (SONET, SDH)"},
810     {14, "Byte synchronous mapping of E1 (SONET, SDH)"},
811     {15, "Byte synchronous mapping of 31 * DS0 (SONET, SDH)"},
812     {16, "Asynchronous mapping of DS1/T1 (SONET, SDH)"},
813     {17, "Bit synchronous mapping of DS1/T1 (SONET, SDH)"},
814     {18, "Byte synchronous mapping of DS1/T1 (SONET, SDH)"},
815     {19, "VC-11 in VC-12 (SDH)"},
816     {22, "DS1 SF Asynchronous (SONET)"},
817     {23, "DS1 ESF Asynchronous (SONET)"},
818     {24, "DS3 M23 Asynchronous (SONET)"},
819     {25, "DS3 C-Bit Parity Asynchronous (SONET)"},
820     {26, "VT/LOVC (SONET, SDH)"},
821     {27, "STS SPE/HOVC (SONET, SDH)"},
822     {28, "POS - No Scrambling, 16 bit CRC (SONET, SDH)"},
823     {29, "POS - No Scrambling, 32 bit CRC (SONET, SDH)"},
824     {30, "POS - Scrambling, 16 bit CRC (SONET, SDH)"},
825     {31, "POS - Scrambling, 32 bit CRC (SONET, SDH)"},
826     {32, "ATM Mapping (SONET, SDH)"},
827     {33, "Ethernet (SDH, Lambda, Fiber)"},
828     {34, "SDH (Lambda, Fiber)"},
829     {35, "SONET (Lambda, Fiber)"},
830     {36, "Digital Wrapper (Lambda, Fiber)"},
831     {37, "Lambda (Fiber)"},
832     {38, "ETSI PDH (SDH)"},
833     {39, "ANSI PDH (SONET, SDH)"},
834     {40, "Link Access Protocol SDH: LAPS - X.85 and X.86 (SONET, SDH)"},
835     {41, "FDDI (SONET, SDH, Lambda, Fiber)"},
836     {42, "DQDB: ETSI ETS 300 216 (SONET, SDH)"},
837     {43, "FiberChannel-3 Services (FiberChannel)"},
838     {44, "HDLC"},
839     {45, "Ethernet V2/DIX (only)"},
840     {46, "Ethernet 802.3 (only)"},
841     { 0, NULL },
842 };
843
844 const value_string gmpls_sonet_signal_type_str[] = {
845     { 1, "VT1.5 SPE / VC-11"},
846     { 2, "VT2 SPE / VC-12"},
847     { 3, "VT3 SPE"},
848     { 4, "VT6 SPE / VC-2"},
849     { 5, "STS-1 SPE / VC-3"},
850     { 6, "STS-3c SPE / VC-4"},
851     { 7, "STS-1 / STM-0 (transp)"},
852     { 8, "STS-3 / STM-1 (transp)"},
853     { 9, "STS-12 / STM-4 (transp)"},
854     {10, "STS-48 / STM-16 (transp)"},
855     {11, "STS-192 / STM-64 (transp)"},
856     {12, "STS-768 / STM-256 (transp)"},
857
858     /* Extended non-SONET signal types */
859     {13, "VTG / TUG-2"},
860     {14, "TUG-3"},
861     {15, "STSG-3 / AUG-1"},
862     {16, "STSG-12  / AUG-4"},
863     {17, "STSG-48  / AUG-16"},
864     {18, "STSG-192 / AUG-64"},
865     {19, "STSG-768 / AUG-256"},
866
867     /* Other SONEt signal types */
868     {21, "STS-12c SPE / VC-4-4c"},
869     {22, "STS-48c SPE / VC-4-16c"},
870     {23, "STS-192c SPE / VC-4-64c"},
871     {0, NULL}
872 };
873
874 static const value_string ouni_guni_diversity_str[] = {
875     {1, "Node Diverse"},
876     {2, "Link Diverse"},
877     {3, "Shared-Risk Link Group Diverse"},
878     {4, "Shared Path"},
879     {0, NULL}
880 };
881
882 /* -------------------- Stuff for MPLS/TE objects -------------------- */
883
884 static const value_string proto_vals[] = { {IP_PROTO_ICMP, "ICMP"},
885                                            {IP_PROTO_IGMP, "IGMP"},
886                                            {IP_PROTO_TCP,  "TCP" },
887                                            {IP_PROTO_UDP,  "UDP" },
888                                            {IP_PROTO_OSPF, "OSPF"},
889                                            {0,             NULL  } };
890
891 /* Filter keys */
892 enum rsvp_filter_keys {
893
894     /* Message types */
895     RSVPF_MSG,          /* Message type */
896     /* Shorthand for message types */
897     RSVPF_PATH,
898     RSVPF_RESV,
899     RSVPF_PATHERR,
900     RSVPF_RESVERR,
901     RSVPF_PATHTEAR,
902     RSVPF_RESVTEAR,
903     RSVPF_RCONFIRM,
904     RSVPF_JUNK_MSG8,
905     RSVPF_JUNK_MSG9,
906     RSVPF_RTEARCONFIRM,
907     RSVPF_JUNK11,
908     RSVPF_BUNDLE,
909     RSVPF_ACK,
910     RSVPF_JUNK14,
911     RSVPF_SREFRESH,
912     RSVPF_JUNK16,
913     RSVPF_JUNK17,
914     RSVPF_JUNK18,
915     RSVPF_JUNK19,
916     RSVPF_HELLO,
917         RSVPF_NOTIFY,
918     /* Does the message contain an object of this type? */
919     RSVPF_OBJECT,
920     /* Object present shorthands */
921     RSVPF_SESSION,
922     RSVPF_DUMMY_1,
923     RSVPF_HOP,
924     RSVPF_INTEGRITY,
925     RSVPF_TIME_VALUES,
926     RSVPF_ERROR,
927     RSVPF_SCOPE,
928     RSVPF_STYLE,
929     RSVPF_FLOWSPEC,
930     RSVPF_FILTER_SPEC,
931     RSVPF_SENDER,
932     RSVPF_TSPEC,
933     RSVPF_ADSPEC,
934     RSVPF_POLICY,
935     RSVPF_CONFIRM,
936     RSVPF_LABEL,
937     RSVPF_DUMMY_2,
938     RSVPF_DUMMY_3,
939     RSVPF_LABEL_REQUEST,
940     RSVPF_EXPLICIT_ROUTE,
941     RSVPF_RECORD_ROUTE,
942     RSVPF_HELLO_OBJ,
943     RSVPF_MESSAGE_ID,
944     RSVPF_MESSAGE_ID_ACK,
945     RSVPF_MESSAGE_ID_LIST,
946     RSVPF_RECOVERY_LABEL,
947     RSVPF_UPSTREAM_LABEL,
948     RSVPF_LABEL_SET,
949     RSVPF_PROTECTION,
950     RSVPF_DIFFSERV,
951     RSVPF_DSTE,
952
953     RSVPF_SUGGESTED_LABEL,
954     RSVPF_ACCEPTABLE_LABEL_SET,
955     RSVPF_RESTART_CAP,
956
957     RSVPF_SESSION_ATTRIBUTE,
958     RSVPF_DCLASS,
959     RSVPF_LSP_TUNNEL_IF_ID,
960     RSVPF_NOTIFY_REQUEST,
961     RSVPF_ADMIN_STATUS,
962     RSVPF_ASSOCIATION,
963     RSVPF_GENERALIZED_UNI,
964     RSVPF_CALL_ID,
965     RSVPF_UNKNOWN_OBJ,
966
967     /* Session object */
968     RSVPF_SESSION_IP,
969     RSVPF_SESSION_PROTO,
970     RSVPF_SESSION_PORT,
971     RSVPF_SESSION_TUNNEL_ID,
972     RSVPF_SESSION_EXT_TUNNEL_ID,
973
974     /* Sender template */
975     RSVPF_SENDER_IP,
976     RSVPF_SENDER_PORT,
977     RSVPF_SENDER_LSP_ID,
978
979     /* Diffserv object */
980     RSVPF_DIFFSERV_MAPNB,
981     RSVPF_DIFFSERV_MAP,
982     RSVPF_DIFFSERV_MAP_EXP,
983     RSVPF_DIFFSERV_PHBID,
984     RSVPF_DIFFSERV_PHBID_DSCP,
985     RSVPF_DIFFSERV_PHBID_CODE,
986     RSVPF_DIFFSERV_PHBID_BIT14,
987     RSVPF_DIFFSERV_PHBID_BIT15,
988
989     /* Diffserv-aware TE object */
990     RSVPF_DSTE_CLASSTYPE,
991
992     /* Generalized UNI object */
993     RSVPF_GUNI_SRC_IPV4,
994     RSVPF_GUNI_DST_IPV4,
995     RSVPF_GUNI_SRC_IPV6,
996     RSVPF_GUNI_DST_IPV6,
997
998     /* CALL ID object */
999     RSVPF_CALL_ID_SRC_ADDR_IPV4,
1000     RSVPF_CALL_ID_SRC_ADDR_IPV6,
1001
1002     /* Sentinel */
1003     RSVPF_MAX
1004 };
1005
1006 static int rsvp_filter[RSVPF_MAX];
1007
1008 static hf_register_info rsvpf_info[] = {
1009
1010     /* Message type number */
1011     {&rsvp_filter[RSVPF_MSG],
1012      { "Message Type", "rsvp.msg", FT_UINT8, BASE_DEC, VALS(message_type_vals), 0x0,
1013         "", HFILL }},
1014
1015     /* Message type shorthands */
1016     {&rsvp_filter[RSVPF_PATH],
1017      { "Path Message", "rsvp.path", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1018         "", HFILL }},
1019
1020     {&rsvp_filter[RSVPF_RESV],
1021      { "Resv Message", "rsvp.resv", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1022         "", HFILL }},
1023
1024     {&rsvp_filter[RSVPF_PATHERR],
1025      { "Path Error Message", "rsvp.perr", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1026         "", HFILL }},
1027
1028     {&rsvp_filter[RSVPF_RESVERR],
1029      { "Resv Error Message", "rsvp.rerr", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1030         "", HFILL }},
1031
1032     {&rsvp_filter[RSVPF_PATHTEAR],
1033      { "Path Tear Message", "rsvp.ptear", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1034         "", HFILL }},
1035
1036     {&rsvp_filter[RSVPF_RESVTEAR],
1037      { "Resv Tear Message", "rsvp.rtear", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1038         "", HFILL }},
1039
1040     {&rsvp_filter[RSVPF_RCONFIRM],
1041      { "Resv Confirm Message", "rsvp.resvconf", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1042         "", HFILL }},
1043
1044     {&rsvp_filter[RSVPF_RTEARCONFIRM],
1045      { "Resv Tear Confirm Message", "rsvp.rtearconf", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1046         "", HFILL }},
1047
1048     {&rsvp_filter[RSVPF_BUNDLE],
1049      { "Bundle Message", "rsvp.bundle", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1050         "", HFILL }},
1051
1052     {&rsvp_filter[RSVPF_ACK],
1053      { "Ack Message", "rsvp.ack", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1054         "", HFILL }},
1055
1056     {&rsvp_filter[RSVPF_SREFRESH],
1057      { "Srefresh Message", "rsvp.srefresh", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1058         "", HFILL }},
1059
1060     {&rsvp_filter[RSVPF_HELLO],
1061      { "HELLO Message", "rsvp.hello", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1062         "", HFILL }},
1063
1064     /* Object class */
1065     {&rsvp_filter[RSVPF_OBJECT],
1066      { "Object class", "rsvp.object", FT_UINT8, BASE_DEC, VALS(rsvp_class_vals), 0x0,
1067         "", HFILL }},
1068
1069     {&rsvp_filter[RSVPF_NOTIFY],
1070      { "Notify Message", "rsvp.notify", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1071        "", HFILL }},
1072
1073         /* Object present shorthands */
1074     {&rsvp_filter[RSVPF_SESSION],
1075      { "SESSION", "rsvp.session", FT_NONE, BASE_NONE, NULL, 0x0,
1076         "", HFILL }},
1077
1078     {&rsvp_filter[RSVPF_HOP],
1079      { "HOP", "rsvp.hop", FT_NONE, BASE_NONE, NULL, 0x0,
1080         "", HFILL }},
1081
1082     {&rsvp_filter[RSVPF_HELLO_OBJ],
1083      { "HELLO Request/Ack", "rsvp.hello_obj", FT_NONE, BASE_NONE, NULL, 0x0,
1084         "", HFILL }},
1085
1086     {&rsvp_filter[RSVPF_INTEGRITY],
1087      { "INTEGRITY", "rsvp.integrity", FT_NONE, BASE_NONE, NULL, 0x0,
1088         "", HFILL }},
1089
1090     {&rsvp_filter[RSVPF_TIME_VALUES],
1091      { "TIME VALUES", "rsvp.time", FT_NONE, BASE_NONE, NULL, 0x0,
1092         "", HFILL }},
1093
1094     {&rsvp_filter[RSVPF_ERROR],
1095      { "ERROR", "rsvp.error", FT_NONE, BASE_NONE, NULL, 0x0,
1096         "", HFILL }},
1097
1098     {&rsvp_filter[RSVPF_SCOPE],
1099      { "SCOPE", "rsvp.scope", FT_NONE, BASE_NONE, NULL, 0x0,
1100         "", HFILL }},
1101
1102     {&rsvp_filter[RSVPF_STYLE],
1103      { "STYLE", "rsvp.style", FT_NONE, BASE_NONE, NULL, 0x0,
1104         "", HFILL }},
1105
1106     {&rsvp_filter[RSVPF_FLOWSPEC],
1107      { "FLOWSPEC", "rsvp.flowspec", FT_NONE, BASE_NONE, NULL, 0x0,
1108         "", HFILL }},
1109
1110     {&rsvp_filter[RSVPF_FILTER_SPEC],
1111      { "FILTERSPEC", "rsvp.filter", FT_NONE, BASE_NONE, NULL, 0x0,
1112         "", HFILL }},
1113
1114     {&rsvp_filter[RSVPF_SENDER],
1115      { "SENDER TEMPLATE", "rsvp.sender", FT_NONE, BASE_NONE, NULL, 0x0,
1116         "", HFILL }},
1117
1118     {&rsvp_filter[RSVPF_TSPEC],
1119      { "SENDER TSPEC", "rsvp.tspec", FT_NONE, BASE_NONE, NULL, 0x0,
1120         "", HFILL }},
1121
1122     {&rsvp_filter[RSVPF_ADSPEC],
1123      { "ADSPEC", "rsvp.adspec", FT_NONE, BASE_NONE, NULL, 0x0,
1124         "", HFILL }},
1125
1126     {&rsvp_filter[RSVPF_POLICY],
1127      { "POLICY", "rsvp.policy", FT_NONE, BASE_NONE, NULL, 0x0,
1128         "", HFILL }},
1129
1130     {&rsvp_filter[RSVPF_CONFIRM],
1131      { "CONFIRM", "rsvp.confirm", FT_NONE, BASE_NONE, NULL, 0x0,
1132         "", HFILL }},
1133
1134     {&rsvp_filter[RSVPF_LABEL],
1135      { "LABEL", "rsvp.label", FT_NONE, BASE_NONE, NULL, 0x0,
1136         "", HFILL }},
1137
1138     {&rsvp_filter[RSVPF_RECOVERY_LABEL],
1139      { "RECOVERY LABEL", "rsvp.recovery_label", FT_NONE, BASE_NONE, NULL, 0x0,
1140         "", HFILL }},
1141
1142     {&rsvp_filter[RSVPF_UPSTREAM_LABEL],
1143      { "UPSTREAM LABEL", "rsvp.upstream_label", FT_NONE, BASE_NONE, NULL, 0x0,
1144         "", HFILL }},
1145
1146     {&rsvp_filter[RSVPF_SUGGESTED_LABEL],
1147      { "SUGGESTED LABEL", "rsvp.suggested_label", FT_NONE, BASE_NONE, NULL, 0x0,
1148         "", HFILL }},
1149
1150     {&rsvp_filter[RSVPF_LABEL_SET],
1151      { "LABEL SET", "rsvp.label_set", FT_NONE, BASE_NONE, NULL, 0x0,
1152         "", HFILL }},
1153
1154     {&rsvp_filter[RSVPF_ACCEPTABLE_LABEL_SET],
1155      { "ACCEPTABLE LABEL SET", "rsvp.acceptable_label_set", FT_NONE, BASE_NONE, NULL, 0x0,
1156         "", HFILL }},
1157
1158     {&rsvp_filter[RSVPF_PROTECTION],
1159      { "PROTECTION", "rsvp.protection", FT_NONE, BASE_NONE, NULL, 0x0,
1160         "", HFILL }},
1161
1162     {&rsvp_filter[RSVPF_DIFFSERV],
1163      { "DIFFSERV", "rsvp.diffserv", FT_NONE, BASE_NONE, NULL, 0x0,
1164         "", HFILL }},
1165
1166     {&rsvp_filter[RSVPF_DSTE],
1167      { "CLASSTYPE", "rsvp.dste", FT_NONE, BASE_NONE, NULL, 0x0,
1168        "", HFILL }},
1169
1170     {&rsvp_filter[RSVPF_RESTART_CAP],
1171      { "RESTART CAPABILITY", "rsvp.restart", FT_NONE, BASE_NONE, NULL, 0x0,
1172         "", HFILL }},
1173
1174     {&rsvp_filter[RSVPF_LABEL_REQUEST],
1175      { "LABEL REQUEST", "rsvp.label_request", FT_NONE, BASE_NONE, NULL, 0x0,
1176         "", HFILL }},
1177
1178     {&rsvp_filter[RSVPF_SESSION_ATTRIBUTE],
1179      { "SESSION ATTRIBUTE", "rsvp.session_attribute", FT_NONE, BASE_NONE, NULL, 0x0,
1180         "", HFILL }},
1181
1182     {&rsvp_filter[RSVPF_EXPLICIT_ROUTE],
1183      { "EXPLICIT ROUTE", "rsvp.explicit_route", FT_NONE, BASE_NONE, NULL, 0x0,
1184         "", HFILL }},
1185
1186     {&rsvp_filter[RSVPF_RECORD_ROUTE],
1187      { "RECORD ROUTE", "rsvp.record_route", FT_NONE, BASE_NONE, NULL, 0x0,
1188         "", HFILL }},
1189
1190     {&rsvp_filter[RSVPF_MESSAGE_ID],
1191      { "MESSAGE-ID", "rsvp.msgid", FT_NONE, BASE_NONE, NULL, 0x0,
1192         "", HFILL }},
1193
1194     {&rsvp_filter[RSVPF_MESSAGE_ID_ACK],
1195      { "MESSAGE-ID ACK", "rsvp.ack", FT_NONE, BASE_NONE, NULL, 0x0,
1196         "", HFILL }},
1197
1198     {&rsvp_filter[RSVPF_MESSAGE_ID_LIST],
1199      { "MESSAGE-ID LIST", "rsvp.msgid_list", FT_NONE, BASE_NONE, NULL, 0x0,
1200         "", HFILL }},
1201
1202     {&rsvp_filter[RSVPF_DCLASS],
1203      { "DCLASS", "rsvp.dclass", FT_NONE, BASE_NONE, NULL, 0x0,
1204         "", HFILL }},
1205
1206     {&rsvp_filter[RSVPF_LSP_TUNNEL_IF_ID],
1207      { "LSP INTERFACE-ID", "rsvp.lsp_tunnel_if_id", FT_NONE, BASE_NONE, NULL, 0x0,
1208         "", HFILL }},
1209
1210     {&rsvp_filter[RSVPF_ADMIN_STATUS],
1211      { "ADMIN STATUS", "rsvp.admin_status", FT_NONE, BASE_NONE, NULL, 0x0,
1212         "", HFILL }},
1213
1214     {&rsvp_filter[RSVPF_ASSOCIATION],
1215      { "ASSOCIATION", "rsvp.association", FT_NONE, BASE_NONE, NULL, 0x0,
1216         "", HFILL }},
1217
1218     {&rsvp_filter[RSVPF_NOTIFY_REQUEST],
1219      { "NOTIFY REQUEST", "rsvp.notify_request", FT_NONE, BASE_NONE, NULL, 0x0,
1220         "", HFILL }},
1221
1222     {&rsvp_filter[RSVPF_GENERALIZED_UNI],
1223      { "GENERALIZED UNI", "rsvp.generalized_uni", FT_NONE, BASE_NONE, NULL, 0x0,
1224         "", HFILL }},
1225
1226     {&rsvp_filter[RSVPF_CALL_ID],
1227      { "CALL ID", "rsvp.call_id", FT_NONE, BASE_NONE, NULL, 0x0,
1228         "", HFILL }},
1229
1230     {&rsvp_filter[RSVPF_UNKNOWN_OBJ],
1231      { "Unknown object", "rsvp.obj_unknown", FT_NONE, BASE_NONE, NULL, 0x0,
1232         "", HFILL }},
1233
1234     /* Session fields */
1235     {&rsvp_filter[RSVPF_SESSION_IP],
1236      { "Destination address", "rsvp.session.ip", FT_IPv4, BASE_NONE, NULL, 0x0,
1237         "", HFILL }},
1238
1239     {&rsvp_filter[RSVPF_SESSION_PORT],
1240      { "Port number", "rsvp.session.port", FT_UINT16, BASE_DEC, NULL, 0x0,
1241         "", HFILL }},
1242
1243     {&rsvp_filter[RSVPF_SESSION_PROTO],
1244      { "Protocol", "rsvp.session.proto", FT_UINT8, BASE_DEC, VALS(proto_vals), 0x0,
1245         "", HFILL }},
1246
1247     {&rsvp_filter[RSVPF_SESSION_TUNNEL_ID],
1248      { "Tunnel ID", "rsvp.session.tunnel_id", FT_UINT16, BASE_DEC, NULL, 0x0,
1249         "", HFILL }},
1250
1251     {&rsvp_filter[RSVPF_SESSION_EXT_TUNNEL_ID],
1252      { "Extended tunnel ID", "rsvp.session.ext_tunnel_id", FT_UINT32, BASE_DEC, NULL, 0x0,
1253         "", HFILL }},
1254
1255     /* Sender template/Filterspec fields */
1256     {&rsvp_filter[RSVPF_SENDER_IP],
1257      { "Sender IPv4 address", "rsvp.sender.ip", FT_IPv4, BASE_NONE, NULL, 0x0,
1258         "", HFILL }},
1259
1260     {&rsvp_filter[RSVPF_SENDER_PORT],
1261      { "Sender port number", "rsvp.sender.port", FT_UINT16, BASE_DEC, NULL, 0x0,
1262        "", HFILL }},
1263
1264     {&rsvp_filter[RSVPF_SENDER_LSP_ID],
1265      { "Sender LSP ID", "rsvp.sender.lsp_id", FT_UINT16, BASE_DEC, NULL, 0x0,
1266         "", HFILL }},
1267
1268     /* Diffserv object fields */
1269     {&rsvp_filter[RSVPF_DIFFSERV_MAPNB],
1270      { "MAPnb", "rsvp.diffserv.mapnb", FT_UINT8, BASE_DEC, NULL, 0x0,
1271        MAPNB_DESCRIPTION, HFILL }},
1272
1273     {&rsvp_filter[RSVPF_DIFFSERV_MAP],
1274      { "MAP", "rsvp.diffserv.map", FT_NONE, BASE_NONE, NULL, 0x0,
1275        MAP_DESCRIPTION, HFILL }},
1276
1277     {&rsvp_filter[RSVPF_DIFFSERV_MAP_EXP],
1278      { "EXP", "rsvp.diffserv.map.exp", FT_UINT8, BASE_DEC, NULL, 0x0,
1279        EXP_DESCRIPTION, HFILL }},
1280
1281     {&rsvp_filter[RSVPF_DIFFSERV_PHBID],
1282      { "PHBID", "rsvp.diffserv.phbid", FT_NONE, BASE_NONE, NULL, 0x0,
1283        PHBID_DESCRIPTION, HFILL }},
1284
1285     {&rsvp_filter[RSVPF_DIFFSERV_PHBID_DSCP],
1286      { PHBID_DSCP_DESCRIPTION, "rsvp.diffserv.phbid.dscp", FT_UINT16,
1287        BASE_DEC, NULL, PHBID_DSCP_MASK, "DSCP", HFILL }},
1288
1289     {&rsvp_filter[RSVPF_DIFFSERV_PHBID_CODE],
1290      { PHBID_CODE_DESCRIPTION, "rsvp.diffserv.phbid.code", FT_UINT16,
1291        BASE_DEC, NULL, PHBID_CODE_MASK, "PHB id code", HFILL }},
1292
1293     {&rsvp_filter[RSVPF_DIFFSERV_PHBID_BIT14],
1294      { PHBID_BIT14_DESCRIPTION, "rsvp.diffserv.phbid.bit14", FT_UINT16,
1295        BASE_DEC, VALS(phbid_bit14_vals), PHBID_BIT14_MASK, "Bit 14", HFILL }},
1296
1297     {&rsvp_filter[RSVPF_DIFFSERV_PHBID_BIT15],
1298      { PHBID_BIT15_DESCRIPTION, "rsvp.diffserv.phbid.bit15", FT_UINT16,
1299        BASE_DEC, VALS(phbid_bit15_vals), PHBID_BIT15_MASK, "Bit 15", HFILL }},
1300
1301     /* Diffserv-aware TE object field */
1302     {&rsvp_filter[RSVPF_DSTE_CLASSTYPE],
1303      { "CT", "rsvp.dste.classtype", FT_UINT8, BASE_DEC, NULL, 0x0,
1304        NULL, HFILL }},
1305
1306     /* Generalized UNI object field */
1307     {&rsvp_filter[RSVPF_GUNI_SRC_IPV4],
1308      { "Source TNA", "rsvp.guni.srctna.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
1309         "", HFILL }},
1310
1311     {&rsvp_filter[RSVPF_GUNI_DST_IPV4],
1312      { "Destination TNA", "rsvp.guni.dsttna.ipv4", FT_IPv4, BASE_NONE, NULL, 0x0,
1313         "", HFILL }},
1314
1315     {&rsvp_filter[RSVPF_GUNI_SRC_IPV6],
1316      { "Source TNA", "rsvp.guni.srctna.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
1317         "", HFILL }},
1318
1319     {&rsvp_filter[RSVPF_GUNI_DST_IPV6],
1320      { "Destination TNA", "rsvp.guni.dsttna.ipv6", FT_IPv6, BASE_NONE, NULL, 0x0,
1321         "", HFILL }},
1322
1323     /* Generalized UNI object field */
1324     {&rsvp_filter[RSVPF_CALL_ID_SRC_ADDR_IPV4],
1325      { "Source Transport Network Address", "rsvp.callid.srcaddr.ipv4", FT_IPv4,
1326         BASE_NONE, NULL, 0x0, "", HFILL }},
1327
1328     {&rsvp_filter[RSVPF_CALL_ID_SRC_ADDR_IPV6],
1329      { "Source Transport Network Address", "rsvp.callid.srcaddr.ipv6", FT_IPv6,
1330         BASE_NONE, NULL, 0x0, "", HFILL }}
1331 };
1332
1333 /* RSVP Conversation related Hash functions */
1334
1335 /*
1336  * Compare two RSVP request keys to see if they are equal. Return 1 if they
1337  * are, 0 otherwise.
1338  * Two RSVP request keys are equal if and only if they have the exactly the
1339  * same internal conversation identifier, session type, and matching values in
1340  * the session info and source info structures.
1341  */
1342 static gint
1343 rsvp_equal (gconstpointer k1, gconstpointer k2)
1344 {
1345     const struct rsvp_request_key *key1 = (const struct rsvp_request_key*) k1;
1346     const struct rsvp_request_key *key2 = (const struct rsvp_request_key*) k2;
1347
1348     if (key1->conversation != key2->conversation) {
1349         return 0;
1350     }
1351
1352     if (key1->session_type != key2->session_type) {
1353         return 0;
1354     }
1355
1356     switch (key1->session_type) {
1357     case RSVP_SESSION_TYPE_IPV4:
1358         if (ADDRESSES_EQUAL(&key1->u.session_ipv4.destination,
1359                             &key2->u.session_ipv4.destination) == FALSE)
1360             return 0;
1361
1362         if (key1->u.session_ipv4.protocol != key2->u.session_ipv4.protocol)
1363             return 0;
1364
1365         if (key1->u.session_ipv4.udp_dest_port != key2->u.session_ipv4.udp_dest_port)
1366             return 0;
1367
1368         break;
1369
1370     case RSVP_SESSION_TYPE_IPV6:
1371         /* this is not supported yet for conversations */
1372         break;
1373
1374     case RSVP_SESSION_TYPE_IPV4_LSP:
1375         if (ADDRESSES_EQUAL(&key1->u.session_ipv4_lsp.destination,
1376                             &key2->u.session_ipv4_lsp.destination) == FALSE)
1377             return 0;
1378
1379         if (key1->u.session_ipv4_lsp.udp_dest_port !=
1380             key2->u.session_ipv4_lsp.udp_dest_port)
1381             return 0;
1382
1383
1384         if (key1->u.session_ipv4_lsp.ext_tunnel_id !=
1385             key2->u.session_ipv4_lsp.ext_tunnel_id)
1386             return 0;
1387
1388         break;
1389
1390     case RSVP_SESSION_TYPE_AGGREGATE_IPV4:
1391         if (ADDRESSES_EQUAL(&key1->u.session_agg_ipv4.destination,
1392                             &key2->u.session_agg_ipv4.destination) == FALSE)
1393             return 0;
1394
1395         if (key1->u.session_agg_ipv4.dscp != key2->u.session_agg_ipv4.dscp)
1396             return 0;
1397
1398         break;
1399
1400     case RSVP_SESSION_TYPE_AGGREGATE_IPV6:
1401         /* this is not supported yet for conversations */
1402         break;
1403
1404     case RSVP_SESSION_TYPE_IPV4_UNI:
1405         if (ADDRESSES_EQUAL(&key1->u.session_ipv4_uni.destination,
1406                             &key2->u.session_ipv4_uni.destination) == FALSE)
1407             return 0;
1408
1409         if (key1->u.session_ipv4_uni.udp_dest_port !=
1410             key2->u.session_ipv4_uni.udp_dest_port)
1411             return 0;
1412
1413
1414         if (key1->u.session_ipv4_uni.ext_tunnel_id !=
1415             key2->u.session_ipv4_uni.ext_tunnel_id)
1416             return 0;
1417
1418         break;
1419
1420     case RSVP_SESSION_TYPE_IPV4_E_NNI:
1421         if (ADDRESSES_EQUAL(&key1->u.session_ipv4_enni.destination,
1422                             &key2->u.session_ipv4_enni.destination) == FALSE)
1423             return 0;
1424
1425         if (key1->u.session_ipv4_enni.udp_dest_port !=
1426             key2->u.session_ipv4_enni.udp_dest_port)
1427             return 0;
1428
1429
1430         if (key1->u.session_ipv4_enni.ext_tunnel_id !=
1431             key2->u.session_ipv4_enni.ext_tunnel_id)
1432             return 0;
1433
1434         break;
1435
1436     default:
1437         /* This should never happen. */
1438         break;
1439     }
1440
1441     if (ADDRESSES_EQUAL(&key1->source_info.source,
1442                         &key2->source_info.source) == FALSE)
1443         return 0;
1444
1445     if (key1->source_info.udp_source_port != key2->source_info.udp_source_port)
1446         return 0;
1447
1448     /* If we get here, the two keys are equal. */
1449     return 1;
1450 }
1451
1452 /*
1453  * Calculate a hash key for the supplied RSVP request. The internally allocated
1454  * conversation-id is unique, so we just use that.
1455  */
1456 static guint
1457 rsvp_hash (gconstpointer k)
1458 {
1459     const struct rsvp_request_key *key = (const struct rsvp_request_key*) k;
1460     return key->conversation;
1461 }
1462
1463 /*
1464  * Conversation specific initialization code that deletes any unused memory that
1465  * might need to be freed, and allocates the memory for the various conversation
1466  * hash tables.
1467  */
1468 static void
1469 rsvp_init_protocol (void)
1470 {
1471     if (rsvp_request_hash)
1472         g_hash_table_destroy(rsvp_request_hash);
1473
1474     rsvp_request_hash = g_hash_table_new(rsvp_hash, rsvp_equal);
1475 }
1476
1477 static inline int rsvp_class_to_filter_num(int classnum)
1478 {
1479     switch(classnum) {
1480     case RSVP_CLASS_SESSION :
1481     case RSVP_CLASS_HOP :
1482     case RSVP_CLASS_INTEGRITY :
1483     case RSVP_CLASS_TIME_VALUES :
1484     case RSVP_CLASS_ERROR :
1485     case RSVP_CLASS_SCOPE :
1486     case RSVP_CLASS_STYLE :
1487     case RSVP_CLASS_FLOWSPEC :
1488     case RSVP_CLASS_FILTER_SPEC :
1489     case RSVP_CLASS_SENDER_TEMPLATE :
1490     case RSVP_CLASS_SENDER_TSPEC :
1491     case RSVP_CLASS_ADSPEC :
1492     case RSVP_CLASS_POLICY :
1493     case RSVP_CLASS_CONFIRM :
1494     case RSVP_CLASS_LABEL :
1495     case RSVP_CLASS_LABEL_REQUEST :
1496     case RSVP_CLASS_HELLO :
1497     case RSVP_CLASS_EXPLICIT_ROUTE :
1498     case RSVP_CLASS_RECORD_ROUTE :
1499     case RSVP_CLASS_MESSAGE_ID :
1500     case RSVP_CLASS_MESSAGE_ID_ACK :
1501     case RSVP_CLASS_MESSAGE_ID_LIST :
1502         return classnum + RSVPF_OBJECT;
1503         break;
1504
1505     case RSVP_CLASS_RECOVERY_LABEL :
1506     case RSVP_CLASS_UPSTREAM_LABEL :
1507     case RSVP_CLASS_LABEL_SET :
1508     case RSVP_CLASS_PROTECTION :
1509         return RSVPF_RECOVERY_LABEL + (classnum - RSVP_CLASS_RECOVERY_LABEL);
1510
1511     case RSVP_CLASS_SUGGESTED_LABEL :
1512     case RSVP_CLASS_ACCEPTABLE_LABEL_SET :
1513     case RSVP_CLASS_RESTART_CAP :
1514         return RSVPF_SUGGESTED_LABEL + (classnum - RSVP_CLASS_SUGGESTED_LABEL);
1515
1516     case RSVP_CLASS_DIFFSERV :
1517         return RSVPF_DIFFSERV;
1518
1519     case RSVP_CLASS_CLASSTYPE :
1520         return RSVPF_DSTE;
1521
1522     case RSVP_CLASS_NOTIFY_REQUEST :
1523         return RSVPF_NOTIFY_REQUEST;
1524     case RSVP_CLASS_ADMIN_STATUS :
1525         return RSVPF_ADMIN_STATUS;
1526     case RSVP_CLASS_ASSOCIATION :
1527         return RSVPF_ASSOCIATION;
1528
1529     case RSVP_CLASS_SESSION_ATTRIBUTE :
1530         return RSVPF_SESSION_ATTRIBUTE;
1531     case RSVP_CLASS_GENERALIZED_UNI :
1532         return RSVPF_GENERALIZED_UNI;
1533     case RSVP_CLASS_CALL_ID :
1534         return RSVPF_CALL_ID;
1535     case RSVP_CLASS_DCLASS :
1536         return RSVPF_DCLASS;
1537     case RSVP_CLASS_LSP_TUNNEL_IF_ID :
1538         return RSVPF_LSP_TUNNEL_IF_ID;
1539
1540     default:
1541         return RSVPF_UNKNOWN_OBJ;
1542     }
1543 }
1544
1545 static inline int rsvp_class_to_tree_type(int classnum)
1546 {
1547     switch(classnum) {
1548     case RSVP_CLASS_SESSION :
1549         return TT_SESSION;
1550     case RSVP_CLASS_HOP :
1551         return TT_HOP;
1552     case RSVP_CLASS_INTEGRITY :
1553         return TT_INTEGRITY;
1554     case RSVP_CLASS_TIME_VALUES :
1555         return TT_TIME_VALUES;
1556     case RSVP_CLASS_ERROR :
1557         return TT_ERROR;
1558     case RSVP_CLASS_SCOPE :
1559         return TT_SCOPE;
1560     case RSVP_CLASS_STYLE :
1561         return TT_STYLE;
1562     case RSVP_CLASS_FLOWSPEC :
1563         return TT_FLOWSPEC;
1564     case RSVP_CLASS_FILTER_SPEC :
1565         return TT_FILTER_SPEC;
1566     case RSVP_CLASS_SENDER_TEMPLATE :
1567         return TT_SENDER_TEMPLATE;
1568     case RSVP_CLASS_SENDER_TSPEC :
1569         return TT_TSPEC;
1570     case RSVP_CLASS_ADSPEC :
1571         return TT_ADSPEC;
1572     case RSVP_CLASS_POLICY :
1573         return TT_POLICY;
1574     case RSVP_CLASS_CONFIRM :
1575         return TT_CONFIRM;
1576     case RSVP_CLASS_RECOVERY_LABEL :
1577     case RSVP_CLASS_UPSTREAM_LABEL :
1578     case RSVP_CLASS_SUGGESTED_LABEL :
1579     case RSVP_CLASS_LABEL :
1580         return TT_LABEL;
1581     case RSVP_CLASS_LABEL_REQUEST :
1582         return TT_LABEL_REQUEST;
1583     case RSVP_CLASS_HELLO :
1584         return TT_HELLO_OBJ;
1585     case RSVP_CLASS_EXPLICIT_ROUTE :
1586         return TT_EXPLICIT_ROUTE;
1587     case RSVP_CLASS_RECORD_ROUTE :
1588         return TT_RECORD_ROUTE;
1589     case RSVP_CLASS_MESSAGE_ID :
1590         return TT_MESSAGE_ID;
1591     case RSVP_CLASS_MESSAGE_ID_ACK :
1592         return TT_MESSAGE_ID_ACK;
1593     case RSVP_CLASS_MESSAGE_ID_LIST :
1594         return TT_MESSAGE_ID_LIST;
1595     case RSVP_CLASS_LABEL_SET :
1596         return TT_LABEL_SET;
1597     case RSVP_CLASS_PROTECTION :
1598         return TT_PROTECTION_INFO;
1599     case RSVP_CLASS_ACCEPTABLE_LABEL_SET :
1600         return TT_UNKNOWN_CLASS;
1601     case RSVP_CLASS_RESTART_CAP :
1602         return TT_RESTART_CAP;
1603     case RSVP_CLASS_DIFFSERV :
1604         return TT_DIFFSERV;
1605     case RSVP_CLASS_CLASSTYPE:
1606         return TT_CLASSTYPE;
1607     case RSVP_CLASS_NOTIFY_REQUEST :
1608         return TT_UNKNOWN_CLASS;
1609     case RSVP_CLASS_ADMIN_STATUS :
1610         return TT_ADMIN_STATUS;
1611     case RSVP_CLASS_ASSOCIATION :
1612         return TT_ASSOCIATION;
1613     case RSVP_CLASS_SESSION_ATTRIBUTE :
1614         return TT_SESSION_ATTRIBUTE;
1615     case RSVP_CLASS_GENERALIZED_UNI :
1616         return TT_GEN_UNI;
1617     case RSVP_CLASS_CALL_ID :
1618         return TT_CALL_ID;
1619     case RSVP_CLASS_DCLASS :
1620         return TT_DCLASS;
1621     case RSVP_CLASS_LSP_TUNNEL_IF_ID :
1622         return TT_LSP_TUNNEL_IF_ID;
1623     default:
1624         return TT_UNKNOWN_CLASS;
1625     }
1626 }
1627
1628 static void
1629 find_rsvp_session_tempfilt(tvbuff_t *tvb, int hdr_offset, int *session_offp, int *tempfilt_offp)
1630 {
1631     int s_off = 0, t_off = 0;
1632     int len, off;
1633     guint obj_length;
1634
1635     if (!tvb_bytes_exist(tvb, hdr_offset+6, 2))
1636         goto done;
1637
1638     len = tvb_get_ntohs(tvb, hdr_offset+6) + hdr_offset;
1639     off = hdr_offset + 8;
1640     for (off = hdr_offset + 8; off < len && tvb_bytes_exist(tvb, off, 3);
1641          off += obj_length) {
1642         obj_length = tvb_get_ntohs(tvb, off);
1643         if (obj_length == 0)
1644             break;
1645         switch(tvb_get_guint8(tvb, off+2)) {
1646         case RSVP_CLASS_SESSION:
1647             s_off = off;
1648             break;
1649         case RSVP_CLASS_SENDER_TEMPLATE:
1650         case RSVP_CLASS_FILTER_SPEC:
1651             t_off = off;
1652             break;
1653         default:
1654             break;
1655         }
1656     }
1657
1658  done:
1659     if (session_offp) *session_offp = s_off;
1660     if (tempfilt_offp) *tempfilt_offp = t_off;
1661 }
1662
1663 static char *summary_session (tvbuff_t *tvb, int offset)
1664 {
1665     static char buf[100];
1666
1667     switch(tvb_get_guint8(tvb, offset+3)) {
1668     case RSVP_SESSION_TYPE_IPV4:
1669         g_snprintf(buf, 100, "SESSION: IPv4, Destination %s, Protocol %d, Port %d. ",
1670                  ip_to_str(tvb_get_ptr(tvb, offset+4, 4)),
1671                  tvb_get_guint8(tvb, offset+8),
1672                  tvb_get_ntohs(tvb, offset+10));
1673         break;
1674     case RSVP_SESSION_TYPE_IPV4_LSP:
1675         g_snprintf(buf, 100, "SESSION: IPv4-LSP, Destination %s, Tunnel ID %d, Ext ID %0x. ",
1676                  ip_to_str(tvb_get_ptr(tvb, offset+4, 4)),
1677                  tvb_get_ntohs(tvb, offset+10),
1678                  tvb_get_ntohl(tvb, offset+12));
1679         break;
1680     case RSVP_SESSION_TYPE_AGGREGATE_IPV4:
1681         g_snprintf(buf, 100, "SESSION: IPv4-Aggregate, Destination %s, DSCP %d. ",
1682                    ip_to_str(tvb_get_ptr(tvb, offset+4, 4)),
1683                    tvb_get_guint8(tvb, offset+11));
1684         break;
1685     case RSVP_SESSION_TYPE_IPV4_UNI:
1686         g_snprintf(buf, 100, "SESSION: IPv4-UNI, Destination %s, Tunnel ID %d, Ext Address %s. ",
1687                  ip_to_str(tvb_get_ptr(tvb, offset+4, 4)),
1688                  tvb_get_ntohs(tvb, offset+10),
1689                  ip_to_str(tvb_get_ptr(tvb, offset+12, 4)));
1690         break;
1691     case RSVP_SESSION_TYPE_IPV4_E_NNI:
1692         g_snprintf(buf, 100, "SESSION: IPv4-E-NNI, Destination %s, Tunnel ID %d, Ext Address %s. ",
1693                  ip_to_str(tvb_get_ptr(tvb, offset+4, 4)),
1694                  tvb_get_ntohs(tvb, offset+10),
1695                  ip_to_str(tvb_get_ptr(tvb, offset+12, 4)));
1696         break;
1697     default:
1698         g_snprintf(buf, 100, "SESSION: Type %d. ", tvb_get_guint8(tvb, offset+3));
1699     }
1700
1701     return buf;
1702 }
1703
1704 static char *summary_template (tvbuff_t *tvb, int offset)
1705 {
1706     static char buf[80];
1707     const char *objtype;
1708
1709     if (tvb_get_guint8(tvb, offset+2) == RSVP_CLASS_FILTER_SPEC)
1710         objtype = "FILTERSPEC";
1711     else
1712         objtype = "SENDER TEMPLATE";
1713
1714     switch(tvb_get_guint8(tvb, offset+3)) {
1715     case 1:
1716         g_snprintf(buf, 80, "%s: IPv4, Sender %s, Port %d. ", objtype,
1717                  ip_to_str(tvb_get_ptr(tvb, offset+4, 4)),
1718                  tvb_get_ntohs(tvb, offset+10));
1719         break;
1720     case 7:
1721         g_snprintf(buf, 80, "%s: IPv4-LSP, Tunnel Source: %s, LSP ID: %d. ", objtype,
1722                  ip_to_str(tvb_get_ptr(tvb, offset+4, 4)),
1723                  tvb_get_ntohs(tvb, offset+10));
1724         break;
1725     case 9:
1726         g_snprintf(buf, 80, "%s: IPv4-Aggregate, Aggregator %s. ", objtype,
1727                    ip_to_str(tvb_get_ptr(tvb, offset+4, 4)));
1728         break;
1729     default:
1730         g_snprintf(buf, 80, "%s: Type %d. ", objtype, tvb_get_guint8(tvb, offset+3));
1731     }
1732
1733     return buf;
1734 }
1735
1736 /*------------------------------------------------------------------------------
1737  * SESSION
1738  *------------------------------------------------------------------------------*/
1739 static void
1740 dissect_rsvp_session (proto_item *ti, proto_tree *rsvp_object_tree,
1741                       tvbuff_t *tvb,
1742                       int offset, int obj_length,
1743                       int class _U_, int type,
1744                       rsvp_conversation_info *rsvph)
1745 {
1746     proto_item *hidden_item;
1747     int offset2 = offset + 4;
1748
1749     proto_item_set_text(ti, "%s", summary_session(tvb, offset));
1750
1751     switch(type) {
1752     case RSVP_SESSION_TYPE_IPV4:
1753         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
1754                             "C-type: 1 - IPv4");
1755         proto_tree_add_item(rsvp_object_tree,
1756                             rsvp_filter[RSVPF_SESSION_IP],
1757                             tvb, offset2, 4, FALSE);
1758
1759         proto_tree_add_item(rsvp_object_tree,
1760                             rsvp_filter[RSVPF_SESSION_PROTO], tvb,
1761                             offset2+4, 1, FALSE);
1762         proto_tree_add_text(rsvp_object_tree, tvb, offset2+5, 1,
1763                             "Flags: %x",
1764                             tvb_get_guint8(tvb, offset2+5));
1765         proto_tree_add_item(rsvp_object_tree,
1766                             rsvp_filter[RSVPF_SESSION_PORT], tvb,
1767                             offset2+6, 2, FALSE);
1768
1769         /*
1770          * Save this information to build the conversation request key
1771          * later.
1772          */
1773         rsvph->session_type = RSVP_SESSION_TYPE_IPV4;
1774         SET_ADDRESS(&rsvph->destination, AT_IPv4, 4,
1775                     tvb_get_ptr(tvb, offset2, 4));
1776         rsvph->protocol = tvb_get_guint8(tvb, offset2+4);
1777         rsvph->udp_dest_port = tvb_get_ntohs(tvb, offset2+6);
1778
1779         break;
1780
1781     case RSVP_SESSION_TYPE_IPV6:
1782         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
1783                             "C-type: 2 - IPv6");
1784         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16,
1785                             "Destination address: %s",
1786                             ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
1787         proto_tree_add_text(rsvp_object_tree, tvb, offset2+16, 1,
1788                             "Protocol: %u",
1789                             tvb_get_guint8(tvb, offset2+16));
1790         proto_tree_add_text(rsvp_object_tree, tvb, offset2+17, 1,
1791                             "Flags: %x",
1792                             tvb_get_guint8(tvb, offset2+17));
1793         proto_tree_add_text(rsvp_object_tree, tvb, offset2+18, 2,
1794                             "Destination port: %u",
1795                             tvb_get_ntohs(tvb, offset2+18));
1796         /*
1797          * Save this information to build the conversation request key
1798          * later. IPv6 conversatiuon support is not implemented yet, so only
1799          * the session type is stored.
1800          */
1801         rsvph->session_type = RSVP_SESSION_TYPE_IPV6;
1802
1803         break;
1804
1805     case RSVP_SESSION_TYPE_IPV4_LSP:
1806         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
1807                             "C-type: 7 - IPv4 LSP");
1808         proto_tree_add_item(rsvp_object_tree,
1809                             rsvp_filter[RSVPF_SESSION_IP],
1810                             tvb, offset2, 4, FALSE);
1811
1812         proto_tree_add_item(rsvp_object_tree,
1813                             rsvp_filter[RSVPF_SESSION_TUNNEL_ID],
1814                             tvb, offset2+6, 2, FALSE);
1815
1816         proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 4,
1817                             "Extended Tunnel ID: %u (%s)",
1818                             tvb_get_ntohl(tvb, offset2+8),
1819                             ip_to_str(tvb_get_ptr(tvb, offset2+8, 4)));
1820         hidden_item = proto_tree_add_item(rsvp_object_tree,
1821                                    rsvp_filter[RSVPF_SESSION_EXT_TUNNEL_ID],
1822                                    tvb, offset2+8, 4, FALSE);
1823         PROTO_ITEM_SET_HIDDEN(hidden_item);
1824
1825         /*
1826          * Save this information to build the conversation request key
1827          * later.
1828          */
1829         rsvph->session_type = RSVP_SESSION_TYPE_IPV4_LSP;
1830         SET_ADDRESS(&rsvph->destination, AT_IPv4, 4,
1831                     tvb_get_ptr(tvb, offset2, 4));
1832         rsvph->udp_dest_port = tvb_get_ntohs(tvb, offset2+6);
1833         rsvph->ext_tunnel_id = tvb_get_ntohl(tvb, offset2 + 8);
1834         break;
1835
1836     case RSVP_SESSION_TYPE_AGGREGATE_IPV4:
1837         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
1838                             "C-type: 9 - IPv4 Aggregate");
1839         proto_tree_add_item(rsvp_object_tree,
1840                             rsvp_filter[RSVPF_SESSION_IP],
1841                             tvb, offset2, 4, FALSE);
1842
1843         proto_tree_add_text(rsvp_object_tree, tvb, offset2+7, 1,
1844                             "DSCP: %u (%s)",
1845                             tvb_get_guint8(tvb, offset2+7),
1846                             val_to_str(tvb_get_guint8(tvb, offset2+7),
1847                                        dscp_vals, "Unknown (%d)"));
1848         /*
1849          * Save this information to build the conversation request key
1850          * later.
1851          */
1852         rsvph->session_type = RSVP_SESSION_TYPE_AGGREGATE_IPV4;
1853         SET_ADDRESS(&rsvph->destination, AT_IPv4, 4,
1854                     tvb_get_ptr(tvb, offset2, 4));
1855         rsvph->dscp = tvb_get_guint8(tvb, offset2+7);
1856         rsvph->ext_tunnel_id = tvb_get_ntohl(tvb, offset2 + 8);
1857         break;
1858
1859     case RSVP_SESSION_TYPE_IPV4_UNI:
1860         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
1861                             "C-type: 11 - IPv4 UNI");
1862         proto_tree_add_item(rsvp_object_tree,
1863                             rsvp_filter[RSVPF_SESSION_IP],
1864                             tvb, offset2, 4, FALSE);
1865
1866         proto_tree_add_item(rsvp_object_tree,
1867                             rsvp_filter[RSVPF_SESSION_TUNNEL_ID],
1868                             tvb, offset2+6, 2, FALSE);
1869
1870         proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 4,
1871                             "Extended IPv4 Address: %s",
1872                             ip_to_str(tvb_get_ptr(tvb, offset2+8, 4)));
1873         hidden_item = proto_tree_add_item(rsvp_object_tree,
1874                                    rsvp_filter[RSVPF_SESSION_EXT_TUNNEL_ID],
1875                                    tvb, offset2+8, 4, FALSE);
1876         PROTO_ITEM_SET_HIDDEN(hidden_item);
1877
1878         /*
1879          * Save this information to build the conversation request key
1880          * later.
1881          */
1882         rsvph->session_type = RSVP_SESSION_TYPE_IPV4_UNI;
1883         SET_ADDRESS(&rsvph->destination, AT_IPv4, 4,
1884                     tvb_get_ptr(tvb, offset2, 4));
1885         rsvph->udp_dest_port = tvb_get_ntohs(tvb, offset2+6);
1886         rsvph->ext_tunnel_id = tvb_get_ntohl(tvb, offset2 + 8);
1887
1888         break;
1889
1890     case RSVP_SESSION_TYPE_IPV4_E_NNI:
1891         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
1892                             "C-type: 15 - IPv4 E-NNI");
1893         proto_tree_add_item(rsvp_object_tree,
1894                             rsvp_filter[RSVPF_SESSION_IP],
1895                             tvb, offset2, 4, FALSE);
1896
1897         proto_tree_add_item(rsvp_object_tree,
1898                             rsvp_filter[RSVPF_SESSION_TUNNEL_ID],
1899                             tvb, offset2+6, 2, FALSE);
1900
1901         proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 4,
1902                             "Extended IPv4 Address: %s",
1903                             ip_to_str(tvb_get_ptr(tvb, offset2+8, 4)));
1904         hidden_item = proto_tree_add_item(rsvp_object_tree,
1905                                    rsvp_filter[RSVPF_SESSION_EXT_TUNNEL_ID],
1906                                    tvb, offset2+8, 4, FALSE);
1907         PROTO_ITEM_SET_HIDDEN(hidden_item);
1908
1909         /*
1910          * Save this information to build the conversation request key
1911          * later.
1912          */
1913         rsvph->session_type = RSVP_SESSION_TYPE_IPV4_E_NNI;
1914         SET_ADDRESS(&rsvph->destination, AT_IPv4, 4,
1915                     tvb_get_ptr(tvb, offset2, 4));
1916         rsvph->udp_dest_port = tvb_get_ntohs(tvb, offset2+6);
1917         rsvph->ext_tunnel_id = tvb_get_ntohl(tvb, offset2 + 8);
1918
1919         break;
1920
1921     default:
1922         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
1923                             "C-type: Unknown (%u)",
1924                             type);
1925         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length-4,
1926                             "Data (%d bytes)", obj_length-4);
1927     }
1928 }
1929
1930
1931 /*------------------------------------------------------------------------------
1932  * TLVs for HOP, ERROR and other IF_ID extended objects
1933  *------------------------------------------------------------------------------*/
1934 static void
1935 dissect_rsvp_ifid_tlv (proto_tree *ti, proto_tree *rsvp_object_tree,
1936                        tvbuff_t *tvb, int offset, int obj_length,
1937                        int subtree_type)
1938 {
1939     int     tlv_off;
1940     guint16   tlv_type;
1941     guint     tlv_len;
1942     const char *ifindex_name;
1943     proto_tree *rsvp_ifid_subtree, *ti2;
1944     int       offset2 = offset + 4;
1945
1946     for (tlv_off = 0; tlv_off < obj_length - 12; ) {
1947         tlv_type = tvb_get_ntohs(tvb, offset+tlv_off);
1948         tlv_len = tvb_get_ntohs(tvb, offset+tlv_off+2);
1949
1950         if (tlv_len == 0) {
1951             proto_tree_add_text(rsvp_object_tree, tvb, offset+tlv_off+2, 2,
1952                 "Invalid length (0)");
1953             return;
1954         }
1955         switch(tlv_type) {
1956         case 1:
1957             ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
1958                                       offset+tlv_off, 8,
1959                                       "IPv4 TLV - %s",
1960                                       ip_to_str(tvb_get_ptr(tvb, offset+tlv_off+4, 4)));
1961
1962             rsvp_ifid_subtree = proto_item_add_subtree(ti2, subtree_type);
1963             proto_tree_add_text(rsvp_ifid_subtree, tvb, offset+tlv_off, 2,
1964                                 "Type: 1 (IPv4)");
1965             proto_tree_add_text(rsvp_ifid_subtree, tvb, offset+tlv_off+2, 2,
1966                                 "Length: %u",
1967                                 tvb_get_ntohs(tvb, offset+tlv_off+2));
1968             proto_tree_add_text(rsvp_ifid_subtree, tvb, offset+tlv_off+4, 4,
1969                                 "IPv4 address: %s",
1970                                 ip_to_str(tvb_get_ptr(tvb, offset+tlv_off+4, 4)));
1971             proto_item_append_text(ti, "Data IPv4: %s. ",
1972                                    ip_to_str(tvb_get_ptr(tvb, offset+tlv_off+4, 4)));
1973             break;
1974
1975         case 3:
1976             ifindex_name = "";
1977             goto ifid_ifindex;
1978         case 4:
1979             ifindex_name = " Forward";
1980             goto ifid_ifindex;
1981         case 5:
1982             ifindex_name = " Reverse";
1983         ifid_ifindex:
1984             ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
1985                                       offset+tlv_off, 12,
1986                                       "Interface-Index%s TLV - %s, %d",
1987                                       ifindex_name,
1988                                       ip_to_str(tvb_get_ptr(tvb, offset+tlv_off+4, 4)),
1989                                       tvb_get_ntohl(tvb, offset+tlv_off+8));
1990             rsvp_ifid_subtree = proto_item_add_subtree(ti2, subtree_type);
1991             proto_tree_add_text(rsvp_ifid_subtree, tvb, offset+tlv_off, 2,
1992                                 "Type: %d (Interface Index%s)", tlv_type, ifindex_name);
1993             proto_tree_add_text(rsvp_ifid_subtree, tvb, offset+tlv_off+2, 2,
1994                                 "Length: %u",
1995                                 tvb_get_ntohs(tvb, offset+tlv_off+2));
1996             proto_tree_add_text(rsvp_ifid_subtree, tvb, offset+tlv_off+4, 4,
1997                                 "IPv4 address: %s",
1998                                 ip_to_str(tvb_get_ptr(tvb, offset+tlv_off+4, 4)));
1999             proto_tree_add_text(rsvp_ifid_subtree, tvb, offset+tlv_off+8, 4,
2000                                 "Interface-ID: %d",
2001                                 tvb_get_ntohl(tvb, offset+tlv_off+8));
2002             proto_item_append_text(ti, "Data If-Index%s: %s, %d. ", ifindex_name,
2003                                    ip_to_str(tvb_get_ptr(tvb, offset+tlv_off+4, 4)),
2004                                    tvb_get_ntohl(tvb, offset+tlv_off+8));
2005             break;
2006
2007         default:
2008             proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
2009                                 "Logical interface: %u",
2010                                 tvb_get_ntohl(tvb, offset2+4));
2011         }
2012         tlv_off += tlv_len;
2013     }
2014 }
2015
2016 /*------------------------------------------------------------------------------
2017  * HOP
2018  *------------------------------------------------------------------------------*/
2019 static void
2020 dissect_rsvp_hop (proto_item *ti, proto_tree *rsvp_object_tree,
2021                   tvbuff_t *tvb,
2022                   int offset, int obj_length,
2023                   int class _U_, int type)
2024 {
2025     int offset2 = offset + 4;
2026
2027     switch(type) {
2028     case 1:
2029         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2030                             "C-type: 1 - IPv4");
2031         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
2032                             "Neighbor address: %s",
2033                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
2034         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
2035                             "Logical interface: %u",
2036                             tvb_get_ntohl(tvb, offset2+4));
2037         proto_item_set_text(ti, "HOP: IPv4, %s",
2038                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
2039         break;
2040
2041     case 2:
2042         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2043                             "C-type: 2 - IPv6");
2044         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16,
2045                             "Neighbor address: %s",
2046                             ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
2047         proto_tree_add_text(rsvp_object_tree, tvb, offset2+16, 4,
2048                             "Logical interface: 0x%08x",
2049                             tvb_get_ntohl(tvb, offset2+16));
2050         break;
2051
2052     case 3:
2053         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2054                             "C-type: 3 - IPv4 IF-ID");
2055         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
2056                             "Neighbor address: %s",
2057                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
2058         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
2059                             "Logical interface: %u",
2060                             tvb_get_ntohl(tvb, offset2+4));
2061
2062         proto_item_set_text(ti, "HOP: IPv4 IF-ID. Control IPv4: %s. ",
2063                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
2064
2065         dissect_rsvp_ifid_tlv(ti, rsvp_object_tree, tvb, offset+12, obj_length,
2066                               TREE(TT_HOP_SUBOBJ));
2067
2068         break;
2069
2070     default:
2071         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2072                             "C-type: Unknown (%u)",
2073                             type);
2074         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
2075                             "Data (%d bytes)", obj_length - 4);
2076     }
2077 }
2078
2079 /*------------------------------------------------------------------------------
2080  * TIME VALUES
2081  *------------------------------------------------------------------------------*/
2082 static void
2083 dissect_rsvp_time_values (proto_item *ti, proto_tree *rsvp_object_tree,
2084                           tvbuff_t *tvb,
2085                           int offset, int obj_length,
2086                           int class _U_, int type)
2087 {
2088     int offset2 = offset + 4;
2089
2090     switch(type) {
2091     case 1:
2092         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2093                             "C-type: 1");
2094         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
2095                             "Refresh interval: %u ms (%u seconds)",
2096                             tvb_get_ntohl(tvb, offset2),
2097                             tvb_get_ntohl(tvb, offset2)/1000);
2098         proto_item_set_text(ti, "TIME VALUES: %d ms",
2099                             tvb_get_ntohl(tvb, offset2));
2100         break;
2101
2102     default:
2103         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2104                             "C-type: Unknown (%u)",
2105                             type);
2106         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
2107                             "Data (%d bytes)", obj_length - 4);
2108         break;
2109     }
2110 }
2111
2112 /*------------------------------------------------------------------------------
2113  * Error value field in ERROR object
2114  *------------------------------------------------------------------------------*/
2115 static guint16
2116 dissect_rsvp_error_value (proto_tree *ti, tvbuff_t *tvb,
2117                           int offset, guint8 error_code)
2118 {
2119     guint16 error_val;
2120     const value_string *rsvp_error_vals = NULL;
2121
2122     error_val = tvb_get_ntohs(tvb, offset);
2123     switch (error_code) {
2124     case RSVP_ERROR_ADMISSION:
2125         rsvp_error_vals = rsvp_admission_control_error_vals;
2126         break;
2127     case RSVP_ERROR_TRAFFIC:
2128         rsvp_error_vals = rsvp_traffic_control_error_vals;
2129         break;
2130     case RSVP_ERROR_ROUTING:
2131         rsvp_error_vals = rsvp_routing_error_vals;
2132         break;
2133     case RSVP_ERROR_NOTIFY:
2134         rsvp_error_vals = rsvp_notify_error_vals;
2135         break;
2136     case RSVP_ERROR_DIFFSERV:
2137         rsvp_error_vals = rsvp_diffserv_error_vals;
2138         break;
2139     case RSVP_ERROR_DSTE:
2140         rsvp_error_vals = rsvp_diffserv_aware_te_error_vals;
2141         break;
2142     }
2143     switch (error_code) {
2144     case RSVP_ERROR_ADMISSION:
2145     case RSVP_ERROR_TRAFFIC:
2146     case RSVP_ERROR_NOTIFY:
2147     case RSVP_ERROR_ROUTING:
2148     case RSVP_ERROR_DIFFSERV:
2149     case RSVP_ERROR_DSTE:
2150         if ((error_val & 0xc0) == 0) {
2151             proto_tree_add_text(ti, tvb, offset, 2,
2152                 "Error value: %u - %s", error_val,
2153                 val_to_str(error_val, rsvp_error_vals, "Unknown (%d)"));
2154             break;
2155         }
2156     default:
2157         proto_tree_add_text(ti, tvb, offset, 2,
2158             "Error value: %u", error_val);
2159     }
2160     return error_val;
2161 }
2162
2163 /*------------------------------------------------------------------------------
2164  * ERROR
2165  *------------------------------------------------------------------------------*/
2166 static void
2167 dissect_rsvp_error (proto_item *ti, proto_tree *rsvp_object_tree,
2168                     tvbuff_t *tvb,
2169                     int offset, int obj_length,
2170                     int class _U_, int type)
2171 {
2172     int offset2 = offset + 4;
2173     int offset3;
2174     guint8 error_flags;
2175     guint8 error_code;
2176     guint16 error_val;
2177     proto_tree *ti2, *rsvp_error_subtree;
2178
2179     switch(type) {
2180     case 1: {
2181         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2182                             "C-type: 1 - IPv4");
2183         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
2184                             "Error node: %s",
2185                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
2186         offset3 = offset2+4;
2187         break;
2188     }
2189
2190     case 2: {
2191         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2192                             "C-type: 2 - IPv6");
2193         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16,
2194                             "Error node: %s",
2195                             ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
2196         offset3 = offset2+16;
2197         break;
2198     }
2199
2200     case 3: {
2201         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2202                             "C-type: 3 - IPv4 IF-ID");
2203         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
2204                             "Error node: %s",
2205                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
2206         offset3 = offset2+4;
2207         break;
2208     }
2209
2210     default:
2211         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2212                             "C-type: Unknown (%u)",
2213                             type);
2214         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
2215                             "Data (%d bytes)", obj_length - 4);
2216         return;
2217     }
2218
2219     error_flags = tvb_get_guint8(tvb, offset3);
2220     ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset3, 1,
2221                               "Flags: 0x%02x", error_flags);
2222     rsvp_error_subtree = proto_item_add_subtree(ti2, TREE(TT_ERROR_FLAGS));
2223     proto_tree_add_text(rsvp_error_subtree, tvb, offset3, 1,
2224                     decode_boolean_bitfield(error_flags, 0x04, 8,
2225                                             "Path State Removed",
2226                                             ""));
2227     proto_tree_add_text(rsvp_error_subtree, tvb, offset3, 1,
2228                     decode_boolean_bitfield(error_flags, 0x02, 8,
2229                                             "NotGuilty",
2230                                             ""));
2231     proto_tree_add_text(rsvp_error_subtree, tvb, offset3, 1,
2232                     decode_boolean_bitfield(error_flags, 0x01, 8,
2233                                             "InPlace",
2234                                             ""));
2235     proto_item_append_text(ti2, " %s %s %s",
2236                            (error_flags & (1<<2))  ? "Path-State-Removed" : "",
2237                            (error_flags & (1<<1))  ? "NotGuilty" : "",
2238                            (error_flags & (1<<0))  ? "InPlace" : "");
2239     error_code = tvb_get_guint8(tvb, offset3+1);
2240     proto_tree_add_text(rsvp_object_tree, tvb, offset3+1, 1,
2241                         "Error code: %u - %s", error_code,
2242                         val_to_str(error_code, rsvp_error_codes, "Unknown (%d)"));
2243     error_val = dissect_rsvp_error_value(rsvp_object_tree, tvb, offset3+2, error_code);
2244
2245     switch (type) {
2246     case 1:
2247         proto_item_set_text(ti, "ERROR: IPv4, Error code: %s, Value: %d, Error Node: %s",
2248                             val_to_str(error_code, rsvp_error_codes, "Unknown (%d)"),
2249                             error_val, ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
2250         break;
2251     case 3:
2252         proto_item_set_text(ti, "ERROR: IPv4 IF-ID, Error code: %s, Value: %d, Control Node: %s. ",
2253                             val_to_str(error_code, rsvp_error_codes, "Unknown (%d)"),
2254                             error_val, ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
2255         dissect_rsvp_ifid_tlv(ti, rsvp_object_tree, tvb, offset+12, obj_length,
2256                               TREE(TT_ERROR_SUBOBJ));
2257         break;
2258     }
2259 }
2260
2261 /*------------------------------------------------------------------------------
2262  * SCOPE
2263  *------------------------------------------------------------------------------*/
2264 static void
2265 dissect_rsvp_scope (proto_item *ti _U_, proto_tree *rsvp_object_tree,
2266                     tvbuff_t *tvb,
2267                     int offset, int obj_length,
2268                     int class _U_, int type)
2269 {
2270     int offset2 = offset + 4;
2271     int mylen;
2272
2273     mylen = obj_length - 4;
2274     switch(type) {
2275     case 1: {
2276         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2277                             "C-type: 1 - IPv4");
2278         while (mylen > 0) {
2279             proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
2280                                 "IPv4 Address: %s",
2281                                 ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
2282             offset2 += 4;
2283             mylen -= 4;
2284         }
2285         break;
2286     }
2287
2288     case 2: {
2289         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2290                             "C-type: 2 - IPv6");
2291         while (mylen > 0) {
2292             proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16,
2293                                 "IPv6 Address: %s",
2294                                 ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
2295             offset2 += 16;
2296             mylen -= 16;
2297         }
2298         break;
2299     }
2300
2301     default:
2302         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2303                             "C-type: Unknown (%u)",
2304                             type);
2305         proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
2306                             "Data (%d bytes)", mylen);
2307     }
2308 }
2309
2310 /*------------------------------------------------------------------------------
2311  * STYLE
2312  *------------------------------------------------------------------------------*/
2313 static void
2314 dissect_rsvp_style (proto_item *ti, proto_tree *rsvp_object_tree,
2315                     tvbuff_t *tvb,
2316                     int offset, int obj_length,
2317                     int class _U_, int type)
2318 {
2319     int offset2 = offset + 4;
2320
2321     switch(type) {
2322     case 1: {
2323         guint32 style;
2324
2325         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2326                             "C-type: 1");
2327         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
2328                             "Flags: 0x%02x",
2329                             tvb_get_guint8(tvb, offset2));
2330         style = tvb_get_ntoh24(tvb, offset2+1);
2331         proto_tree_add_text(rsvp_object_tree, tvb, offset2+1,
2332                             3, "Style: 0x%06X - %s", style,
2333                             val_to_str(style, style_vals, "Unknown"));
2334         proto_item_set_text(ti, "STYLE: %s (%d)",
2335                             val_to_str(style, style_vals, "Unknown"),
2336                             style);
2337         break;
2338     }
2339
2340     default:
2341         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2342                             "C-type: Unknown (%u)",
2343                             type);
2344         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
2345                             "Data (%d bytes)", obj_length - 4);
2346         break;
2347     }
2348 }
2349
2350 /*------------------------------------------------------------------------------
2351  * CONFIRM
2352  *------------------------------------------------------------------------------*/
2353 static void
2354 dissect_rsvp_confirm (proto_item *ti, proto_tree *rsvp_object_tree,
2355                       tvbuff_t *tvb,
2356                       int offset, int obj_length,
2357                       int class _U_, int type)
2358 {
2359     int offset2 = offset + 4;
2360
2361     switch(type) {
2362     case 1: {
2363         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2364                             "C-type: 1 - IPv4");
2365         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
2366                             "Receiver address: %s",
2367                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
2368         proto_item_set_text(ti, "CONFIRM: Receiver %s",
2369                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
2370         break;
2371     }
2372
2373     case 2: {
2374         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2375                             "C-type: 2 - IPv6");
2376         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16,
2377                             "Receiver address: %s",
2378                             ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
2379         break;
2380     }
2381
2382     default:
2383         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2384                             "C-type: Unknown (%u)",
2385                             type);
2386         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
2387                             "Data (%d bytes)", obj_length - 4);
2388     }
2389 }
2390
2391 /*------------------------------------------------------------------------------
2392  * SENDER TEMPLATE and FILTERSPEC
2393  *------------------------------------------------------------------------------*/
2394 static void
2395 dissect_rsvp_template_filter (proto_item *ti, proto_tree *rsvp_object_tree,
2396                               tvbuff_t *tvb,
2397                               int offset, int obj_length,
2398                               int class _U_, int type,
2399                               rsvp_conversation_info *rsvph)
2400 {
2401     int offset2 = offset + 4;
2402
2403     proto_item_set_text(ti, "%s", summary_template(tvb, offset));
2404     switch(type) {
2405     case 1:
2406          proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2407                              "C-type: 1 - IPv4");
2408          proto_tree_add_item(rsvp_object_tree,
2409                              rsvp_filter[RSVPF_SENDER_IP],
2410                              tvb, offset2, 4, FALSE);
2411          proto_tree_add_item(rsvp_object_tree,
2412                              rsvp_filter[RSVPF_SENDER_PORT],
2413                              tvb, offset2+6, 2, FALSE);
2414
2415          /*
2416           * Save this information to build the conversation request key later.
2417           */
2418          SET_ADDRESS(&rsvph->source, AT_IPv4, 4, tvb_get_ptr(tvb, offset2, 4));
2419          rsvph->udp_source_port = tvb_get_ntohs(tvb, offset2+6);
2420          break;
2421
2422      case 2:
2423          proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2424                              "C-type: 2 - IPv6");
2425          proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16,
2426                              "Source address: %s",
2427                              ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
2428          proto_tree_add_text(rsvp_object_tree, tvb, offset2+18, 2,
2429                              "Source port: %u",
2430                              tvb_get_ntohs(tvb, offset2+18));
2431          break;
2432
2433      case 7:
2434          proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2435                              "C-type: 7 - IPv4 LSP");
2436          proto_tree_add_item(rsvp_object_tree,
2437                              rsvp_filter[RSVPF_SENDER_IP],
2438                              tvb, offset2, 4, FALSE);
2439          proto_tree_add_item(rsvp_object_tree,
2440                              rsvp_filter[RSVPF_SENDER_LSP_ID],
2441                              tvb, offset2+6, 2, FALSE);
2442
2443          /*
2444           * Save this information to build the conversation request key later.
2445           */
2446          SET_ADDRESS(&rsvph->source, AT_IPv4, 4, tvb_get_ptr(tvb, offset2, 4));
2447          rsvph->udp_source_port = tvb_get_ntohs(tvb, offset2+6);
2448          break;
2449
2450     case 9:
2451          proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2452                              "C-type: 9 - IPv4 Aggregate");
2453          proto_tree_add_item(rsvp_object_tree,
2454                              rsvp_filter[RSVPF_SENDER_IP],
2455                              tvb, offset2, 4, FALSE);
2456
2457          /*
2458           * Save this information to build the conversation request key later.
2459           */
2460          SET_ADDRESS(&rsvph->source, AT_IPv4, 4, tvb_get_ptr(tvb, offset2, 4));
2461          break;
2462
2463      default:
2464          proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2465                              "C-type: Unknown (%u)",
2466                              type);
2467          proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
2468                              "Data (%d bytes)", obj_length - 4);
2469      }
2470 }
2471
2472 /*------------------------------------------------------------------------------
2473  * TLVs for Ethernet SENDER TSPEC and FLOWSPEC
2474  * draft-ietf-ccamp-ethernet-traffic-parameters-02
2475  *------------------------------------------------------------------------------*/
2476 static void
2477 dissect_rsvp_eth_tspec_tlv(proto_item *ti, proto_tree *rsvp_object_tree,
2478                            tvbuff_t *tvb, int offset, int tlv_length,
2479                            int subtree_type)
2480 {
2481     int       tlv_off;
2482     guint16   tlv_type;
2483     int       tlv_len;
2484     guint8    profile;
2485     proto_tree *rsvp_ethspec_subtree, *ethspec_profile_subtree, *ti2, *ti3;
2486
2487     for (tlv_off = 0; tlv_off < tlv_length; ) {
2488         tlv_type = tvb_get_ntohs(tvb, offset+tlv_off);
2489         tlv_len = tvb_get_ntohs(tvb, offset+tlv_off+2);
2490
2491         if (tlv_len == 0 || tlv_off+tlv_len > tlv_length) {
2492             proto_tree_add_text(rsvp_object_tree, tvb, offset+tlv_off+2, 2,
2493                                 "Invalid length");
2494             return;
2495         }
2496         switch(tlv_type) {
2497         case 128:
2498             ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
2499                                       offset+tlv_off, tlv_len,
2500                                       "RESERVED (TBD)");
2501             rsvp_ethspec_subtree = proto_item_add_subtree(ti2, subtree_type);
2502             proto_tree_add_text(rsvp_ethspec_subtree, tvb, offset+tlv_off, 2,
2503                                 "Type: 128 (RESERVED)");
2504             proto_tree_add_text(rsvp_ethspec_subtree, tvb, offset+tlv_off+2, 2,
2505                                 "Length: %u", tlv_len);
2506             break;
2507             
2508         case 129:
2509             ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
2510                                       offset+tlv_off, tlv_len,
2511                                       "Ethernet Bandwidth Profile TLV: CIR=%.10g, CBS=%.10g, "
2512                                       "EIR=%.10g, EBS=%.10g",
2513                                       tvb_get_ntohieee_float(tvb, offset+tlv_off+8),
2514                                       tvb_get_ntohieee_float(tvb, offset+tlv_off+12),
2515                                       tvb_get_ntohieee_float(tvb, offset+tlv_off+16),
2516                                       tvb_get_ntohieee_float(tvb, offset+tlv_off+20));
2517             rsvp_ethspec_subtree = proto_item_add_subtree(ti2, subtree_type);
2518             proto_tree_add_text(rsvp_ethspec_subtree, tvb, offset+tlv_off, 2,
2519                                 "Type: %d - Ethernet Bandwidth Profile", tlv_type);
2520             proto_tree_add_text(rsvp_ethspec_subtree, tvb, offset+tlv_off+2, 2,
2521                                 "Length: %u", tlv_len);
2522             profile = tvb_get_guint8(tvb, offset+tlv_off+4);
2523             ti3 = proto_tree_add_text(rsvp_ethspec_subtree, tvb, offset+tlv_off+4, 1,
2524                                       "Profile: 0x%02x", profile);
2525             ethspec_profile_subtree = proto_item_add_subtree(ti3, TREE(TT_ETHSPEC_SUBTREE));
2526             proto_tree_add_text(ethspec_profile_subtree, tvb, offset+tlv_off+4, 1,
2527                                 decode_boolean_bitfield(profile, 0x02, 8,
2528                                             "Color Mode (CM) set",
2529                                             "Color Mode (CM) NOT set"));
2530             proto_tree_add_text(ethspec_profile_subtree, tvb, offset+tlv_off+4, 1,
2531                                 decode_boolean_bitfield(profile, 0x01, 8,
2532                                             "Coupling Flag (CF) set",
2533                                             "Coupling Flag (CF) NOT set"));
2534             proto_item_append_text(ti3, " %s %s",
2535                                    (profile & (1<<1))  ? "CM" : "",
2536                                    (profile & (1<<0))  ? "CF" : "");
2537             proto_tree_add_text(rsvp_ethspec_subtree, tvb, offset+tlv_off+5, 1,
2538                                 "Index: %x", tvb_get_guint8(tvb, offset+tlv_off+5));
2539             proto_tree_add_text(rsvp_ethspec_subtree, tvb, offset+tlv_off+6, 2,
2540                                 "Reserved: %x", tvb_get_ntohs(tvb, offset+tlv_off+6));
2541             proto_tree_add_text(rsvp_ethspec_subtree, tvb, offset+tlv_off+8, 4, "CIR: %.10g",
2542                                 tvb_get_ntohieee_float(tvb, offset+tlv_off+8));
2543             proto_tree_add_text(rsvp_ethspec_subtree, tvb, offset+tlv_off+12, 4, "CBS: %.10g",
2544                                 tvb_get_ntohieee_float(tvb, offset+tlv_off+12));
2545             proto_tree_add_text(rsvp_ethspec_subtree, tvb, offset+tlv_off+16, 4, "EIR: %.10g",
2546                                 tvb_get_ntohieee_float(tvb, offset+tlv_off+16));
2547             proto_tree_add_text(rsvp_ethspec_subtree, tvb, offset+tlv_off+20, 4, "EBS: %.10g",
2548                                 tvb_get_ntohieee_float(tvb, offset+tlv_off+20));
2549
2550             proto_item_append_text(ti, "ETH profile: CIR=%.10g, CBS=%.10g, EIR=%.10g, "
2551                                        "EBS=%.10g",
2552                                    tvb_get_ntohieee_float(tvb, offset+tlv_off+8),
2553                                    tvb_get_ntohieee_float(tvb, offset+tlv_off+12),
2554                                    tvb_get_ntohieee_float(tvb, offset+tlv_off+16),
2555                                    tvb_get_ntohieee_float(tvb, offset+tlv_off+20));
2556             break;
2557             
2558         default:
2559             proto_tree_add_text(rsvp_object_tree, tvb, offset+tlv_off, 2,
2560                                 "Unknown TLV: %u", tlv_type);
2561         }
2562         tlv_off += tlv_len;
2563     }
2564 }
2565
2566 /*------------------------------------------------------------------------------
2567  * SENDER TSPEC
2568  *------------------------------------------------------------------------------*/
2569 static void
2570 dissect_rsvp_tspec (proto_item *ti, proto_tree *rsvp_object_tree,
2571                     tvbuff_t *tvb,
2572                     int offset, int obj_length,
2573                     int class _U_, int type)
2574 {
2575     int offset2 = offset + 4;
2576     int mylen;
2577     proto_tree *tspec_tree, *ti2;
2578     guint8 signal_type;
2579     guint16 switch_gran;
2580
2581     mylen = obj_length - 4;
2582
2583     switch(type) {
2584     case 2:
2585         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2586                             "C-type: 2 - Integrated Services");
2587         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
2588                             "Message format version: %u",
2589                             tvb_get_guint8(tvb, offset2)>>4);
2590         proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
2591                             "Data length: %u words, not including header",
2592                             tvb_get_ntohs(tvb, offset2+2));
2593
2594         mylen -= 4;
2595         offset2 += 4;
2596
2597         proto_item_set_text(ti, "SENDER TSPEC: IntServ: ");
2598
2599         while (mylen > 0) {
2600             guint8 service_num;
2601             guint8 param_id;
2602             guint param_len;
2603             guint param_len_processed;
2604             guint length;
2605
2606             service_num = tvb_get_guint8(tvb, offset2);
2607             proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
2608                                 "Service header: %u - %s",
2609                                 service_num,
2610                                 val_to_str(service_num, qos_vals, "Unknown"));
2611             length = tvb_get_ntohs(tvb, offset2+2);
2612             proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
2613                                 "Length of service %u data: %u words, "
2614                                 "not including header",
2615                                 service_num, length);
2616
2617             mylen -= 4;
2618             offset2 += 4;
2619
2620             /* Process all known service headers as a set of parameters */
2621             param_len_processed = 0;
2622             while (param_len_processed < length) {
2623                 param_id = tvb_get_guint8(tvb, offset2);
2624                 param_len = tvb_get_ntohs(tvb, offset2+2) + 1;
2625                 if (param_len < 1)
2626                     THROW(ReportedBoundsError);
2627                 switch(param_id) {
2628                 case 127:
2629                     /* Token Bucket */
2630                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
2631                                               offset2, param_len*4,
2632                                               "Token Bucket TSpec: ");
2633                     tspec_tree = proto_item_add_subtree(ti2, TREE(TT_TSPEC_SUBTREE));
2634
2635                     proto_tree_add_text(tspec_tree, tvb, offset2, 1,
2636                                         "Parameter %u - %s",
2637                                         param_id,
2638                                         val_to_str(param_id, svc_vals, "Unknown"));
2639                     proto_tree_add_text(tspec_tree, tvb, offset2+1, 1,
2640                                         "Parameter %u flags: 0x%02x",
2641                                         param_id,
2642                                         tvb_get_guint8(tvb, offset2+1));
2643                     proto_tree_add_text(tspec_tree, tvb, offset2+2, 2,
2644                                         "Parameter %u data length: %u words, "
2645                                         "not including header",
2646                                         param_id,
2647                                         tvb_get_ntohs(tvb, offset2+2));
2648                     proto_tree_add_text(tspec_tree, tvb, offset2+4, 4,
2649                                         "Token bucket rate: %.10g",
2650                                         tvb_get_ntohieee_float(tvb, offset2+4));
2651                     proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
2652                                         "Token bucket size: %.10g",
2653                                         tvb_get_ntohieee_float(tvb, offset2+8));
2654                     proto_tree_add_text(tspec_tree, tvb, offset2+12, 4,
2655                                         "Peak data rate: %.10g",
2656                                         tvb_get_ntohieee_float(tvb, offset2+12));
2657                     proto_tree_add_text(tspec_tree, tvb, offset2+16, 4,
2658                                         "Minimum policed unit [m]: %u",
2659                                         tvb_get_ntohl(tvb, offset2+16));
2660                     proto_tree_add_text(tspec_tree, tvb, offset2+20, 4,
2661                                         "Maximum packet size [M]: %u",
2662                                         tvb_get_ntohl(tvb, offset2+20));
2663                     proto_item_append_text(ti, "Token Bucket, %.10g bytes/sec. ",
2664                                            tvb_get_ntohieee_float(tvb, offset2+4));
2665                     proto_item_append_text(ti2, "Rate=%.10g Burst=%.10g Peak=%.10g m=%u M=%u",
2666                                            tvb_get_ntohieee_float(tvb, offset2+4),
2667                                            tvb_get_ntohieee_float(tvb, offset2+8),
2668                                            tvb_get_ntohieee_float(tvb, offset2+12),
2669                                            tvb_get_ntohl(tvb, offset2+16),
2670                                            tvb_get_ntohl(tvb, offset2+20));
2671                     break;
2672
2673                 case 128:
2674                     /* Null Service (RFC2997) */
2675                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
2676                                               offset2, param_len*4,
2677                                               "Null Service TSpec: ");
2678                     tspec_tree = proto_item_add_subtree(ti2, TREE(TT_TSPEC_SUBTREE));
2679
2680                     proto_tree_add_text(tspec_tree, tvb, offset2, 1,
2681                                         "Parameter %u - %s",
2682                                         param_id,
2683                                         val_to_str(param_id, svc_vals, "Unknown"));
2684                     proto_tree_add_text(tspec_tree, tvb, offset2+1, 1,
2685                                         "Parameter %u flags: %x",
2686                                         param_id,
2687                                         tvb_get_guint8(tvb, offset2+1));
2688                     proto_tree_add_text(tspec_tree, tvb, offset2+2, 2,
2689                                         "Parameter %u data length: %u words, "
2690                                         "not including header",
2691                                         param_id,
2692                                         tvb_get_ntohs(tvb, offset2+2));
2693                     proto_tree_add_text(tspec_tree, tvb, offset2+4, 4,
2694                                         "Maximum packet size [M]: %u",
2695                                         tvb_get_ntohl(tvb, offset2+4));
2696                     proto_item_append_text(ti, "Null Service. M=%u",
2697                                            tvb_get_ntohl(tvb, offset2+4));
2698                     proto_item_append_text(ti2, "Max pkt size=%u",
2699                                            tvb_get_ntohl(tvb, offset2+4));
2700                     break;
2701
2702                 case 126:
2703                     /* Compression hint (RFC3006) */
2704                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
2705                                               offset2, param_len*4,
2706                                               "Compression Hint: ");
2707                     tspec_tree = proto_item_add_subtree(ti2, TREE(TT_TSPEC_SUBTREE));
2708
2709                     proto_tree_add_text(tspec_tree, tvb, offset2, 1,
2710                                         "Parameter %u - %s",
2711                                         param_id,
2712                                         val_to_str(param_id, svc_vals, "Unknown"));
2713                     proto_tree_add_text(tspec_tree, tvb, offset2+1, 1,
2714                                         "Parameter %u flags: %x",
2715                                         param_id,
2716                                         tvb_get_guint8(tvb, offset2+1));
2717                     proto_tree_add_text(tspec_tree, tvb, offset2+2, 2,
2718                                         "Parameter %u data length: %u words, "
2719                                         "not including header",
2720                                         param_id,
2721                                         tvb_get_ntohs(tvb, offset2+2));
2722                     proto_tree_add_text(tspec_tree, tvb, offset2+4, 4,
2723                                         "Hint: %u",
2724                                         tvb_get_ntohl(tvb, offset2+4));
2725                     proto_tree_add_text(tspec_tree, tvb, offset2+4, 4,
2726                                         "Compression Factor: %u",
2727                                         tvb_get_ntohl(tvb, offset2+8));
2728                     proto_item_append_text(ti, "Compression Hint. Hint=%u, Factor=%u",
2729                                            tvb_get_ntohl(tvb, offset2+4),
2730                                            tvb_get_ntohl(tvb, offset2+8));
2731                     proto_item_append_text(ti2, "Hint=%u, Factor=%u",
2732                                            tvb_get_ntohl(tvb, offset2+4),
2733                                            tvb_get_ntohl(tvb, offset2+8));
2734                     break;
2735
2736                 default:
2737                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, param_len*4,
2738                                         "Unknown parameter %d, %d words",
2739                                         param_id, param_len);
2740                     break;
2741                 }
2742                 param_len_processed += param_len;
2743                 offset2 += param_len*4;
2744             }
2745             mylen -= length*4;
2746         }
2747         break;
2748
2749     case 4: /* SONET/SDH Tspec */
2750         proto_item_set_text(ti, "SENDER TSPEC: SONET/SDH: ");
2751
2752         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2753                             "C-type: 4 - SONET/SDH");
2754         signal_type = tvb_get_guint8(tvb, offset2);
2755         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
2756                             "Signal Type: %d - %s", signal_type,
2757                             val_to_str(signal_type,
2758                                        gmpls_sonet_signal_type_str, "Unknown"));
2759         ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2+1, 1,
2760                             "Requested Concatenation (RCC): %d", tvb_get_guint8(tvb, offset2+1));
2761         tspec_tree = proto_item_add_subtree(ti2, TREE(TT_TSPEC_SUBTREE));
2762         proto_tree_add_text(tspec_tree, tvb, offset2+1, 1,
2763                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+1), 0x01, 8,
2764                                                     "Standard contiguous concatenation",
2765                                                     "No standard contiguous concatenation"));
2766         proto_tree_add_text(tspec_tree, tvb, offset2+1, 1,
2767                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+1), 0x02, 8,
2768                                                     "Arbitrary contiguous concatenation",
2769                                                     "No arbitrary contiguous concatenation"));
2770         proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
2771                             "Number of Contiguous Components (NCC): %d", tvb_get_ntohs(tvb, offset2+2));
2772         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 2,
2773                             "Number of Virtual Components (NVC): %d", tvb_get_ntohs(tvb, offset2+4));
2774         proto_tree_add_text(rsvp_object_tree, tvb, offset2+6, 2,
2775                             "Multiplier (MT): %d", tvb_get_ntohs(tvb, offset2+6));
2776         ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 4,
2777                                   "Transparency (T): 0x%0x", tvb_get_ntohl(tvb, offset2+8));
2778         tspec_tree = proto_item_add_subtree(ti2, TREE(TT_TSPEC_SUBTREE));
2779         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
2780                             decode_boolean_bitfield(tvb_get_ntohl(tvb, offset2+8), 0x0001, 32,
2781                                                     "Section/Regenerator Section layer transparency",
2782                                                     "No Section/Regenerator Section layer transparency"));
2783         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
2784                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0002, 32,
2785                                                     "Line/Multiplex Section layer transparency",
2786                                                     "No Line/Multiplex Section layer transparency"));
2787         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
2788                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0004, 32,
2789                                                     "J0 transparency",
2790                                                     "No J0 transparency"));
2791         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
2792                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0008, 32,
2793                                                     "SOH/RSOH DCC transparency",
2794                                                     "No SOH/RSOH DCC transparency"));
2795         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
2796                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0010, 32,
2797                                                     "LOH/MSOH DCC transparency",
2798                                                     "No LOH/MSOH DCC transparency"));
2799         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
2800                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0020, 32,
2801                                                     "LOH/MSOH Extended DCC transparency",
2802                                                     "No LOH/MSOH Extended DCC transparency"));
2803         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
2804                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0040, 32,
2805                                                     "K1/K2 transparency",
2806                                                     "No K1/K2 transparency"));
2807         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
2808                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0080, 32,
2809                                                     "E1 transparency",
2810                                                     "No E1 transparency"));
2811         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
2812                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0100, 32,
2813                                                     "F1 transparency",
2814                                                     "No F1 transparency"));
2815         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
2816                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0200, 32,
2817                                                     "E2 transparency",
2818                                                     "No E2 transparency"));
2819         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
2820                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0400, 32,
2821                                                     "B1 transparency",
2822                                                     "No B1 transparency"));
2823         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
2824                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0800, 32,
2825                                                     "B2 transparency",
2826                                                     "No B2 transparency"));
2827         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
2828                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x1000, 32,
2829                                                     "M0 transparency",
2830                                                     "No M0 transparency"));
2831         proto_tree_add_text(tspec_tree, tvb, offset2+8, 4,
2832                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x2000, 32,
2833                                                     "M1 transparency",
2834                                                     "No M1 transparency"));
2835         proto_tree_add_text(rsvp_object_tree, tvb, offset2+12, 4,
2836                             "Profile (P): %d", tvb_get_ntohl(tvb, offset2+12));
2837
2838         proto_item_append_text(ti, "Signal [%s], RCC %d, NCC %d, NVC %d, MT %d, Transparency %d, Profile %d",
2839                                val_to_str(signal_type, gmpls_sonet_signal_type_str, "Unknown"),
2840                                tvb_get_guint8(tvb, offset2+1), tvb_get_ntohs(tvb, offset2+2),
2841                                tvb_get_ntohs(tvb, offset2+4), tvb_get_ntohs(tvb, offset2+6),
2842                                tvb_get_ntohl(tvb, offset2+8), tvb_get_ntohl(tvb, offset2+12));
2843         break;
2844
2845     case 6:   /* Ethernet TSPEC  draft-ietf-ccamp-ethernet-traffic-parameters-02 */
2846         proto_item_set_text(ti, "SENDER TSPEC: Ethernet: ");
2847         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2848                             "C-type: 6 - Ethernet");
2849         switch_gran = tvb_get_ntohs(tvb, offset2);
2850         if (switch_gran == 1)
2851           proto_tree_add_text(rsvp_object_tree, tvb, offset2, 2,
2852                               "Switching granularity: 1 - Ethernet port");
2853         else if (switch_gran == 2)
2854           proto_tree_add_text(rsvp_object_tree, tvb, offset2, 2,
2855                               "Switching granularity: 2 - Ethernet frame");
2856         else
2857           proto_tree_add_text(rsvp_object_tree, tvb, offset2, 2,
2858                               "Switching granularity: %u - ???", switch_gran);
2859
2860         proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
2861                             "MTU: %u", tvb_get_ntohs(tvb, offset2+2));
2862
2863         dissect_rsvp_eth_tspec_tlv(ti, rsvp_object_tree, tvb, offset+8, obj_length-8,
2864                                    TREE(TT_TSPEC_SUBTREE));
2865         break;
2866
2867     default: /* Unknown TSpec */
2868         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2869                             "C-type: Unknown (%u)",
2870                             type);
2871         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
2872                             "Data (%d bytes)", obj_length - 4);
2873         break;
2874
2875     }
2876 }
2877
2878 /*------------------------------------------------------------------------------
2879  * FLOWSPEC
2880  *------------------------------------------------------------------------------*/
2881 static void
2882 dissect_rsvp_flowspec (proto_item *ti, proto_tree *rsvp_object_tree,
2883                        tvbuff_t *tvb,
2884                        int offset, int obj_length,
2885                        int class _U_, int type)
2886 {
2887     int offset2 = offset + 4;
2888     int mylen, signal_type;
2889     proto_tree *flowspec_tree, *ti2;
2890     proto_item *item;
2891     guint16 switch_gran;
2892
2893     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
2894                         "C-type: %u", type);
2895     mylen = obj_length - 4;
2896
2897     switch(type) {
2898
2899     case 2:
2900         if (mylen < 4) {
2901             item = proto_tree_add_text(rsvp_object_tree, tvb, 0, 0,
2902                                        "Object length %u < 8", obj_length);
2903             PROTO_ITEM_SET_GENERATED(item);
2904             return;
2905         }
2906         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
2907                             "Message format version: %u",
2908                             tvb_get_guint8(tvb, offset2)>>4);
2909         proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
2910                             "Data length: %u words, not including header",
2911                             tvb_get_ntohs(tvb, offset2+2));
2912
2913         proto_item_set_text(ti, "FLOWSPEC: ");
2914
2915         mylen -= 4;
2916         offset2+= 4;
2917         while (mylen > 0) {
2918             guint8 service_num;
2919             guint length;
2920             guint8 param_id;
2921             guint param_len;
2922             guint param_len_processed;
2923
2924             if (mylen < 4) {
2925                 item = proto_tree_add_text(rsvp_object_tree, tvb, 0, 0,
2926                                            "Object length %u not large enough",
2927                                            obj_length);
2928                 PROTO_ITEM_SET_GENERATED(item);
2929                 return;
2930             }
2931             service_num = tvb_get_guint8(tvb, offset2);
2932             proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
2933                                 "Service header: %u - %s",
2934                                 service_num,
2935                                 val_to_str(service_num, intsrv_services_str, "Unknown"));
2936             length = tvb_get_ntohs(tvb, offset2+2);
2937             proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
2938                                 "Length of service %u data: %u words, "
2939                                 "not including header",
2940                                 service_num,
2941                                 length);
2942
2943             mylen -= 4;
2944             offset2 += 4;
2945
2946             proto_item_append_text(ti, "%s: ",
2947                                    val_to_str(service_num, intsrv_services_str,
2948                                               "Unknown (%d)"));
2949
2950             /* Process all known service headers as a set of parameters */
2951             param_len_processed = 0;
2952             while (param_len_processed < length) {
2953                 param_id = tvb_get_guint8(tvb, offset2);
2954                 param_len = tvb_get_ntohs(tvb, offset2+2) + 1;
2955                 if (param_len < 1)
2956                     THROW(ReportedBoundsError);
2957                 switch(param_id) {
2958                 case 127:
2959                     /* Token Bucket */
2960                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
2961                                               offset2, param_len*4,
2962                                               "Token Bucket: ");
2963                     flowspec_tree = proto_item_add_subtree(ti2, TREE(TT_FLOWSPEC_SUBTREE));
2964
2965                     proto_tree_add_text(flowspec_tree, tvb, offset2, 1,
2966                                         "Parameter %u - %s",
2967                                         param_id,
2968                                         val_to_str(param_id, svc_vals, "Unknown"));
2969                     proto_tree_add_text(flowspec_tree, tvb, offset2+1, 1,
2970                                         "Parameter %u flags: 0x%02x",
2971                                         param_id,
2972                                         tvb_get_guint8(tvb, offset2+1));
2973                     proto_tree_add_text(flowspec_tree, tvb, offset2+2, 2,
2974                                         "Parameter %u data length: %u words, "
2975                                         "not including header",
2976                                         param_id,
2977                                         tvb_get_ntohs(tvb, offset2+2));
2978                     proto_tree_add_text(flowspec_tree, tvb, offset2+4, 4,
2979                                         "Token bucket rate: %.10g",
2980                                         tvb_get_ntohieee_float(tvb, offset2+4));
2981                     proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
2982                                         "Token bucket size: %.10g",
2983                                         tvb_get_ntohieee_float(tvb, offset2+8));
2984                     proto_tree_add_text(flowspec_tree, tvb, offset2+12, 4,
2985                                         "Peak data rate: %.10g",
2986                                         tvb_get_ntohieee_float(tvb, offset2+12));
2987                     proto_tree_add_text(flowspec_tree, tvb, offset2+16, 4,
2988                                         "Minimum policed unit [m]: %u",
2989                                         tvb_get_ntohl(tvb, offset2+16));
2990                     proto_tree_add_text(flowspec_tree, tvb, offset2+20, 4,
2991                                         "Maximum packet size [M]: %u",
2992                                         tvb_get_ntohl(tvb, offset2+20));
2993                     proto_item_append_text(ti, "Token Bucket, %.10g bytes/sec. ",
2994                                            tvb_get_ntohieee_float(tvb, offset2+4));
2995                     proto_item_append_text(ti2, "Rate=%.10g Burst=%.10g Peak=%.10g m=%u M=%u",
2996                                            tvb_get_ntohieee_float(tvb, offset2+4),
2997                                            tvb_get_ntohieee_float(tvb, offset2+8),
2998                                            tvb_get_ntohieee_float(tvb, offset2+12),
2999                                            tvb_get_ntohl(tvb, offset2+16),
3000                                            tvb_get_ntohl(tvb, offset2+20));
3001                     break;
3002
3003                 case 130:
3004                     /* Guaranteed-rate RSpec */
3005                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3006                                               offset2, param_len*4,
3007                                               "Guaranteed-Rate RSpec: ");
3008                     flowspec_tree = proto_item_add_subtree(ti2, TREE(TT_FLOWSPEC_SUBTREE));
3009                     proto_tree_add_text(flowspec_tree, tvb, offset2, 1,
3010                                         "Parameter %u - %s",
3011                                         param_id,
3012                                         val_to_str(param_id, svc_vals, "Unknown"));
3013                     proto_tree_add_text(flowspec_tree, tvb, offset2+1, 1,
3014                                         "Parameter %u flags: %x",
3015                                         param_id,
3016                                         tvb_get_guint8(tvb, offset2+1));
3017                     proto_tree_add_text(flowspec_tree, tvb, offset2+2, 2,
3018                                         "Parameter %u data length: %u words, "
3019                                         "not including header",
3020                                         param_id,
3021                                         tvb_get_ntohs(tvb, offset2+2));
3022
3023                     proto_tree_add_text(flowspec_tree, tvb, offset2+4, 4,
3024                                         "Rate: %.10g",
3025                                         tvb_get_ntohieee_float(tvb, offset2+4));
3026                     proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
3027                                         "Slack term: %u",
3028                                         tvb_get_ntohl(tvb, offset2+8));
3029                     proto_item_append_text(ti, "RSpec, %.10g bytes/sec. ",
3030                                            tvb_get_ntohieee_float(tvb, offset2+4));
3031                     proto_item_append_text(ti2, "R=%.10g, s=%u",
3032                                            tvb_get_ntohieee_float(tvb, offset2+4),
3033                                            tvb_get_ntohl(tvb, offset2+8));
3034                     break;
3035
3036                 case 128:
3037                     /* Null Service (RFC2997) */
3038                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3039                                               offset2, param_len*4,
3040                                               "Null Service Flowspec: ");
3041                     flowspec_tree = proto_item_add_subtree(ti2, TREE(TT_FLOWSPEC_SUBTREE));
3042
3043                     proto_tree_add_text(flowspec_tree, tvb, offset2, 1,
3044                                         "Parameter %u - %s",
3045                                         param_id,
3046                                         val_to_str(param_id, svc_vals, "Unknown"));
3047                     proto_tree_add_text(flowspec_tree, tvb, offset2+1, 1,
3048                                         "Parameter %u flags: %x",
3049                                         param_id,
3050                                         tvb_get_guint8(tvb, offset2+1));
3051                     proto_tree_add_text(flowspec_tree, tvb, offset2+2, 2,
3052                                         "Parameter %u data length: %u words, "
3053                                         "not including header",
3054                                         param_id,
3055                                         tvb_get_ntohs(tvb, offset2+2));
3056                     proto_tree_add_text(flowspec_tree, tvb, offset2+4, 4,
3057                                         "Maximum packet size [M]: %u",
3058                                         tvb_get_ntohl(tvb, offset2+4));
3059                     proto_item_append_text(ti, "Null Service. M=%u",
3060                                            tvb_get_ntohl(tvb, offset2+4));
3061                     proto_item_append_text(ti2, "Max pkt size=%u",
3062                                            tvb_get_ntohl(tvb, offset2+4));
3063                     break;
3064
3065                 default:
3066                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, param_len*4,
3067                                         "Unknown parameter %d, %d words",
3068                                         param_id, param_len);
3069                     break;
3070                 }
3071                 param_len_processed += param_len;
3072                 offset2 += param_len * 4;
3073             }
3074
3075             /* offset2 += length*4; */
3076             mylen -= length*4;
3077         }
3078         break;
3079
3080     case 4:
3081         proto_item_set_text(ti, "FLOWSPEC: SONET/SDH: ");
3082
3083         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3084                             "C-type: 4 - SONET/SDH");
3085         signal_type = tvb_get_guint8(tvb, offset2);
3086         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
3087                             "Signal Type: %d - %s", signal_type,
3088                             val_to_str(signal_type,
3089                                        gmpls_sonet_signal_type_str, "Unknown"));
3090         ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2+1, 1,
3091                                   "Requested Concatenation (RCC): %d", tvb_get_guint8(tvb, offset2+1));
3092         flowspec_tree = proto_item_add_subtree(ti2, TREE(TT_FLOWSPEC_SUBTREE));
3093         proto_tree_add_text(flowspec_tree, tvb, offset2+1, 1,
3094                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+1), 0x01, 8,
3095                                                     "Standard contiguous concatenation",
3096                                                     "No standard contiguous concatenation"));
3097         proto_tree_add_text(flowspec_tree, tvb, offset2+1, 1,
3098                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+1), 0x02, 8,
3099                                                     "Arbitrary contiguous concatenation",
3100                                                     "No arbitrary contiguous concatenation"));
3101         proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
3102                             "Number of Contiguous Components (NCC): %d", tvb_get_ntohs(tvb, offset2+2));
3103         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 2,
3104                             "Number of Virtual Components (NVC): %d", tvb_get_ntohs(tvb, offset2+4));
3105         proto_tree_add_text(rsvp_object_tree, tvb, offset2+6, 2,
3106                             "Multiplier (MT): %d", tvb_get_ntohs(tvb, offset2+6));
3107         ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 4,
3108                                   "Transparency (T): 0x%0x", tvb_get_ntohl(tvb, offset2+8));
3109         flowspec_tree = proto_item_add_subtree(ti2, TREE(TT_FLOWSPEC_SUBTREE));
3110         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
3111                             decode_boolean_bitfield(tvb_get_ntohl(tvb, offset2+8), 0x0001, 32,
3112                                                     "Section/Regenerator Section layer transparency",
3113                                                     "No Section/Regenerator Section layer transparency"));
3114         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
3115                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0002, 32,
3116                                                     "Line/Multiplex Section layer transparency",
3117                                                     "No Line/Multiplex Section layer transparency"));
3118         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
3119                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0004, 32,
3120                                                     "J0 transparency",
3121                                                     "No J0 transparency"));
3122         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
3123                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0008, 32,
3124                                                     "SOH/RSOH DCC transparency",
3125                                                     "No SOH/RSOH DCC transparency"));
3126         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
3127                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0010, 32,
3128                                                     "LOH/MSOH DCC transparency",
3129                                                     "No LOH/MSOH DCC transparency"));
3130         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
3131                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0020, 32,
3132                                                     "LOH/MSOH Extended DCC transparency",
3133                                                     "No LOH/MSOH Extended DCC transparency"));
3134         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
3135                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0040, 32,
3136                                                     "K1/K2 transparency",
3137                                                     "No K1/K2 transparency"));
3138         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
3139                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0080, 32,
3140                                                     "E1 transparency",
3141                                                     "No E1 transparency"));
3142         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
3143                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0100, 32,
3144                                                     "F1 transparency",
3145                                                     "No F1 transparency"));
3146         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
3147                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0200, 32,
3148                                                     "E2 transparency",
3149                                                     "No E2 transparency"));
3150         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
3151                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0400, 32,
3152                                                     "B1 transparency",
3153                                                     "No B1 transparency"));
3154         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
3155                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x0800, 32,
3156                                                     "B2 transparency",
3157                                                     "No B2 transparency"));
3158         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
3159                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x1000, 32,
3160                                                     "M0 transparency",
3161                                                     "No M0 transparency"));
3162         proto_tree_add_text(flowspec_tree, tvb, offset2+8, 4,
3163                             decode_boolean_bitfield(tvb_get_guint8(tvb, offset2+8), 0x2000, 32,
3164                                                     "M1 transparency",
3165                                                     "No M1 transparency"));
3166         proto_tree_add_text(rsvp_object_tree, tvb, offset2+12, 4,
3167                             "Profile (P): %d", tvb_get_ntohl(tvb, offset2+12));
3168
3169         proto_item_append_text(ti, "Signal [%s], RCC %d, NCC %d, NVC %d, MT %d, Transparency %d, Profile %d",
3170                                val_to_str(signal_type, gmpls_sonet_signal_type_str, "Unknown"),
3171                                tvb_get_guint8(tvb, offset2+1), tvb_get_ntohs(tvb, offset2+2),
3172                                tvb_get_ntohs(tvb, offset2+4), tvb_get_ntohs(tvb, offset2+6),
3173                                tvb_get_ntohl(tvb, offset2+8), tvb_get_ntohl(tvb, offset2+12));
3174         break;
3175
3176     case 6:   /* Ethernet FLOWSPEC  draft-ietf-ccamp-ethernet-traffic-parameters-02 */
3177         proto_item_set_text(ti, "FLOWSPEC: Ethernet: ");
3178         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3179                             "C-type: 6 - Ethernet");
3180         switch_gran = tvb_get_ntohs(tvb, offset2);
3181         if (switch_gran == 1)
3182           proto_tree_add_text(rsvp_object_tree, tvb, offset2, 2,
3183                               "Switching granularity: 1 - Ethernet port");
3184         else if (switch_gran == 2)
3185           proto_tree_add_text(rsvp_object_tree, tvb, offset2, 2,
3186                               "Switching granularity: 2 - Ethernet frame");
3187         else
3188           proto_tree_add_text(rsvp_object_tree, tvb, offset2, 2,
3189                               "Switching granularity: %u - ???", switch_gran);
3190
3191         proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
3192                             "MTU: %u", tvb_get_ntohs(tvb, offset2+2));
3193
3194         dissect_rsvp_eth_tspec_tlv(ti, rsvp_object_tree, tvb, offset+8, obj_length-8,
3195                                    TREE(TT_FLOWSPEC_SUBTREE));
3196         break;
3197
3198     default:
3199         break;
3200     }
3201
3202
3203 }
3204
3205 /*------------------------------------------------------------------------------
3206  * ADSPEC
3207  *------------------------------------------------------------------------------*/
3208 static void
3209 dissect_rsvp_adspec (proto_item *ti, proto_tree *rsvp_object_tree,
3210                      tvbuff_t *tvb,
3211                      int offset, int obj_length,
3212                      int class _U_, int type)
3213 {
3214     int offset2 = offset + 4;
3215     int mylen, i;
3216     proto_tree *adspec_tree;
3217
3218     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3219                         "C-type: %u", type);
3220     mylen = obj_length - 4;
3221
3222     proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
3223                         "Message format version: %u",
3224                         tvb_get_guint8(tvb, offset2)>>4);
3225     proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
3226                         "Data length: %u words, not including header",
3227                         tvb_get_ntohs(tvb, offset2+2));
3228     mylen -= 4;
3229     offset2 += 4;
3230     while (mylen > 0) {
3231         guint8 service_num;
3232         guint8 break_bit;
3233         guint length;
3234         const char *str;
3235
3236         service_num = tvb_get_guint8(tvb, offset2);
3237         str = val_to_str(service_num, intsrv_services_str, "Unknown");
3238         break_bit = tvb_get_guint8(tvb, offset2+1);
3239         length = tvb_get_ntohs(tvb, offset2+2);
3240         ti = proto_tree_add_text(rsvp_object_tree, tvb, offset2,
3241                                  (length+1)*4,
3242                                  str);
3243         adspec_tree = proto_item_add_subtree(ti,
3244                                              TREE(TT_ADSPEC_SUBTREE));
3245         proto_tree_add_text(adspec_tree, tvb, offset2, 1,
3246                             "Service header %u - %s",
3247                             service_num, str);
3248         proto_tree_add_text(adspec_tree, tvb, offset2+1, 1,
3249                             (break_bit&0x80)?
3250                             "Break bit set":"Break bit not set");
3251         proto_tree_add_text(adspec_tree, tvb, offset2+2, 2,
3252                             "Data length: %u words, not including header",
3253                             length);
3254         mylen -= 4;
3255         offset2 += 4;
3256         i = length*4;
3257         while (i > 0) {
3258             guint8 id;
3259             guint phdr_length;
3260
3261             id = tvb_get_guint8(tvb, offset2);
3262             phdr_length = tvb_get_ntohs(tvb, offset2+2);
3263             str = match_strval(id, adspec_params);
3264             if (str) {
3265                 switch(id) {
3266                 case 4:
3267                 case 8:
3268                 case 10:
3269                 case 133:
3270                 case 134:
3271                 case 135:
3272                 case 136:
3273                     /* 32-bit unsigned integer */
3274                     proto_tree_add_text(adspec_tree, tvb, offset2,
3275                                         (phdr_length+1)<<2,
3276                                         "%s - %u (type %u, length %u)",
3277                                         str,
3278                                         tvb_get_ntohl(tvb, offset2+4),
3279                                         id, phdr_length);
3280                     break;
3281
3282                 case 6:
3283                     /* IEEE float */
3284                     proto_tree_add_text(adspec_tree, tvb, offset2,
3285                                         (phdr_length+1)<<2,
3286                                         "%s - %.10g (type %u, length %u)",
3287                                         str,
3288                                         tvb_get_ntohieee_float(tvb, offset2+4),
3289                                         id, phdr_length);
3290                     break;
3291                 default:
3292                     proto_tree_add_text(adspec_tree, tvb, offset2,
3293                                         (phdr_length+1)<<2,
3294                                         "%s (type %u, length %u)",
3295                                         str,
3296                                         id, phdr_length);
3297                 }
3298             } else {
3299                 proto_tree_add_text(adspec_tree, tvb, offset2,
3300                                     (phdr_length+1)<<2,
3301                                     "Unknown (type %u, length %u)",
3302                                     id, phdr_length);
3303             }
3304             offset2 += (phdr_length+1)<<2;
3305             i -= (phdr_length+1)<<2;
3306             mylen -= (phdr_length+1)<<2;
3307         }
3308     }
3309 }
3310
3311 /*------------------------------------------------------------------------------
3312  * INTEGRITY
3313  *------------------------------------------------------------------------------*/
3314 static void
3315 dissect_rsvp_integrity (proto_item *ti _U_, proto_tree *rsvp_object_tree,
3316                         tvbuff_t *tvb,
3317                         int offset, int obj_length,
3318                         int class _U_, int type)
3319 {
3320     int offset2 = offset + 4;
3321     proto_tree *ti2, *rsvp_integ_flags_tree;
3322     int flags;
3323
3324     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3325                         "C-type: %u", type);
3326     flags = tvb_get_guint8(tvb, offset2);
3327     ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
3328                               "Flags: 0x%02x", flags);
3329     rsvp_integ_flags_tree = proto_item_add_subtree(ti2, TREE(TT_INTEGRITY_FLAGS));
3330     proto_tree_add_text(rsvp_integ_flags_tree, tvb, offset2, 1,
3331         decode_boolean_bitfield(flags, 0x01, 8, "Handshake capable", "Handshake not capable"));
3332     proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 6,
3333                         "Key Identifier: %s", tvb_bytes_to_str(tvb, offset2+2, 6));
3334     proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 8,
3335                         "Sequence Number: %" G_GINT64_MODIFIER "u", tvb_get_ntoh64(tvb, offset2+8));
3336     proto_tree_add_text(rsvp_object_tree, tvb, offset2+16, obj_length - 20,
3337                         "Hash: %s", tvb_bytes_to_str(tvb, offset2+16, obj_length - 20));
3338 }
3339
3340 /*------------------------------------------------------------------------------
3341  * POLICY
3342  *------------------------------------------------------------------------------*/
3343 static void
3344 dissect_rsvp_policy (proto_item *ti _U_, proto_tree *rsvp_object_tree,
3345                      tvbuff_t *tvb,
3346                      int offset, int obj_length,
3347                      int class _U_, int type)
3348 {
3349     int offset2 = offset + 4;
3350
3351     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3352                         "C-type: %u", type);
3353     proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
3354                         "Data (%d bytes)", obj_length - 4);
3355 }
3356
3357 /*------------------------------------------------------------------------------
3358  * LABEL_REQUEST
3359  *------------------------------------------------------------------------------*/
3360 static void
3361 dissect_rsvp_label_request (proto_item *ti, proto_tree *rsvp_object_tree,
3362                             tvbuff_t *tvb,
3363                             int offset, int obj_length,
3364                             int class _U_, int type)
3365 {
3366     int offset2 = offset + 4;
3367
3368     switch(type) {
3369     case 1: {
3370         unsigned short l3pid = tvb_get_ntohs(tvb, offset2+2);
3371         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3372                             "C-type: 1");
3373         proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
3374                             "L3PID: %s (0x%04x)",
3375                             val_to_str(l3pid, etype_vals, "Unknown"),
3376                             l3pid);
3377         proto_item_set_text(ti, "LABEL REQUEST: Basic: L3PID: %s (0x%04x)",
3378                             val_to_str(l3pid, etype_vals, "Unknown"),
3379                             l3pid);
3380         break;
3381     }
3382
3383     case 2: {
3384         unsigned short l3pid = tvb_get_ntohs(tvb, offset2+2);
3385         unsigned short min_vpi, min_vci, max_vpi, max_vci;
3386         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3387                             "C-type: 2 (Label Request with ATM label Range)");
3388         proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
3389                             "L3PID: %s (0x%04x)",
3390                             val_to_str(l3pid, etype_vals, "Unknown"),
3391                             l3pid);
3392         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 1,
3393                             "M: %s Merge in Data Plane",
3394                             (tvb_get_guint8(tvb, offset2+4) & 0x80) ?
3395                             "1: Can" : "0: Cannot");
3396         min_vpi = tvb_get_ntohs(tvb, offset2+4) & 0x7f;
3397         min_vci = tvb_get_ntohs(tvb, offset2+6);
3398         max_vpi = tvb_get_ntohs(tvb, offset2+8) & 0x7f;
3399         max_vci = tvb_get_ntohs(tvb, offset2+10);
3400         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 2,
3401                             "Min VPI: %d", min_vpi);
3402         proto_tree_add_text(rsvp_object_tree, tvb, offset2+6, 2,
3403                             "Min VCI: %d", min_vci);
3404         proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 2,
3405                             "Max VPI: %d", max_vpi);
3406         proto_tree_add_text(rsvp_object_tree, tvb, offset2+10, 2,
3407                             "Max VCI: %d", max_vci);
3408         proto_item_set_text(ti, "LABEL REQUEST: ATM: L3PID: %s (0x%04x). VPI/VCI: Min: %d/%d, Max: %d/%d. %s Merge. ",
3409                             val_to_str(l3pid, etype_vals, "Unknown"), l3pid,
3410                             min_vpi, min_vci, max_vpi, max_vci,
3411                             (tvb_get_guint8(tvb, offset2+4) & 0x80) ? "Can" : "Cannot");
3412         break;
3413     }
3414
3415     case 3: {
3416         guint16 l3pid = tvb_get_ntohs(tvb, offset2+2);
3417         guint32 min_dlci, max_dlci, dlci_len, dlci_len_code;
3418         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3419                             "C-type: 2 (Label Request with ATM label Range)");
3420         proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
3421                             "L3PID: %s (0x%04x)",
3422                             val_to_str(l3pid, etype_vals, "Unknown"),
3423                             l3pid);
3424         dlci_len_code = (tvb_get_ntohs(tvb, offset2+4) & 0x0180) >> 7;
3425         min_dlci = tvb_get_ntohl(tvb, offset2+4) & 0x7fffff;
3426         max_dlci = tvb_get_ntohl(tvb, offset2+8) & 0x7fffff;
3427         switch(dlci_len_code) {
3428         case 0:
3429             /* 10-bit DLCIs */
3430             dlci_len = 10;
3431             min_dlci &= 0x3ff;
3432             max_dlci &= 0x3ff;
3433         case 2:
3434             dlci_len = 23;
3435         default:
3436             dlci_len = 0;
3437             min_dlci = 0;
3438             max_dlci = 0;
3439         }
3440         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 2,
3441                             "DLCI Length: %s (%d)",
3442                             dlci_len==10 ? "10 bits" :
3443                             dlci_len==23 ? "23 bits" :
3444                             "INVALID", dlci_len_code);
3445         proto_tree_add_text(rsvp_object_tree, tvb, offset2+5, 3,
3446                             "Min DLCI: %d", min_dlci);
3447         proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 2,
3448                             "Max DLCI: %d", max_dlci);
3449         proto_item_set_text(ti, "LABEL REQUEST: Frame: L3PID: %s (0x%04x). DLCI Len: %s. Min DLCI: %d. Max DLCI: %d",
3450                             val_to_str(l3pid, etype_vals, "Unknown"), l3pid,
3451                             dlci_len==10 ? "10 bits" :
3452                             dlci_len==23 ? "23 bits" :
3453                             "INVALID", min_dlci, max_dlci);
3454         break;
3455     }
3456     case 4: {
3457         unsigned short l3pid = tvb_get_ntohs(tvb, offset2+2);
3458         unsigned char  lsp_enc = tvb_get_guint8(tvb,offset2);
3459         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3460                             "C-type: 4 (Generalized Label Request)");
3461         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
3462                             "LSP Encoding Type: %s",
3463                             val_to_str(lsp_enc, gmpls_lsp_enc_str, "Unknown (%d)"));
3464         proto_tree_add_text(rsvp_object_tree, tvb, offset2+1, 1,
3465                             "Switching Type: %s",
3466                             val_to_str(tvb_get_guint8(tvb,offset2+1),
3467                                        gmpls_switching_type_str, "Unknown (%d)"));
3468         proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
3469                             "G-PID: %s (0x%0x)",
3470                             val_to_str(l3pid, gmpls_gpid_str,
3471                                        val_to_str(l3pid, etype_vals,
3472                                                   "Unknown G-PID(0x%04x)")),
3473                             l3pid);
3474         proto_item_set_text(ti, "LABEL REQUEST: Generalized: LSP Encoding=%s, "
3475                             "Switching Type=%s, G-PID=%s ",
3476                             val_to_str(lsp_enc, gmpls_lsp_enc_str, "Unknown (%d)"),
3477                             val_to_str(tvb_get_guint8(tvb,offset2+1),
3478                                        gmpls_switching_type_str, "Unknown (%d)"),
3479                             val_to_str(l3pid, gmpls_gpid_str,
3480                                        val_to_str(l3pid, etype_vals,
3481                                                   "Unknown (0x%04x)")));
3482         break;
3483     }
3484
3485     default: {
3486         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3487                             "C-type: Unknown (%u)",
3488                             type);
3489         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
3490                             "Data (%d bytes)", obj_length - 4);
3491         break;
3492     }
3493     }
3494 }
3495
3496 /*------------------------------------------------------------------------------
3497  * LABEL
3498  *------------------------------------------------------------------------------*/
3499 static void
3500 dissect_rsvp_label (proto_tree *ti, proto_tree *rsvp_object_tree,
3501                     tvbuff_t *tvb,
3502                     int offset, int obj_length,
3503                     int class, int type)
3504 {
3505     int offset2 = offset + 4;
3506     int mylen, i;
3507     const char *name;
3508
3509     name = (class==RSVP_CLASS_SUGGESTED_LABEL ? "SUGGESTED LABEL":
3510             (class==RSVP_CLASS_UPSTREAM_LABEL ? "UPSTREAM LABEL":
3511              (class==RSVP_CLASS_RECOVERY_LABEL ? "RECOVERY LABEL":
3512              "LABEL")));
3513     mylen = obj_length - 4;
3514     switch(type) {
3515     case 1:
3516         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3517                             "C-type: 1 (Packet Label)");
3518         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
3519                             "Label: %u",
3520                             tvb_get_ntohl(tvb, offset2));
3521         proto_item_set_text(ti, "%s: %u", name,
3522                             tvb_get_ntohl(tvb, offset2));
3523         break;
3524
3525     case 2:
3526         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3527                             "C-type: 2 (Generalized Label)");
3528         proto_item_set_text(ti, "%s: Generalized: ", name);
3529         for (i = 0; i < mylen; i += 4) {
3530             proto_tree_add_text(rsvp_object_tree, tvb, offset2+i, 4,
3531                                 "Generalized Label: %u (0x%x)",
3532                                 tvb_get_ntohl(tvb, offset2+i),
3533                                 tvb_get_ntohl(tvb, offset2+i));
3534             if (i < 16) {
3535                 proto_item_append_text(ti, "0x%x%s",
3536                                        tvb_get_ntohl(tvb, offset2+i),
3537                                        i+4<mylen?", ":"");
3538             } else if (i == 16) {
3539                 proto_item_append_text(ti, "...");
3540             }
3541         }
3542         break;
3543
3544     default:
3545         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3546                             "C-type: Unknown (%u)",
3547                             type);
3548         proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
3549                             "Data (%d bytes)", mylen);
3550         break;
3551     }
3552 }
3553
3554 /*------------------------------------------------------------------------------
3555  * LABEL_SET
3556  *------------------------------------------------------------------------------*/
3557 static void
3558 dissect_rsvp_label_set (proto_item *ti, proto_tree *rsvp_object_tree,
3559                         tvbuff_t *tvb,
3560                         int offset, int obj_length,
3561                         int class _U_, int type)
3562 {
3563     int offset2 = offset + 8;
3564     guint8 label_type;
3565     int len, i;
3566
3567     static const value_string action_type_vals[] = {
3568       {0, "Inclusive list"},
3569       {1, "Exclusive list"},
3570       {2, "Inclusive range"},
3571       {3, "Exclusive range"},
3572       {0, NULL}
3573    };
3574
3575     len = obj_length - 8;
3576     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, "C-type: %u", type);
3577     proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1, "Action: %s",
3578                         val_to_str(tvb_get_guint8(tvb, offset+4),
3579                         action_type_vals, "Unknown (%u)"));
3580     proto_item_append_text(ti, ": %s",
3581                            val_to_str(tvb_get_guint8(tvb, offset+4),
3582                            action_type_vals, "Unknown (%u)"));
3583     label_type = tvb_get_guint8 (tvb, offset+7);
3584     proto_tree_add_text(rsvp_object_tree, tvb, offset+7, 1, "Label type: %s",
3585                         label_type==1 ? "Packet Label" : "Generalized Label");
3586     proto_item_append_text(ti, ", %s",
3587                         label_type==1 ? "Packet Label: " : "Generalized Label: ");
3588
3589     for (i = 0; i < len/4; i++) {
3590         proto_tree_add_text(rsvp_object_tree, tvb, offset2+i*4, 4,
3591                             "Subchannel %u: %u (0x%x)", i+1,
3592                             tvb_get_ntohl(tvb, offset2+i*4),
3593                             tvb_get_ntohl(tvb, offset2+i*4));
3594
3595         if (i<5) {
3596                 if (i!=0)
3597                   proto_item_append_text(ti, ", ");
3598
3599                 proto_item_append_text(ti, "%u",
3600                                         tvb_get_ntohl(tvb, offset2+i*4));
3601         }
3602     }
3603 }
3604
3605 /*------------------------------------------------------------------------------
3606  * SESSION ATTRIBUTE
3607  *------------------------------------------------------------------------------*/
3608 static void
3609 dissect_rsvp_session_attribute (proto_item *ti, proto_tree *rsvp_object_tree,
3610                                 tvbuff_t *tvb,
3611                                 int offset, int obj_length,
3612                                 int class _U_, int type)
3613 {
3614     int offset2 = offset + 4;
3615     guint8 flags;
3616     guint8 name_len;
3617     proto_tree *ti2, *rsvp_sa_flags_tree;
3618
3619     switch(type) {
3620     case 1:
3621     case 7:
3622
3623         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3624                             "C-type: %u - IPv4 LSP (%sResource Affinities)",
3625                             type, (type == 1) ? "" : "No ");
3626
3627         if (type == 1) {
3628             proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
3629                             "Exclude-Any: 0x%0x", tvb_get_ntohl(tvb, offset2));
3630             proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
3631                             "Include-Any: 0x%0x", tvb_get_ntohl(tvb, offset2+4));
3632             proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 4,
3633                             "Include-All: 0x%0x", tvb_get_ntohl(tvb, offset2+8));
3634             offset2 = offset2+12;
3635         }
3636
3637         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
3638                             "Setup priority: %u",
3639                             tvb_get_guint8(tvb, offset2));
3640         proto_tree_add_text(rsvp_object_tree, tvb, offset2+1, 1,
3641                             "Hold priority: %u",
3642                             tvb_get_guint8(tvb, offset2+1));
3643         flags = tvb_get_guint8(tvb, offset2+2);
3644         ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 1,
3645                                   "Flags: 0x%02x", flags);
3646         rsvp_sa_flags_tree = proto_item_add_subtree(ti2,
3647                                                     TREE(TT_SESSION_ATTRIBUTE_FLAGS));
3648         proto_tree_add_text(rsvp_sa_flags_tree, tvb, offset2+2, 1,
3649                             decode_boolean_bitfield(flags, 0x01, 8,
3650                                                     "Local protection desired",
3651                                                     "Local protection not desired"));
3652         proto_tree_add_text(rsvp_sa_flags_tree, tvb, offset2+2, 1,
3653                             decode_boolean_bitfield(flags, 0x02, 8,
3654                                                     "Label recording desired",
3655                                                     "Label recording not desired"));
3656         proto_tree_add_text(rsvp_sa_flags_tree, tvb, offset2+2, 1,
3657                             decode_boolean_bitfield(flags, 0x04, 8,
3658                                                     "SE style desired",
3659                                                     "SE style not desired"));
3660         proto_tree_add_text(rsvp_sa_flags_tree, tvb, offset2+2, 1,
3661                             decode_boolean_bitfield(flags, 0x08, 8,
3662                                                     "Bandwidth protection desired",
3663                                                     "Bandwidth protection not desired"));
3664         proto_tree_add_text(rsvp_sa_flags_tree, tvb, offset2+2, 1,
3665                             decode_boolean_bitfield(flags, 0x10, 8,
3666                                                     "Node protection desired",
3667                                                     "Node protection not desired"));
3668
3669         name_len = tvb_get_guint8(tvb, offset2+3);
3670         proto_tree_add_text(rsvp_object_tree, tvb, offset2+3, 1,
3671                             "Name length: %u", name_len);
3672         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, name_len,
3673                             "Name: %s",
3674                             tvb_format_text(tvb, offset2+4, name_len));
3675
3676         proto_item_set_text(ti, "SESSION ATTRIBUTE: SetupPrio %d, HoldPrio %d, %s%s%s%s%s [%s]",
3677                             tvb_get_guint8(tvb, offset2),
3678                             tvb_get_guint8(tvb, offset2+1),
3679                             flags &0x01 ? "Local Protection, " : "",
3680                             flags &0x02 ? "Label Recording, " : "",
3681                             flags &0x04 ? "SE Style, " : "",
3682                             flags &0x08 ? "Bandwidth Protection, " : "",
3683                             flags &0x10 ? "Node Protection, " : "",
3684                             name_len ? tvb_format_text(tvb, offset2+4, name_len) : "");
3685         break;
3686
3687     default:
3688         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
3689                             "C-type: Unknown (%u)",
3690                             type);
3691         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
3692                             "Data (%d bytes)", obj_length - 4);
3693         break;
3694     }
3695 }
3696
3697 /*------------------------------------------------------------------------------
3698  * EXPLICIT ROUTE AND RECORD ROUTE SUBOBJECTS
3699  *------------------------------------------------------------------------------*/
3700 static void
3701 dissect_rsvp_ero_rro_subobjects (proto_tree *ti, proto_tree *rsvp_object_tree,
3702                                  tvbuff_t *tvb,
3703                                  int offset, int obj_length, int class)
3704 {
3705     int i, j, k, l, flags;
3706     proto_tree *ti2, *rsvp_ro_subtree, *rsvp_rro_flags_subtree;
3707     int tree_type;
3708
3709     switch(class) {
3710     case RSVP_CLASS_EXPLICIT_ROUTE:
3711         tree_type = TREE(TT_EXPLICIT_ROUTE_SUBOBJ);
3712         break;
3713     case RSVP_CLASS_RECORD_ROUTE:
3714         tree_type = TREE(TT_RECORD_ROUTE_SUBOBJ);
3715         break;
3716     default:
3717         /* Bail out */
3718         return;
3719     }
3720
3721     for (i=1, l = 0; l < obj_length - 4; i++) {
3722         j = tvb_get_guint8(tvb, offset+l) & 0x7f;
3723         switch(j) {
3724         case 1: /* IPv4 */
3725             k = tvb_get_guint8(tvb, offset+l) & 0x80;
3726             ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3727                                       offset+l, 8,
3728                                       "IPv4 Subobject - %s%s",
3729                                       ip_to_str(tvb_get_ptr(tvb, offset+l+2, 4)),
3730                                       class == RSVP_CLASS_EXPLICIT_ROUTE ?
3731                                       (k ? ", Loose" : ", Strict") : "");
3732             rsvp_ro_subtree =
3733                 proto_item_add_subtree(ti2, tree_type);
3734             if (class == RSVP_CLASS_EXPLICIT_ROUTE)
3735                 proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3736                                     k ? "Loose Hop " : "Strict Hop");
3737             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3738                                 "Type: 1 (IPv4)");
3739             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
3740                                 "Length: %u",
3741                                 tvb_get_guint8(tvb, offset+l+1));
3742             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+2, 4,
3743                                 "IPv4 hop: %s",
3744                                 ip_to_str(tvb_get_ptr(tvb, offset+l+2, 4)));
3745             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+6, 1,
3746                                 "Prefix length: %u",
3747                                 tvb_get_guint8(tvb, offset+l+6));
3748             if (i < 4) {
3749                 proto_item_append_text(ti, "IPv4 %s%s",
3750                                        ip_to_str(tvb_get_ptr(tvb, offset+l+2, 4)),
3751                                        k ? " [L]" : "");
3752             }
3753             if (class == RSVP_CLASS_RECORD_ROUTE) {
3754                 flags = tvb_get_guint8(tvb, offset+l+7);
3755                 if (flags&0x10) {
3756                     proto_item_append_text(ti,  " (Node-id)");
3757                     proto_item_append_text(ti2, " (Node-id)");
3758                 }
3759                 if (flags&0x01) proto_item_append_text(ti2, ", Local Protection Available");
3760                 if (flags&0x02) proto_item_append_text(ti2, ", Local Protection In Use");
3761                 if (flags&0x04) proto_item_append_text(ti2, ", Backup BW Avail");
3762                 if (flags&0x08) proto_item_append_text(ti2, ", Backup is Next-Next-Hop");
3763                 ti2 = proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+7, 1,
3764                                           "Flags: 0x%02x", flags);
3765                 rsvp_rro_flags_subtree =
3766                     proto_item_add_subtree(ti2, TREE(TT_RECORD_ROUTE_SUBOBJ_FLAGS));
3767                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
3768                                     decode_boolean_bitfield(flags, 0x01, 8,
3769                                                             "Local Protection Available",
3770                                                             "Local Protection Not Available"));
3771                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
3772                                     decode_boolean_bitfield(flags, 0x02, 8,
3773                                                             "Local Protection In Use",
3774                                                             "Local Protection Not In Use"));
3775                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
3776                                     decode_boolean_bitfield(flags, 0x04, 8,
3777                                                             "Bandwidth Protection Available",
3778                                                             "Bandwidth Protection Not Available"));
3779                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
3780                                     decode_boolean_bitfield(flags, 0x08, 8,
3781                                                             "Node Protection Available",
3782                                                             "Node Protection Not Available"));
3783                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+7, 1,
3784                                     decode_boolean_bitfield(flags, 0x10, 8,
3785                                                             "Address Specifies a Node-id Address",
3786                                                             "Address Doesn't Specify a Node-id Address"));
3787             }
3788
3789             break;
3790
3791         case 2: /* IPv6 */
3792             ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3793                                       offset+l, 20,
3794                                       "IPv6 Subobject");
3795             rsvp_ro_subtree =
3796                 proto_item_add_subtree(ti2, tree_type);
3797             k = tvb_get_guint8(tvb, offset+l) & 0x80;
3798             if (class == RSVP_CLASS_EXPLICIT_ROUTE)
3799                 proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3800                                     k ? "Loose Hop " : "Strict Hop");
3801             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3802                                 "Type: 2 (IPv6)");
3803             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
3804                                 "Length: %u",
3805                                 tvb_get_guint8(tvb, offset+l+1));
3806             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+2, 16,
3807                                 "IPv6 hop: %s",
3808                                 ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset+l+2, 16)));
3809             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+18, 1,
3810                                 "Prefix length: %u",
3811                                 tvb_get_guint8(tvb, offset+l+18));
3812             if (i < 4) {
3813                 proto_item_append_text(ti, "IPv6 [...]%s", k ? " [L]":"");
3814             }
3815             if (class == RSVP_CLASS_RECORD_ROUTE) {
3816                 flags = tvb_get_guint8(tvb, offset+l+19);
3817                 if (flags&0x10) {
3818                     proto_item_append_text(ti,  " (Node-id)");
3819                     proto_item_append_text(ti2, " (Node-id)");
3820                 }
3821                 if (flags&0x01) proto_item_append_text(ti2, ", Local Protection Available");
3822                 if (flags&0x02) proto_item_append_text(ti2, ", Local Protection In Use");
3823                 if (flags&0x04) proto_item_append_text(ti2, ", Backup BW Avail");
3824                 if (flags&0x08) proto_item_append_text(ti2, ", Backup is Next-Next-Hop");
3825                 ti2 = proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+19, 1,
3826                                           "Flags: 0x%02x", flags);
3827                 rsvp_rro_flags_subtree =
3828                     proto_item_add_subtree(ti2, TREE(TT_RECORD_ROUTE_SUBOBJ_FLAGS));
3829                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
3830                                     decode_boolean_bitfield(flags, 0x01, 8,
3831                                                             "Local Protection Available",
3832                                                             "Local Protection Not Available"));
3833                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
3834                                     decode_boolean_bitfield(flags, 0x02, 8,
3835                                                             "Local Protection In Use",
3836                                                             "Local Protection Not In Use"));
3837                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
3838                                     decode_boolean_bitfield(flags, 0x04, 8,
3839                                                             "Backup Tunnel Has Bandwidth",
3840                                                             "Backup Tunnel Does Not Have Bandwidth"));
3841                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
3842                                     decode_boolean_bitfield(flags, 0x08, 8,
3843                                                             "Backup Tunnel Goes To Next-Next-Hop",
3844                                                             "Backup Tunnel Goes To Next-Hop"));
3845                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+19, 1,
3846                                     decode_boolean_bitfield(flags, 0x10, 8,
3847                                                             "Address Specifies a Node-id Address",
3848                                                             "Address Doesn't Specify a Node-id Address"));
3849             }
3850
3851             break;
3852
3853         case 3: /* Label */
3854             k = tvb_get_guint8(tvb, offset+l) & 0x80;
3855             ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3856                                       offset+l, 8,
3857                                       "Label Subobject - %d, %s",
3858                                       tvb_get_ntohl(tvb, offset+l+4),
3859                                       class == RSVP_CLASS_EXPLICIT_ROUTE ?
3860                                       (k ? "Loose" : "Strict") : "");
3861             rsvp_ro_subtree =
3862                 proto_item_add_subtree(ti2, tree_type);
3863             if (class == RSVP_CLASS_EXPLICIT_ROUTE)
3864                 proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3865                                     k ? "Loose Hop " : "Strict Hop");
3866             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3867                                 "Type: 3 (Label)");
3868             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
3869                                 "Length: %u",
3870                                 tvb_get_guint8(tvb, offset+l+1));
3871             if (class == RSVP_CLASS_RECORD_ROUTE) {
3872                 flags = tvb_get_guint8(tvb, offset+l+2);
3873                 if (flags&0x01) proto_item_append_text(ti2, ", Local Protection Available");
3874                 if (flags&0x02) proto_item_append_text(ti2, ", Local Protection In Use");
3875                 if (flags&0x04) proto_item_append_text(ti2, ", Backup BW Avail");
3876                 if (flags&0x08) proto_item_append_text(ti2, ", Backup is Next-Next-Hop");
3877                 ti2 = proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+2, 1,
3878                                           "Flags: 0x%02x", flags);
3879                 rsvp_rro_flags_subtree =
3880                     proto_item_add_subtree(ti2, TREE(TT_RECORD_ROUTE_SUBOBJ_FLAGS));
3881                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
3882                                     decode_boolean_bitfield(flags, 0x01, 8,
3883                                                             "Local Protection Available",
3884                                                             "Local Protection Not Available"));
3885                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
3886                                     decode_boolean_bitfield(flags, 0x02, 8,
3887                                                             "Local Protection In Use",
3888                                                             "Local Protection Not In Use"));
3889                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
3890                                     decode_boolean_bitfield(flags, 0x04, 8,
3891                                                             "Backup Tunnel Has Bandwidth",
3892                                                             "Backup Tunnel Does Not Have Bandwidth"));
3893                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
3894                                     decode_boolean_bitfield(flags, 0x08, 8,
3895                                                             "Backup Tunnel Goes To Next-Next-Hop",
3896                                                             "Backup Tunnel Goes To Next-Hop"));
3897             }
3898             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+3, 1,
3899                                 "C-Type: %u",
3900                                 tvb_get_guint8(tvb, offset+l+3));
3901             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+4, 4,
3902                                 "Label: %d",
3903                                 tvb_get_ntohl(tvb, offset+l+4));
3904             if (i < 4) {
3905                 proto_item_append_text(ti, "Label %d%s",
3906                                        tvb_get_ntohl(tvb, offset+l+4),
3907                                        k ? " [L]":"");
3908             }
3909             break;
3910
3911         case 4: /* Unnumbered Interface-ID */
3912             k = tvb_get_guint8(tvb, offset+l) & 0x80;
3913             ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3914                                       offset+l, 8,
3915                                       "Unnumbered Interface-ID - %s, %d, %s",
3916                                       ip_to_str(tvb_get_ptr(tvb, offset+l+4, 4)),
3917                                       tvb_get_ntohl(tvb, offset+l+8),
3918                                       class == RSVP_CLASS_EXPLICIT_ROUTE ?
3919                                       (k ? "Loose" : "Strict") : "");
3920             rsvp_ro_subtree =
3921                 proto_item_add_subtree(ti2, tree_type);
3922             if (class == RSVP_CLASS_EXPLICIT_ROUTE)
3923                 proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3924                                     k ? "Loose Hop " : "Strict Hop");
3925             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3926                                 "Type: 4 (Unnumbered Interface-ID)");
3927             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
3928                                 "Length: %u",
3929                                 tvb_get_guint8(tvb, offset+l+1));
3930             if (class == RSVP_CLASS_RECORD_ROUTE) {
3931                 flags = tvb_get_guint8(tvb, offset+l+2);
3932                 if (flags&0x01) proto_item_append_text(ti2, ", Local Protection Available");
3933                 if (flags&0x02) proto_item_append_text(ti2, ", Local Protection In Use");
3934                 if (flags&0x04) proto_item_append_text(ti2, ", Backup BW Avail");
3935                 if (flags&0x08) proto_item_append_text(ti2, ", Backup is Next-Next-Hop");
3936                 ti2 = proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+2, 1,
3937                                           "Flags: 0x%02x", flags);
3938                 rsvp_rro_flags_subtree =
3939                     proto_item_add_subtree(ti2, TREE(TT_RECORD_ROUTE_SUBOBJ_FLAGS));
3940                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
3941                                     decode_boolean_bitfield(flags, 0x01, 8,
3942                                                             "Local Protection Available",
3943                                                             "Local Protection Not Available"));
3944                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
3945                                     decode_boolean_bitfield(flags, 0x02, 8,
3946                                                             "Local Protection In Use",
3947                                                             "Local Protection Not In Use"));
3948                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
3949                                     decode_boolean_bitfield(flags, 0x04, 8,
3950                                                             "Backup Tunnel Has Bandwidth",
3951                                                             "Backup Tunnel Does Not Have Bandwidth"));
3952                 proto_tree_add_text(rsvp_rro_flags_subtree, tvb, offset+l+2, 1,
3953                                     decode_boolean_bitfield(flags, 0x08, 8,
3954                                                             "Backup Tunnel Goes To Next-Next-Hop",
3955                                                             "Backup Tunnel Goes To Next-Hop"));
3956             }
3957             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+4, 4,
3958                                 "Router-ID: %s",
3959                                 ip_to_str(tvb_get_ptr(tvb, offset+l+4, 4)));
3960             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+8, 4,
3961                                 "Interface-ID: %d",
3962                                 tvb_get_ntohl(tvb, offset+l+8));
3963             if (i < 4) {
3964                 proto_item_append_text(ti, "Unnum %s/%d%s",
3965                                        ip_to_str(tvb_get_ptr(tvb, offset+l+4, 4)),
3966                                        tvb_get_ntohl(tvb, offset+l+8),
3967                                        k ? " [L]":"");
3968             }
3969
3970             break;
3971
3972         case 32: /* AS */
3973             if (class == RSVP_CLASS_RECORD_ROUTE) goto defaultsub;
3974             k = tvb_get_ntohs(tvb, offset+l+2);
3975             ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3976                                       offset+l, 4,
3977                                       "Autonomous System %u",
3978                                       k);
3979             rsvp_ro_subtree =
3980                 proto_item_add_subtree(ti2, tree_type);
3981             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
3982                                 "Type: 32 (Autonomous System Number)");
3983             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
3984                                 "Length: %u",
3985                                 tvb_get_guint8(tvb, offset+l+1));
3986             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+2, 2,
3987                                 "Autonomous System %u", k);
3988             if (i < 4) {
3989                 proto_item_append_text(ti, "AS %d",
3990                                        tvb_get_ntohs(tvb, offset+l+2));
3991             }
3992
3993             break;
3994
3995         default: /* Unknown subobject */
3996         defaultsub:
3997             k = tvb_get_guint8(tvb, offset+l) & 0x80;
3998             ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
3999                                       offset+l,
4000                                       tvb_get_guint8(tvb, offset+l+1),
4001                                       "Unknown subobject: %d", j);
4002             rsvp_ro_subtree =
4003                 proto_item_add_subtree(ti2, tree_type);
4004             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
4005                                 k ? "Loose Hop " : "Strict Hop");
4006             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l, 1,
4007                                 "Type: %u (Unknown)", j);
4008             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
4009                                 "Length: %u",
4010                                 tvb_get_guint8(tvb, offset+l+1));
4011
4012         }
4013
4014         if (tvb_get_guint8(tvb, offset+l+1) < 1) {
4015             proto_tree_add_text(rsvp_ro_subtree, tvb, offset+l+1, 1,
4016                 "Invalid length: %u", tvb_get_guint8(tvb, offset+l+1));
4017             return;
4018         }
4019         l += tvb_get_guint8(tvb, offset+l+1);
4020         if (l < obj_length - 4) {
4021             if (i < 4)
4022                 proto_item_append_text(ti, ", ");
4023             else if (i==4)
4024                 proto_item_append_text(ti, "...");
4025         }
4026     }
4027 }
4028
4029 /*------------------------------------------------------------------------------
4030  * EXPLICIT ROUTE OBJECT
4031  *------------------------------------------------------------------------------*/
4032 static void
4033 dissect_rsvp_explicit_route (proto_item *ti, proto_tree *rsvp_object_tree,
4034                              tvbuff_t *tvb,
4035                              int offset, int obj_length,
4036                              int class, int type)
4037 {
4038     /* int offset2 = offset + 4; */
4039     /* int mylen, i, j, k, l; */
4040     /* proto_tree *ti2, *rsvp_ero_subtree; */
4041
4042     /* mylen = obj_length - 4; */
4043     switch(type) {
4044     case 1:
4045         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4046                             "C-type: 1");
4047         proto_item_set_text(ti, "EXPLICIT ROUTE: ");
4048
4049         dissect_rsvp_ero_rro_subobjects(ti, rsvp_object_tree, tvb,
4050                                         offset + 4, obj_length, class);
4051         break;
4052
4053     default:
4054         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4055                             "C-type: Unknown (%u)",
4056                             type);
4057         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, obj_length - 4,
4058                             "Data (%d bytes)", obj_length - 4);
4059         break;
4060     }
4061 }
4062
4063 /*------------------------------------------------------------------------------
4064  * RECORD ROUTE OBJECT
4065  *------------------------------------------------------------------------------*/
4066 static void
4067 dissect_rsvp_record_route (proto_item *ti, proto_tree *rsvp_object_tree,
4068                            tvbuff_t *tvb,
4069                            int offset, int obj_length,
4070                            int class, int type)
4071 {
4072     /* int offset2 = offset + 4; */
4073     /* int mylen, i, j, l; */
4074     /* proto_tree *ti2, *rsvp_rro_subtree; */
4075
4076     proto_item_set_text(ti, "RECORD ROUTE: ");
4077     /* mylen = obj_length - 4; */
4078     switch(type) {
4079     case 1:
4080         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4081                             "C-type: 1");
4082
4083         dissect_rsvp_ero_rro_subobjects(ti, rsvp_object_tree, tvb,
4084                                         offset + 4, obj_length, class);
4085         break;
4086
4087     default:
4088         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4089                             "C-type: Unknown (%u)",
4090                             type);
4091         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, obj_length - 4,
4092                             "Data (%d bytes)", obj_length - 4);
4093         break;
4094     }
4095 }
4096
4097 /*------------------------------------------------------------------------------
4098  * MESSAGE ID
4099  *------------------------------------------------------------------------------*/
4100 static void
4101 dissect_rsvp_message_id (proto_tree *ti, proto_tree *rsvp_object_tree,
4102                          tvbuff_t *tvb,
4103                          int offset, int obj_length,
4104                          int class _U_, int type)
4105 {
4106     int offset2 = offset + 4;
4107
4108     switch(type) {
4109     case 1:
4110         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4111                             "C-type: 1");
4112         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1,
4113                             "Flags: %d", tvb_get_guint8(tvb, offset+4));
4114         proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 3,
4115                             "Epoch: %d", tvb_get_ntoh24(tvb, offset+5));
4116         proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
4117                             "Message-ID: %d", tvb_get_ntohl(tvb, offset+8));
4118         proto_item_set_text(ti, "MESSAGE-ID: %d %s",
4119                             tvb_get_ntohl(tvb, offset+8),
4120                             tvb_get_guint8(tvb, offset+4) & 1 ? "(Ack Desired)" : "");
4121         break;
4122
4123     default:
4124         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4125                             "C-type: Unknown (%u)",
4126                             type);
4127         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
4128                             "Data (%d bytes)", obj_length - 4);
4129         break;
4130     }
4131 }
4132
4133 /*------------------------------------------------------------------------------
4134  * MESSAGE ID ACK
4135  *------------------------------------------------------------------------------*/
4136 static void
4137 dissect_rsvp_message_id_ack (proto_tree *ti, proto_tree *rsvp_object_tree,
4138                              tvbuff_t *tvb,
4139                              int offset, int obj_length,
4140                              int class _U_, int type)
4141 {
4142     int offset2 = offset + 4;
4143
4144     switch(type) {
4145     case 1:
4146         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4147                             "C-type: 1");
4148         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1,
4149                             "Flags: %d", tvb_get_guint8(tvb, offset+4));
4150         proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 3,
4151                             "Epoch: %d", tvb_get_ntoh24(tvb, offset+5));
4152         proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
4153                             "Message-ID: %d", tvb_get_ntohl(tvb, offset+8));
4154         proto_item_set_text(ti, "MESSAGE-ID ACK: %d", tvb_get_ntohl(tvb, offset+8));
4155         break;
4156
4157     case 2:
4158         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4159                             "C-type: 2");
4160         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1,
4161                             "Flags: %d", tvb_get_guint8(tvb, offset+4));
4162         proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 3,
4163                             "Epoch: %d", tvb_get_ntoh24(tvb, offset+5));
4164         proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
4165                             "Message-ID: %d", tvb_get_ntohl(tvb, offset+8));
4166         proto_item_set_text(ti, "MESSAGE-ID NACK: %d", tvb_get_ntohl(tvb, offset+8));
4167         break;
4168
4169     default:
4170         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4171                             "C-type: Unknown (%u)",
4172                             type);
4173         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
4174                             "Data (%d bytes)", obj_length - 4);
4175         break;
4176     }
4177 }
4178
4179 /*------------------------------------------------------------------------------
4180  * MESSAGE ID LIST
4181  *------------------------------------------------------------------------------*/
4182 static void
4183 dissect_rsvp_message_id_list (proto_tree *ti, proto_tree *rsvp_object_tree,
4184                               tvbuff_t *tvb,
4185                               int offset, int obj_length,
4186                               int class _U_, int type)
4187 {
4188     int offset2 = offset + 4;
4189     int mylen;
4190
4191     switch(type) {
4192     case 1:
4193         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4194                             "C-type: 1");
4195         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1,
4196                             "Flags: %d", tvb_get_guint8(tvb, offset+4));
4197         proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 3,
4198                             "Epoch: %d", tvb_get_ntoh24(tvb, offset+5));
4199         for (mylen = 8; mylen < obj_length; mylen += 4)
4200             proto_tree_add_text(rsvp_object_tree, tvb, offset+mylen, 4,
4201                                 "Message-ID: %d", tvb_get_ntohl(tvb, offset+mylen));
4202         proto_item_set_text(ti, "MESSAGE-ID LIST: %d IDs",
4203                             (obj_length - 8)/4);
4204         break;
4205
4206     default:
4207         mylen = obj_length - 4;
4208         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4209                             "C-type: Unknown (%u)",
4210                             type);
4211         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
4212                             "Data (%d bytes)", obj_length - 4);
4213         break;
4214     }
4215 }
4216
4217 /*------------------------------------------------------------------------------
4218  * HELLO
4219  *------------------------------------------------------------------------------*/
4220 static void
4221 dissect_rsvp_hello (proto_tree *ti, proto_tree *rsvp_object_tree,
4222                     tvbuff_t *tvb,
4223                     int offset, int obj_length _U_,
4224                     int class _U_, int type)
4225 {
4226     switch(type) {
4227     case 1:
4228     case 2:
4229         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4230                             "C-Type: %d - HELLO %s object",
4231                             tvb_get_guint8 (tvb, offset+3),
4232                             type==1 ? "REQUEST" : "ACK");
4233         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 4,
4234                             "Source Instance: 0x%x",tvb_get_ntohl(tvb, offset+4));
4235         proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
4236                             "Destination Instance: 0x%x",tvb_get_ntohl(tvb, offset+8));
4237         proto_item_append_text(ti, ": %s. Src Instance: 0x%0x. Dest Instance: 0x%0x. ",
4238                                type==1 ? "REQUEST" : "ACK",
4239                                tvb_get_ntohl(tvb, offset+4),
4240                                tvb_get_ntohl(tvb, offset+8));
4241         break;
4242     default:
4243         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4244                             "C-Type: %d - UNKNOWN", type);
4245         break;
4246     };
4247 }
4248
4249 /*------------------------------------------------------------------------------
4250  * DCLASS
4251  *------------------------------------------------------------------------------*/
4252 static void
4253 dissect_rsvp_dclass (proto_tree *ti, proto_tree *rsvp_object_tree,
4254                      tvbuff_t *tvb,
4255                      int offset, int obj_length,
4256                      int class _U_, int type)
4257 {
4258     int offset2 = offset + 4;
4259     int mylen;
4260
4261     proto_item_set_text(ti, "DCLASS: ");
4262     switch(type) {
4263     case 1:
4264         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4265                             "C-type: 1");
4266         for (mylen = 4; mylen < obj_length; mylen += 4) {
4267             proto_tree_add_text(rsvp_object_tree, tvb, offset+mylen+3, 1,
4268                                 "DSCP: %s",
4269                                 val_to_str(tvb_get_guint8(tvb, offset+mylen+3),
4270                                            dscp_vals, "Unknown (%d)"));
4271             proto_item_append_text(ti, "%d%s",
4272                                    tvb_get_guint8(tvb, offset+mylen+3)>>2,
4273                                    mylen==obj_length-4 ? "":
4274                                    mylen<16 ? ", ":
4275                                    mylen==16 ? ", ..." : "");
4276         }
4277         break;
4278
4279     default:
4280         mylen = obj_length - 4;
4281         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4282                             "C-type: Unknown (%u)",
4283                             type);
4284         proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
4285                             "Data (%d bytes)", mylen);
4286         break;
4287     }
4288 }
4289
4290 /*------------------------------------------------------------------------------
4291  * ADMINISTRATIVE STATUS
4292  *------------------------------------------------------------------------------*/
4293 static void
4294 dissect_rsvp_admin_status (proto_tree *ti, proto_tree *rsvp_object_tree,
4295                            tvbuff_t *tvb,
4296                            int offset, int obj_length,
4297                            int class _U_, int type)
4298 {
4299     int offset2 = offset + 4;
4300     proto_tree *ti2, *rsvp_admin_subtree;
4301     int mylen;
4302     guint32 status;
4303
4304     proto_item_set_text(ti, "ADMIN STATUS: ");
4305     switch(type) {
4306     case 1:
4307         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4308                             "C-type: 1");
4309         status = tvb_get_ntohl(tvb, offset2);
4310         ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
4311                                   "Admin Status: 0x%08x", status);
4312         rsvp_admin_subtree =
4313             proto_item_add_subtree(ti2, TREE(TT_ADMIN_STATUS_FLAGS));
4314         proto_tree_add_text(rsvp_admin_subtree, tvb, offset2, 4,
4315                             decode_boolean_bitfield(status, 0x80000000, 32,
4316                                                     "R: Reflect",
4317                                                     "R: Do not reflect"));
4318         proto_tree_add_text(rsvp_admin_subtree, tvb, offset2, 4,
4319                             decode_boolean_bitfield(status, 0x04, 32,
4320                                                     "T: Testing",
4321                                                     "T: "));
4322         proto_tree_add_text(rsvp_admin_subtree, tvb, offset2, 4,
4323                             decode_boolean_bitfield(status, 0x02, 32,
4324                                                     "A: Administratively Down",
4325                                                     "A: "));
4326         proto_tree_add_text(rsvp_admin_subtree, tvb, offset2, 4,
4327                             decode_boolean_bitfield(status, 0x01, 32,
4328                                                     "D: Delete In Progress",
4329                                                     "D: "));
4330         proto_item_set_text(ti, "ADMIN-STATUS: %s %s %s %s",
4331                             (status & (1<<31)) ? "Reflect" : "",
4332                             (status & (1<<2))  ? "Testing" : "",
4333                             (status & (1<<1))  ? "Admin-Down" : "",
4334                             (status & (1<<0))  ? "Deleting" : "");
4335         break;
4336
4337     default:
4338         mylen = obj_length - 4;
4339         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4340                             "C-type: Unknown (%u)",
4341                             type);
4342         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
4343                             "Data (%d bytes)", obj_length - 4);
4344         break;
4345     }
4346 }
4347
4348 /*------------------------------------------------------------------------------
4349  * ASSOCIATION
4350  *------------------------------------------------------------------------------*/
4351 static void
4352 dissect_rsvp_association (proto_tree *ti, proto_tree *rsvp_object_tree,
4353                           tvbuff_t *tvb,
4354                           int offset, int obj_length,
4355                           int class _U_, int type)
4356 {
4357     guint16 association_type;
4358     guint16 association_id;
4359     static const value_string association_type_vals[] = {
4360       {0, "Reserved"},
4361       {1, "Recovery"},
4362       { 0, NULL}
4363     };
4364
4365     proto_item_set_text(ti, "ASSOCIATION ");
4366     association_type = tvb_get_ntohs (tvb, offset + 4);
4367     association_id = tvb_get_ntohs (tvb, offset + 6);
4368     switch(type) {
4369     case 1:
4370         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4371                             "C-type: 1 (IPv4)");
4372         proto_item_append_text(ti, "(IPv4): ");
4373         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 2,
4374                             "Association type: %s",
4375                             val_to_str(association_type, association_type_vals, "Unknown (%u)"));
4376         proto_item_append_text(ti, "%s. ",
4377                                val_to_str(association_type, association_type_vals, "Unknown (%u)"));
4378         proto_tree_add_text(rsvp_object_tree, tvb, offset+6, 2,
4379                             "Association ID: %u", association_id);
4380         proto_item_append_text(ti, "ID: %u. ", association_id);
4381         proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
4382                             "Association source: %s", ip_to_str(tvb_get_ptr(tvb, offset+8, 4)));
4383         proto_item_append_text(ti, "Src: %s", ip_to_str(tvb_get_ptr(tvb, offset+8, 4)));
4384         break;
4385
4386     case 2:
4387         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4388                             "C-type: 2 (IPv6)");
4389         proto_item_append_text(ti, "(IPv6): ");
4390         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 2,
4391                             "Association type: %s",
4392                             val_to_str(association_type, association_type_vals, "Unknown (%u)"));
4393         proto_item_append_text(ti, "%s. ",
4394                                val_to_str(association_type, association_type_vals, "Unknown (%u)"));
4395         proto_tree_add_text(rsvp_object_tree, tvb, offset+6, 2,
4396                             "Association ID: %u", association_id);
4397         proto_item_append_text(ti, "ID: %u. ", association_id);
4398         proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 16,
4399                             "Association source: %s", ip6_to_str((const struct e_in6_addr *)
4400                                                                 tvb_get_ptr(tvb, offset+8, 16)));
4401         proto_item_append_text(ti, "Src: %s", ip6_to_str((const struct e_in6_addr *)
4402                                                         tvb_get_ptr(tvb, offset+8, 16)));
4403         break;
4404
4405     default:
4406         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4407                             "C-type: Unknown (%u)", type);
4408         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, obj_length - 4,
4409                             "Data (%d bytes)", obj_length - 4);
4410         break;
4411     }
4412 }
4413
4414 /*------------------------------------------------------------------------------
4415  * TLVs for LSP TUNNEL IF ID object
4416  * draft-ietf-ccamp-lsp-hierarchy-bis-02
4417  *------------------------------------------------------------------------------*/
4418 static void
4419 dissect_rsvp_lsp_tunnel_if_id_tlv(proto_tree *rsvp_object_tree,
4420                                   tvbuff_t *tvb, int offset, int tlv_length,
4421                                   int subtree_type)
4422 {
4423     int       tlv_off;
4424     guint16   tlv_type;
4425     int       tlv_len;
4426     proto_tree *ti, *rsvp_lsp_tunnel_if_id_subtree;
4427
4428     for (tlv_off = 0; tlv_off < tlv_length; ) {
4429         tlv_type = tvb_get_ntohs(tvb, offset+tlv_off);
4430         tlv_len = tvb_get_ntohs(tvb, offset+tlv_off+2);
4431
4432         if (tlv_len == 0 || tlv_off+tlv_len > tlv_length) {
4433             proto_tree_add_text(rsvp_object_tree, tvb, offset+tlv_off+2, 2,
4434                                 "Invalid length");
4435             return;
4436         }
4437         switch(tlv_type) {
4438         case 1:
4439             ti = proto_tree_add_text(rsvp_object_tree, tvb,
4440                                      offset+tlv_off, tlv_len,
4441                                      "Unnumbered component link identifier: %u",
4442                                      tvb_get_ntohl(tvb, offset+tlv_off+4));
4443             rsvp_lsp_tunnel_if_id_subtree = proto_item_add_subtree(ti, subtree_type);
4444             proto_tree_add_text(rsvp_lsp_tunnel_if_id_subtree, tvb, offset+tlv_off, 2,
4445                                 "Type: 1 (Unnumbered component link identifier)");
4446             proto_tree_add_text(rsvp_lsp_tunnel_if_id_subtree, tvb, offset+tlv_off+2, 2,
4447                                 "Length: %u", tlv_len);
4448             proto_tree_add_text(rsvp_lsp_tunnel_if_id_subtree, tvb, offset+tlv_off+4, 4,
4449                                 "Component link identifier: %u",
4450                                 tvb_get_ntohl(tvb, offset+tlv_off+4));
4451             break;
4452             
4453         case 2:
4454             ti = proto_tree_add_text(rsvp_object_tree, tvb,
4455                                      offset+tlv_off, tlv_len,
4456                                      "IPv4 component link identifier: %s",
4457                                      ip_to_str(tvb_get_ptr(tvb, offset+tlv_off+4, 4)));
4458             rsvp_lsp_tunnel_if_id_subtree = proto_item_add_subtree(ti, subtree_type);
4459             proto_tree_add_text(rsvp_lsp_tunnel_if_id_subtree, tvb, offset+tlv_off, 2,
4460                                 "Type: 2 (IPv4 component link identifier)");
4461             proto_tree_add_text(rsvp_lsp_tunnel_if_id_subtree, tvb, offset+tlv_off+2, 2,
4462                                 "Length: %u", tlv_len);
4463             proto_tree_add_text(rsvp_lsp_tunnel_if_id_subtree, tvb, offset+tlv_off+4, 4,
4464                                 "Component link identifier: %s",
4465                                 ip_to_str(tvb_get_ptr(tvb, offset+tlv_off+4, 4)));
4466             break;
4467             
4468         case 32769:  /* oif-p0040.002.09 demo spec */
4469             ti = proto_tree_add_text(rsvp_object_tree, tvb,
4470                                      offset+tlv_off, tlv_len,
4471                                      "Targeted client layer: ");
4472             rsvp_lsp_tunnel_if_id_subtree = proto_item_add_subtree(ti, subtree_type);
4473             proto_tree_add_text(rsvp_lsp_tunnel_if_id_subtree, tvb, offset+tlv_off, 2,
4474                                 "Type: 32769 (Targeted client layer)");
4475             proto_tree_add_text(rsvp_lsp_tunnel_if_id_subtree, tvb, offset+tlv_off+2, 2,
4476                                 "Length: %u", tlv_len);
4477             proto_tree_add_text(rsvp_lsp_tunnel_if_id_subtree, tvb, offset+tlv_off+4, 1,
4478                                 "LSP Encoding Type: %s",
4479                                 val_to_str(tvb_get_guint8(tvb,offset+tlv_off+4),
4480                                            gmpls_lsp_enc_str, "Unknown (%d)"));
4481             proto_tree_add_text(rsvp_lsp_tunnel_if_id_subtree, tvb, offset+tlv_off+5, 1,
4482                                 "Switching Type: %s",
4483                                 val_to_str(tvb_get_guint8(tvb,offset+tlv_off+5),
4484                                            gmpls_switching_type_str, "Unknown (%d)"));
4485             proto_tree_add_text(rsvp_lsp_tunnel_if_id_subtree, tvb, offset+tlv_off+6, 1,
4486                                 "Signal Type: %s",
4487                                 val_to_str(tvb_get_guint8(tvb,offset+tlv_off+6),
4488                                            gmpls_sonet_signal_type_str, "Unknown (%d)"));
4489             proto_tree_add_text(rsvp_lsp_tunnel_if_id_subtree, tvb, offset+tlv_off+8, 8,
4490                                 "Sub Interface/Connection ID: %" G_GINT64_MODIFIER "u (0x%s)",
4491                                 tvb_get_ntoh64(tvb, offset+tlv_off+8),
4492                                 tvb_bytes_to_str(tvb, offset+tlv_off+8, 8));
4493             proto_tree_add_text(rsvp_lsp_tunnel_if_id_subtree, tvb, offset+tlv_off+16, 4,
4494                                 "SC PC ID: %s",
4495                                 ip_to_str(tvb_get_ptr(tvb, offset+tlv_off+16, 4)));
4496             proto_tree_add_text(rsvp_lsp_tunnel_if_id_subtree, tvb, offset+tlv_off+20, 4,
4497                                 "SC PC SCN Address: %s",
4498                                 ip_to_str(tvb_get_ptr(tvb, offset+tlv_off+20, 4)));
4499             proto_item_append_text(ti, "LSP Encoding=%s, Switching Type=%s, Signal Type=%s",
4500                                    val_to_str(tvb_get_guint8(tvb,offset+tlv_off+4),
4501                                               gmpls_lsp_enc_str, "Unknown (%d)"),
4502                                    val_to_str(tvb_get_guint8(tvb,offset+tlv_off+5),
4503                                               gmpls_switching_type_str, "Unknown (%d)"),
4504                                    val_to_str(tvb_get_guint8(tvb,offset+tlv_off+6),
4505                                               gmpls_sonet_signal_type_str, "Unknown (%d)"));
4506             break;
4507
4508         default:
4509             proto_tree_add_text(rsvp_object_tree, tvb, offset+tlv_off, 2,
4510                                 "Unknown TLV: %u", tlv_type);
4511         }
4512         tlv_off += tlv_len;
4513     }
4514 }
4515
4516 /*------------------------------------------------------------------------------
4517  * LSP TUNNEL INTERFACE ID
4518  *------------------------------------------------------------------------------*/
4519 static void
4520 dissect_rsvp_lsp_tunnel_if_id (proto_tree *ti, proto_tree *rsvp_object_tree,
4521                                tvbuff_t *tvb,
4522                                int offset, int obj_length,
4523                                int class _U_, int type)
4524 {
4525     guint8  action;
4526
4527     static const value_string lsp_tunnel_if_id_action_str[] = {
4528       {0, "LSP is FA (MPLS-TE topology advertisement only)"},
4529       {1, "LSP is RA (IP network advertisement only)"},
4530       {2, "LSP is RA (both IP and MPLS-TE topology advertisement)"},
4531       {3, "LSP is to be used as a virtual local link"},
4532       {0, NULL}
4533     };
4534
4535     proto_item_set_text(ti, "LSP INTERFACE-ID: ");
4536     switch(type) {
4537     case 1:
4538         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4539                             "C-type: 1 - Unnumbered interface");
4540         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 4,
4541                             "Router ID: %s",
4542                             ip_to_str(tvb_get_ptr(tvb, offset+4, 4)));
4543         proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
4544                             "Interface ID: %u", tvb_get_ntohl(tvb, offset+8));
4545         proto_item_set_text(ti, "LSP INTERFACE-ID: Unnumbered, Router-ID %s, Interface-ID %d",
4546                             ip_to_str(tvb_get_ptr(tvb, offset+4, 4)),
4547                             tvb_get_ntohl(tvb, offset+8));
4548         break;
4549
4550     case 2:
4551         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4552                             "C-type: 2 - IPv4");
4553         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 4,
4554                             "IPv4 interface address: %s",
4555                             ip_to_str(tvb_get_ptr(tvb, offset+4, 4)));
4556         proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
4557                             "Target IGP instance: %s",
4558                             ip_to_str(tvb_get_ptr(tvb, offset+8, 4)));
4559         proto_item_set_text(ti, "LSP INTERFACE-ID: IPv4, interface address %s,"
4560                             "IGP instance %s",
4561                             ip_to_str(tvb_get_ptr(tvb, offset+4, 4)),
4562                             ip_to_str(tvb_get_ptr(tvb, offset+8, 4)));
4563         action = tvb_get_guint8(tvb, offset+12);
4564         action >>= 4;
4565         proto_tree_add_text(rsvp_object_tree, tvb, offset+12, 1, "Action: %d - %s",
4566                             action,
4567                             val_to_str(action, lsp_tunnel_if_id_action_str, "Unknown"));
4568         dissect_rsvp_lsp_tunnel_if_id_tlv(rsvp_object_tree, tvb, offset+16, obj_length-16,
4569                                           TREE(TT_LSP_TUNNEL_IF_ID_SUBTREE));
4570         break;
4571
4572     case 3:
4573         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4574                             "C-type: 3 - IPv6");
4575         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 16,
4576                             "IPv6 interface address: %s",
4577                             ip6_to_str((const struct e_in6_addr *)
4578                                         tvb_get_ptr(tvb, offset+4, 16)));
4579         proto_tree_add_text(rsvp_object_tree, tvb, offset+20, 4,
4580                             "Target IGP instance: %s",
4581                             ip_to_str(tvb_get_ptr(tvb, offset+20, 4)));
4582         proto_item_set_text(ti, "LSP INTERFACE-ID: IPv6, interface address %s,"
4583                             "IGP instance %s",
4584                             ip6_to_str((const struct e_in6_addr *)
4585                                         tvb_get_ptr(tvb, offset+4, 16)),
4586                             ip_to_str(tvb_get_ptr(tvb, offset+20, 4)));
4587         action = tvb_get_guint8(tvb, offset+24);
4588         action >>= 4;
4589         proto_tree_add_text(rsvp_object_tree, tvb, offset+24, 1, "Action: %d - %s",
4590                             action,
4591                             val_to_str(action, lsp_tunnel_if_id_action_str, "Unknown"));
4592         dissect_rsvp_lsp_tunnel_if_id_tlv(rsvp_object_tree, tvb, offset+28, obj_length-28,
4593                                           TREE(TT_LSP_TUNNEL_IF_ID_SUBTREE));
4594         break;
4595
4596     case 4:
4597         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4598                             "C-type: 4 - Unnumbered interface with target");
4599         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 4,
4600                             "Router ID: %s",
4601                             ip_to_str(tvb_get_ptr(tvb, offset+4, 4)));
4602         proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
4603                             "Interface ID: %u", tvb_get_ntohl(tvb, offset+8));
4604         proto_tree_add_text(rsvp_object_tree, tvb, offset+12, 4,
4605                             "Target IGP instance: %s",
4606                             ip_to_str(tvb_get_ptr(tvb, offset+12, 4)));
4607         proto_item_set_text(ti, "LSP INTERFACE-ID: Unnumbered with target, Router-ID %s,"
4608                             " Interface-ID %d, IGP instance %s",
4609                             ip_to_str(tvb_get_ptr(tvb, offset+4, 4)),
4610                             tvb_get_ntohl(tvb, offset+8),
4611                             ip_to_str(tvb_get_ptr(tvb, offset+12, 4)));
4612         action = tvb_get_guint8(tvb, offset+16);
4613         action >>= 4;
4614         proto_tree_add_text(rsvp_object_tree, tvb, offset+16, 1, "Action: %d - %s",
4615                             action,
4616                             val_to_str(action, lsp_tunnel_if_id_action_str, "Unknown"));
4617         dissect_rsvp_lsp_tunnel_if_id_tlv(rsvp_object_tree, tvb, offset+20, obj_length-20,
4618                                           TREE(TT_LSP_TUNNEL_IF_ID_SUBTREE));
4619         break;
4620
4621     default:
4622         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4623                             "C-type: Unknown (%u)",
4624                             type);
4625         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, obj_length-4,
4626                             "Data (%d bytes)", obj_length-4);
4627         break;
4628     }
4629 }
4630
4631 /*------------------------------------------------------------------------------
4632  * NOTIFY REQUEST
4633  *------------------------------------------------------------------------------*/
4634 static void
4635 dissect_rsvp_notify_request (proto_item *ti, proto_tree *rsvp_object_tree,
4636                              tvbuff_t *tvb,
4637                              int offset, int obj_length,
4638                              int class _U_, int type)
4639 {
4640     int offset2 = offset + 4;
4641
4642     switch(type) {
4643     case 1: {
4644         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4645                             "C-type: 1 - IPv4");
4646         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
4647                             "Notify node address: %s",
4648                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
4649         proto_item_append_text(ti, ": Notify node: %s",
4650                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
4651         break;
4652     }
4653
4654     case 2: {
4655         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4656                             "C-type: 2 - IPv6");
4657         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16,
4658                             "Notify node address: %s",
4659                             ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
4660         proto_item_append_text(ti, ": Notify node: %s",
4661                                ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
4662         break;
4663     }
4664
4665     default:
4666         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4667                             "C-type: Unknown (%u)",
4668                             type);
4669         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
4670                             "Data (%d bytes)", obj_length - 4);
4671     }
4672 }
4673
4674 /*------------------------------------------------------------------------------
4675  * GENERALIZED UNI
4676  *------------------------------------------------------------------------------*/
4677 static void
4678 dissect_rsvp_gen_uni (proto_tree *ti, proto_tree *rsvp_object_tree,
4679                       tvbuff_t *tvb,
4680                       int offset, int obj_length,
4681                       int class _U_, int type,
4682                       rsvp_conversation_info *rsvph)
4683 {
4684     int offset2 = offset + 4;
4685     int mylen, i, j, k, l, m;
4686     proto_item *ti2;
4687     proto_tree *rsvp_gen_uni_subtree, *rsvp_session_subtree, *rsvp_template_subtree;
4688     int s_len, s_class, s_type;
4689     int offset3;
4690
4691     proto_item_set_text(ti, "GENERALIZED UNI: ");
4692
4693     mylen = obj_length - 4;
4694     switch(type) {
4695     case 1: {
4696         const char *c;
4697         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4698                             "C-type: 1");
4699         for (i=1, l = 0; l < mylen; i++) {
4700             j = tvb_get_guint8(tvb, offset2+l+2);
4701             switch(j) {
4702             case 1:
4703             case 2: /* We do source and destination TNA together */
4704                 c = (j==1) ? "Source" : "Destination";
4705                 k = tvb_get_guint8(tvb, offset2+l+3);
4706                 switch(k) {
4707                 case 1:
4708                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
4709                                               offset2+l, 8,
4710                                               "%s IPv4 TNA: %s", c,
4711                                               ip_to_str(tvb_get_ptr(tvb, offset2+l+4, 4)));
4712                     rsvp_gen_uni_subtree =
4713                         proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
4714                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
4715                                         "Class: %d (%s)", j, c);
4716                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
4717                                         "Type: 1 (IPv4)");
4718                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
4719                                         "Length: %u",
4720                                         tvb_get_ntohs(tvb, offset2+l));
4721                     if (j==1)
4722                       proto_tree_add_item(rsvp_gen_uni_subtree, rsvp_filter[RSVPF_GUNI_SRC_IPV4],
4723                                           tvb, offset2+l+4, 4, FALSE);
4724                     else
4725                       proto_tree_add_item(rsvp_gen_uni_subtree, rsvp_filter[RSVPF_GUNI_DST_IPV4],
4726                                           tvb, offset2+l+4, 4, FALSE);
4727                     if (i < 4) {
4728                         proto_item_append_text(ti, "%s IPv4 TNA: %s", c,
4729                                                ip_to_str(tvb_get_ptr(tvb, offset2+l+4, 4)));
4730                     }
4731                     break;
4732
4733                 case 2:
4734                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
4735                                               offset2+l, 20,
4736                                               "%s IPv6 TNA", c);
4737                     rsvp_gen_uni_subtree =
4738                         proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
4739                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
4740                                         "Class: %d (%s)", j, c);
4741                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
4742                                         "Type: 2 (IPv6)");
4743                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
4744                                         "Length: %u",
4745                                         tvb_get_ntohs(tvb, offset2+l));
4746                     if (j==1)
4747                       proto_tree_add_item(rsvp_gen_uni_subtree, rsvp_filter[RSVPF_GUNI_SRC_IPV6],
4748                                           tvb, offset2+l+4, 16, FALSE);
4749                     else
4750                       proto_tree_add_item(rsvp_gen_uni_subtree, rsvp_filter[RSVPF_GUNI_DST_IPV6],
4751                                           tvb, offset2+l+4, 16, FALSE);
4752                     if (i < 4) {
4753                         proto_item_append_text(ti, "%s IPv6 %s", c,
4754                                                ip6_to_str((const struct e_in6_addr *)
4755                                                           tvb_get_ptr(tvb, offset2+l+4, 16)));
4756                     }
4757                     break;
4758
4759                 case 3:
4760                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
4761                                               offset2+l, tvb_get_ntohs(tvb, offset2+l),
4762                                               "%s NSAP TNA", c);
4763                     rsvp_gen_uni_subtree =
4764                         proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
4765                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
4766                                         "Class: %d (%s)", j, c);
4767                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
4768                                         "Type: 3 (NSAP)");
4769                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
4770                                         "Length: %u",
4771                                         tvb_get_ntohs(tvb, offset2+l));
4772                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4,
4773                                         tvb_get_ntohs(tvb, offset2+l)-4,
4774                                         "Data");
4775                     if (i < 4) {
4776                         proto_item_append_text(ti, "%s NSAP", c);
4777                     }
4778                     break;
4779
4780                 default:
4781                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
4782                                               offset2+l, tvb_get_ntohs(tvb, offset2+l),
4783                                               "%s UNKNOWN TNA", c);
4784                     rsvp_gen_uni_subtree =
4785                         proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
4786                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
4787                                         "Class: %d (%s)", j, c);
4788                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
4789                                         "Type: %d (UNKNOWN)", j);
4790                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
4791                                         "Length: %u",
4792                                         tvb_get_ntohs(tvb, offset2+l));
4793                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4,
4794                                         tvb_get_ntohs(tvb, offset2+l)-4,
4795                                         "Data");
4796                     if (i < 4) {
4797                         proto_item_append_text(ti, "%s UNKNOWN", c);
4798                     }
4799                     break;
4800                 }
4801                 break;
4802
4803             case 3: /* Diversity subobject */
4804                 k = tvb_get_guint8(tvb, offset2+l+3);
4805                 switch(k) {
4806                 default:
4807                 case 1:
4808                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
4809                                               offset2+l, tvb_get_ntohs(tvb, offset2+l),
4810                                               "Diversity Subobject");
4811                     rsvp_gen_uni_subtree =
4812                         proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
4813                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
4814                                         "Class: %d (Diversity)", j);
4815                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
4816                                         "Type: %d", tvb_get_guint8(tvb, offset2+l+3));
4817                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
4818                                         "Length: %u",
4819                                         tvb_get_ntohs(tvb, offset2+l));
4820                     m = tvb_get_guint8(tvb, offset2+l+4) >> 4;
4821                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 1,
4822                                         "Diversity: %d - %s", m,
4823                                         val_to_str(m, ouni_guni_diversity_str, "Unknown"));
4824                     s_len = tvb_get_ntohs(tvb, offset2+l+8);
4825                     s_class = tvb_get_guint8(tvb, offset2+l+10);
4826                     s_type = tvb_get_guint8(tvb, offset2+l+11);
4827                     ti2 = proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+8,
4828                                               s_len, "Session");
4829                     rsvp_session_subtree =
4830                         proto_item_add_subtree(ti2, TREE(rsvp_class_to_tree_type(s_class)));
4831                     if (s_len < 4) {
4832                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+l+8, 2,
4833                             "Length: %u (bogus, must be >= 4)", s_len);
4834                         break;
4835                     }
4836                     proto_tree_add_text(rsvp_session_subtree, tvb, offset2+l+8, 2,
4837                                 "Length: %u", s_len);
4838                     proto_tree_add_uint(rsvp_session_subtree, rsvp_filter[RSVPF_OBJECT], tvb,
4839                                 offset2+8+l+10, 1, s_class);
4840                     dissect_rsvp_session(ti2, rsvp_session_subtree, tvb, offset2+l+8,
4841                                          s_len, s_class, s_type, rsvph);
4842                     offset3 = offset2 + s_len;
4843                     s_len = tvb_get_ntohs(tvb, offset3+l+8);
4844                     s_class = tvb_get_guint8(tvb, offset3+l+10);
4845                     s_type = tvb_get_guint8(tvb, offset3+l+11);
4846                     ti2 = proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset3+l+8,
4847                                               s_len, "Template");
4848                     rsvp_template_subtree =
4849                         proto_item_add_subtree(ti2, TREE(rsvp_class_to_tree_type(s_class)));
4850                     if (s_len < 4) {
4851                         proto_tree_add_text(rsvp_object_tree, tvb, offset3+l+8, 2,
4852                             "Length: %u (bogus, must be >= 4)", s_len);
4853                         break;
4854                     }
4855                     proto_tree_add_text(rsvp_template_subtree, tvb, offset3+l+8, 2,
4856                                 "Length: %u", s_len);
4857                     proto_tree_add_uint(rsvp_template_subtree, rsvp_filter[RSVPF_OBJECT], tvb,
4858                                 offset3+8+l+10, 1, s_class);
4859                     dissect_rsvp_template_filter(ti2, rsvp_template_subtree, tvb, offset3+l+8,
4860                                                  s_len, s_class, s_type, rsvph);
4861
4862                     if (i < 4) {
4863                         proto_item_append_text(ti, "Diversity");
4864                     }
4865                     break;
4866
4867                 }
4868                 break;
4869
4870             case 4: /* Egress Label */
4871                 k = tvb_get_guint8(tvb, offset2+l+3);
4872                 if (k == 1)             /* Egress label sub-type */
4873                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
4874                                               offset2+l, tvb_get_ntohs(tvb, offset2+l),
4875                                               "Egress Label Subobject");
4876                 else if (k == 2)        /* SPC_label sub-type (see G.7713.2) */
4877                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
4878                                               offset2+l, tvb_get_ntohs(tvb, offset2+l),
4879                                               "SPC Label Subobject");
4880                 else
4881                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
4882                                               offset2+l, tvb_get_ntohs(tvb, offset2+l),
4883                                               "Unknown Label Subobject");
4884                 rsvp_gen_uni_subtree = proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
4885                 proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
4886                                     "Class: %d (Egress/SPC Label)", j);
4887                 proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
4888                                     "Type: %d", k);
4889                 proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
4890                                     "Length: %u",
4891                                     tvb_get_ntohs(tvb, offset2+l));
4892                 proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 1,
4893                                     "Direction: %s",
4894                                     decode_boolean_bitfield(
4895                                         tvb_get_guint8(tvb, offset2+l+4), 0x80, 8,
4896                                         "U: 1 - Upstream label/port ID",
4897                                         "U: 0 - Downstream label/port ID"));
4898                 proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+7, 1,
4899                                     "Label type: %u", tvb_get_guint8(tvb, offset2+l+7));
4900                 proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+8, 4,
4901                                     "Logical Port ID: %u", tvb_get_ntohl(tvb, offset2+l+8));
4902                 proto_item_append_text(ti2, ": %s, Label type %d, Port ID %d, Label ",
4903                                        tvb_get_guint8(tvb, offset2+l+4) & 0x80 ?
4904                                        "Upstream" : "Downstream",
4905                                        tvb_get_guint8(tvb, offset2+l+7),
4906                                        tvb_get_ntohl(tvb, offset2+l+8));
4907                 for (j=12; j < tvb_get_ntohs(tvb, offset2+l); j+=4) {
4908                         proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+j, 4,
4909                                             "Label: %u", tvb_get_ntohl(tvb, offset2+l+j));
4910                         proto_item_append_text(ti2, "%u ", tvb_get_ntohl(tvb, offset2+l+j));
4911                 }
4912                 if (i < 4) {
4913                         if (k == 1)
4914                             proto_item_append_text(ti, "Egress Label");
4915                         else if (k == 2)
4916                             proto_item_append_text(ti, "SPC Label");
4917                 }
4918                 break;
4919
4920             case 5: /* Service Level */
4921                 k = tvb_get_guint8(tvb, offset2+l+3);
4922                 switch(k) {
4923                 default:
4924                 case 1:
4925                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
4926                                               offset2+l, tvb_get_ntohs(tvb, offset2+l),
4927                                               "Service Level Subobject");
4928                     rsvp_gen_uni_subtree =
4929                         proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
4930                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+2, 1,
4931                                         "Class: %d (Egress Label)", j);
4932                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+3, 1,
4933                                         "Type: %d", tvb_get_guint8(tvb, offset2+l+3));
4934                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 2,
4935                                         "Length: %u",
4936                                         tvb_get_ntohs(tvb, offset2+l));
4937                     proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+4, 1,
4938                                         "Service Level: %u", tvb_get_guint8(tvb, offset2+l+4));
4939                     proto_item_append_text(ti2, ": %u", tvb_get_guint8(tvb, offset2+l+4));
4940                     if (i < 4) {
4941                         proto_item_append_text(ti, "Service Level %d", tvb_get_guint8(tvb, offset2+l+4));
4942                     }
4943                     break;
4944                 }
4945                 break;
4946
4947             default: /* Unknown subobject */
4948                 ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
4949                                           offset2+l,
4950                                           tvb_get_ntohs(tvb, offset2+l),
4951                                           "Unknown subobject: %u",
4952                                           j);
4953                 rsvp_gen_uni_subtree =
4954                     proto_item_add_subtree(ti2, TREE(TT_GEN_UNI_SUBOBJ));
4955                 proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l, 1,
4956                                     "Type: %u (Unknown)", j);
4957                 proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+1, 1,
4958                                     "Length: %u",
4959                                     tvb_get_guint8(tvb, offset2+l+1));
4960
4961             }
4962
4963             if (tvb_get_guint8(tvb, offset2+l+1) < 1) {
4964                 proto_tree_add_text(rsvp_gen_uni_subtree, tvb, offset2+l+1, 1,
4965                     "Invalid length: %u", tvb_get_guint8(tvb, offset2+l+1));
4966                 return;
4967             }
4968             l += tvb_get_guint8(tvb, offset2+l+1);
4969             if (l < mylen) {
4970                 if (i < 4)
4971                     proto_item_append_text(ti, ", ");
4972                 else if (i==4)
4973                     proto_item_append_text(ti, "...");
4974             }
4975         }
4976         break;
4977     }
4978
4979     default:
4980         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
4981                             "C-type: Unknown (%u)",
4982                             type);
4983         proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
4984                             "Data (%d bytes)", mylen);
4985         break;
4986     }
4987 }
4988
4989 /*------------------------------------------------------------------------------
4990  * CALL_ID
4991  *------------------------------------------------------------------------------*/
4992 static void
4993 dissect_rsvp_call_id (proto_tree *ti, proto_tree *rsvp_object_tree,
4994                       tvbuff_t *tvb,
4995                       int offset, int obj_length,
4996                       int class _U_, int c_type)
4997 {
4998     int type;
4999     char *str;
5000     int offset2 = offset + 4;
5001     int offset3, offset4, len;
5002
5003     static const value_string address_type_vals[] = {
5004       {1, "1 (IPv4)"},
5005       {2, "2 (IPv6)"},
5006       {3, "3 (NSAP)"},
5007       {4, "4 (MAC)"},
5008       {0x7f, "0x7f (Vendor-defined)"},
5009       {0, NULL}
5010     };
5011
5012     proto_item_set_text(ti, "CALL-ID: ");
5013     type = tvb_get_guint8 (tvb, offset2);
5014     switch(c_type) {
5015     case 0:
5016           proto_item_append_text(ti,"Empty");
5017           proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
5018                               "C-type: Empty (%u)", type);
5019           proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length-4,
5020                               "Data (%d bytes)", obj_length-4);
5021           break;
5022     case 1:
5023     case 2:
5024         if (c_type == 1) {
5025           offset3 = offset2 + 4;
5026           len = obj_length - 16;
5027           proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
5028                             "C-type: 1 (operator specific)");
5029           proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1, "Address type: %s",
5030                               val_to_str(type, address_type_vals, "Unknown (%u)"));
5031           proto_tree_add_text(rsvp_object_tree, tvb, offset2+1, 3, "Reserved: %u",
5032                               tvb_get_ntoh24(tvb, offset2+1));
5033           proto_item_append_text(ti, "Operator-Specific. Addr Type: %s. ",
5034                                  val_to_str(type, address_type_vals, "Unknown (%u)"));
5035         }
5036         else {
5037           offset3 = offset2 + 16;
5038           len = obj_length - 28;
5039           proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
5040                             "C-type: 2 (globally unique)");
5041           proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1, "Address type: %s",
5042                               val_to_str(type, address_type_vals, "Unknown (%u)"));
5043           str = tvb_get_ephemeral_string (tvb, offset2 + 1, 3);
5044           proto_tree_add_text(rsvp_object_tree, tvb, offset2 + 1, 3,
5045                               "International Segment: %s", str);
5046           proto_item_append_text(ti, "Globally-Unique. Addr Type: %s. Intl Segment: %s. ",
5047                                  val_to_str(type, address_type_vals, "Unknown (%u)"), str);
5048           str = tvb_get_ephemeral_string (tvb, offset2 + 4, 12);
5049           proto_tree_add_text(rsvp_object_tree, tvb, offset2 + 4, 12,
5050                               "National Segment: %s", str);
5051           proto_item_append_text(ti, "Natl Segment: %s. ", str);
5052         }
5053
5054         switch(type) {
5055         case 1:
5056           offset4 = offset3 + 4;
5057           proto_tree_add_item(rsvp_object_tree, rsvp_filter[RSVPF_CALL_ID_SRC_ADDR_IPV4],
5058                               tvb, offset3, 4, FALSE);
5059           proto_item_append_text(ti, "Src: %s. ", ip_to_str(tvb_get_ptr(tvb, offset3, 4)));
5060           break;
5061
5062         case 2:
5063           offset4 = offset3 + 16;
5064           proto_tree_add_item(rsvp_object_tree, rsvp_filter[RSVPF_CALL_ID_SRC_ADDR_IPV6],
5065                               tvb, offset3, 16, FALSE);
5066           proto_item_append_text(ti, "Src: %s. ",
5067                                  ip6_to_str((const struct e_in6_addr *) tvb_get_ptr(tvb, offset3, 16)));
5068           break;
5069
5070         case 3:
5071           offset4 = offset3 + 20;
5072           proto_tree_add_text(rsvp_object_tree, tvb, offset3, 20, "Source Transport Network addr: %s",
5073                               tvb_bytes_to_str(tvb, offset3, 20));
5074           proto_item_append_text(ti, "Src: %s. ", tvb_bytes_to_str(tvb, offset3, 20));
5075           break;
5076
5077         case 4:
5078           offset4 = offset3 + 6;
5079           proto_tree_add_text(rsvp_object_tree, tvb, offset3, 6, "Source Transport Network addr: %s",
5080                               tvb_bytes_to_str(tvb, offset3, 6));
5081           proto_item_append_text(ti, "Src: %s. ", tvb_bytes_to_str(tvb, offset3, 6));
5082           break;
5083
5084         case 0x7F:
5085           offset4 = offset3 + len;
5086           proto_tree_add_text(rsvp_object_tree, tvb, offset3, len, "Source Transport Network addr: %s",
5087                               tvb_bytes_to_str(tvb, offset3, len));
5088           proto_item_append_text(ti, "Src: %s. ", tvb_bytes_to_str(tvb, offset3, len));
5089           break;
5090
5091         default:
5092           offset4 = offset3 + len;
5093           proto_tree_add_text(rsvp_object_tree, tvb, offset3, len, "Unknown Transport Network type: %d",
5094                               type);
5095         }
5096
5097         proto_tree_add_text(rsvp_object_tree, tvb, offset4, 8, "Local Identifier: %s",
5098                             tvb_bytes_to_str(tvb, offset4, 8));
5099         proto_item_append_text(ti, "Local ID: %s. ", tvb_bytes_to_str(tvb, offset4, 8));
5100         break;
5101
5102     default:
5103         proto_item_append_text(ti, " Unknown");
5104         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
5105                             "C-type: Unknown (%u)", type);
5106         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
5107                             "Data (%d bytes)", obj_length - 4);
5108         break;
5109     }
5110 }
5111
5112 /*------------------------------------------------------------------------------
5113  * RESTART CAPABILITY
5114  *------------------------------------------------------------------------------*/
5115 static void
5116 dissect_rsvp_restart_cap (proto_tree *ti, proto_tree *rsvp_object_tree,
5117                           tvbuff_t *tvb,
5118                           int offset, int obj_length,
5119                           int class _U_, int type)
5120 {
5121     int offset2 = offset + 4;
5122
5123     proto_item_set_text(ti, "RESTART CAPABILITY: ");
5124     switch(type) {
5125     case 1:
5126         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
5127                             "C-type: 1");
5128         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4,
5129                             "Restart Time: %d ms",
5130                             tvb_get_ntohl(tvb, offset2));
5131         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
5132                             "Recovery Time: %d ms",
5133                             tvb_get_ntohl(tvb, offset2+4));
5134         proto_item_append_text(ti, "Restart Time: %d ms. Recovery Time: %d ms.",
5135                             tvb_get_ntohl(tvb, offset2), tvb_get_ntohl(tvb, offset2+4));
5136         break;
5137
5138     default:
5139         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
5140                             "C-type: Unknown (%u)",
5141                             type);
5142         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
5143                             "Data (%d bytes)", obj_length - 4);
5144         break;
5145     }
5146 }
5147
5148 /*------------------------------------------------------------------------------
5149  * PROTECTION INFORMATION
5150  *------------------------------------------------------------------------------*/
5151 static void
5152 dissect_rsvp_protection_info (proto_tree *ti, proto_tree *rsvp_object_tree,
5153                               tvbuff_t *tvb,
5154                               int offset, int obj_length,
5155                               int class _U_, int type)
5156 {
5157     guint8 flags, flag;
5158     proto_tree *ti2, *rsvp_pi_flags_tree;
5159     int offset2 = offset + 4;
5160
5161     proto_item_set_text(ti, "PROTECTION_INFO: ");
5162     switch(type) {
5163     case 1:
5164         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
5165                             "C-type: 1 - Protection");
5166         flag = tvb_get_guint8(tvb, offset2);
5167         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
5168                             "Secondary LSP: %s",
5169                             decode_boolean_bitfield(flag, 0x80, 8, "Yes", "No"));
5170
5171         flags = tvb_get_guint8(tvb, offset2+3);
5172         ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2+3, 1,
5173                                   "Link Flags: 0x%02x", flags);
5174         rsvp_pi_flags_tree = proto_item_add_subtree(ti2,
5175                                                     TREE(TT_PROTECTION_INFO));
5176         proto_tree_add_text(rsvp_pi_flags_tree, tvb, offset2+3, 1,
5177                             decode_boolean_bitfield(flags, 0x01, 8,
5178                                                     "Extra Traffic desired",
5179                                                     "Extra Traffic not desired"));
5180         proto_tree_add_text(rsvp_pi_flags_tree, tvb, offset2+3, 1,
5181                             decode_boolean_bitfield(flags, 0x02, 8,
5182                                                     "Unprotected desired",
5183                                                     "Unprotected not desired"));
5184         proto_tree_add_text(rsvp_pi_flags_tree, tvb, offset2+3, 1,
5185                             decode_boolean_bitfield(flags, 0x04, 8,
5186                                                     "Shared desired",
5187                                                     "Shared not desired"));
5188         proto_tree_add_text(rsvp_pi_flags_tree, tvb, offset2+3, 1,
5189                             decode_boolean_bitfield(flags, 0x08, 8,
5190                                                     "Dedicated 1:1 desired",
5191                                                     "Dedicated 1:1 not desired"));
5192         proto_tree_add_text(rsvp_pi_flags_tree, tvb, offset2+3, 1,
5193                             decode_boolean_bitfield(flags, 0x10, 8,
5194                                                     "Dedicated 1+1 desired",
5195                                                     "Dedicated 1+1 not desired"));
5196         proto_tree_add_text(rsvp_pi_flags_tree, tvb, offset2+3, 1,
5197                             decode_boolean_bitfield(flags, 0x20, 8,
5198                                                     "Enhanced desired",
5199                                                     "Enhanced not desired"));
5200         proto_item_append_text(ti, "%s%s%s%s%s%s%s.",
5201                                flag  &0x80 ? "SecondaryLSP " : "",
5202                                flags &0x01 ? "ExtraTraffic " : "",
5203                                flags &0x02 ? "Unprotected " : "",
5204                                flags &0x04 ? "Shared " : "",
5205                                flags &0x08 ? "Dedicated1:1 " : "",
5206                                flags &0x10 ? "Dedicated1+1 " : "",
5207                                flags &0x20 ? "Enhanced " : "");
5208         break;
5209
5210     default:
5211         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
5212                             "C-type: Unknown (%u)",
5213                             type);
5214         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
5215                             "Data (%d bytes)", obj_length - 4);
5216         break;
5217     }
5218 }
5219
5220 /*------------------------------------------------------------------------------
5221  * FAST REROUTE
5222  *------------------------------------------------------------------------------*/
5223 static void
5224 dissect_rsvp_fast_reroute (proto_tree *ti, proto_tree *rsvp_object_tree,
5225                            tvbuff_t *tvb,
5226                            int offset, int obj_length,
5227                            int class _U_, int type)
5228 {
5229     guint8 flags;
5230     proto_tree *ti2, *rsvp_frr_flags_tree;
5231
5232     proto_item_set_text(ti, "FAST_REROUTE: ");
5233     switch(type) {
5234     case 1:
5235     case 7:
5236         if ((type==1 && obj_length!=24) || (type==7 && obj_length!=20)) {
5237             proto_tree_add_text(rsvp_object_tree, tvb, offset, obj_length,
5238                                 "<<<Invalid length: cannot decode>>>");
5239             proto_item_append_text(ti, "Invalid length");
5240             break;
5241         }
5242         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
5243                             "C-type: %u", type);
5244         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, 1,
5245                             "Setup Priority: %d", tvb_get_guint8(tvb, offset+4));
5246         proto_tree_add_text(rsvp_object_tree, tvb, offset+5, 1,
5247                             "Hold Priority: %d", tvb_get_guint8(tvb, offset+5));
5248         proto_tree_add_text(rsvp_object_tree, tvb, offset+6, 1,
5249                             "Hop Limit: %d", tvb_get_guint8(tvb, offset+6));
5250
5251         flags = tvb_get_guint8(tvb, offset+7);
5252         ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset+7, 1,
5253                                   "Flags: 0x%02x", flags);
5254         rsvp_frr_flags_tree = proto_item_add_subtree(ti2,
5255                                                      TREE(TT_FAST_REROUTE_FLAGS));
5256         proto_tree_add_text(rsvp_frr_flags_tree, tvb, offset+7, 1,
5257                             decode_boolean_bitfield(flags, 0x01, 8,
5258                                                     "One-to-One Backup desired",
5259                                                     "One-to-One Backup not desired"));
5260         proto_tree_add_text(rsvp_frr_flags_tree, tvb, offset+7, 1,
5261                             decode_boolean_bitfield(flags, 0x02, 8,
5262                                                     "Facility Backup desired",
5263                                                     "Facility Backup not desired"));
5264         proto_tree_add_text(rsvp_object_tree, tvb, offset+8, 4,
5265                             "Bandwidth: %.10g", tvb_get_ntohieee_float(tvb, offset+8));
5266         proto_tree_add_text(rsvp_object_tree, tvb, offset+12, 4,
5267                             "Include-Any: 0x%0x", tvb_get_ntohl(tvb, offset+12));
5268         proto_tree_add_text(rsvp_object_tree, tvb, offset+16, 4,
5269                             "Exclude-Any: 0x%0x", tvb_get_ntohl(tvb, offset+16));
5270         if (type==1) {
5271             proto_tree_add_text(rsvp_object_tree, tvb, offset+20, 4,
5272                                 "Include-All: 0x%0x", tvb_get_ntohl(tvb, offset+20));
5273         }
5274
5275         proto_item_append_text(ti, "%s%s",
5276                                flags &0x01 ? "One-to-One Backup, " : "",
5277                                flags &0x02 ? "Facility Backup" : "");
5278         break;
5279
5280     default:
5281         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
5282                             "C-type: Unknown (%u)",
5283                             type);
5284         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, obj_length - 4,
5285                             "Data (%d bytes)", obj_length - 4);
5286         break;
5287     }
5288 }
5289
5290 /*------------------------------------------------------------------------------
5291  * DETOUR
5292  *------------------------------------------------------------------------------*/
5293 static void
5294 dissect_rsvp_detour (proto_tree *ti, proto_tree *rsvp_object_tree,
5295                      tvbuff_t *tvb,
5296                      int offset, int obj_length,
5297                      int class _U_, int type)
5298 {
5299     int remaining_length, count;
5300     int iter;
5301
5302     proto_item_set_text(ti, "DETOUR: ");
5303     switch(type) {
5304     case 7:
5305         iter = 0;
5306         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
5307                             "C-type: %u", type);
5308         for (remaining_length = obj_length - 4, count = 1;
5309              remaining_length > 0; remaining_length -= 8, count++) {
5310             if (remaining_length < 8) {
5311                 proto_tree_add_text(rsvp_object_tree, tvb, offset+remaining_length,
5312                                     obj_length-remaining_length,
5313                                     "<<<Invalid length: cannot decode>>>");
5314                 proto_item_append_text(ti, "Invalid length");
5315                 break;
5316             }
5317             iter++;
5318             proto_tree_add_text(rsvp_object_tree, tvb, offset+(4*iter), 4,
5319                                 "PLR ID %d: %s", count,
5320                                 ip_to_str(tvb_get_ptr(tvb, offset+(4*iter), 4)));
5321             iter++;
5322             proto_tree_add_text(rsvp_object_tree, tvb, offset+(4*iter), 4,
5323                                 "Avoid Node ID %d: %s", count,
5324                                 ip_to_str(tvb_get_ptr(tvb, offset+(4*iter), 4)));
5325         }
5326         break;
5327
5328     default:
5329         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
5330                             "C-type: Unknown (%u)",
5331                             type);
5332         proto_tree_add_text(rsvp_object_tree, tvb, offset+4, obj_length - 4,
5333                             "Data (%d bytes)", obj_length - 4);
5334         break;
5335     }
5336 }
5337
5338 /*------------------------------------------------------------------------------
5339  * DIFFSERV
5340  *------------------------------------------------------------------------------*/
5341 static void
5342 dissect_rsvp_diffserv (proto_tree *ti, proto_tree *rsvp_object_tree,
5343                        tvbuff_t *tvb,
5344                        int offset, int obj_length,
5345                        int class _U_, int type)
5346 {
5347     int mapnb, count;
5348     int *hfindexes[] = {
5349         &rsvp_filter[RSVPF_DIFFSERV_MAP],
5350         &rsvp_filter[RSVPF_DIFFSERV_MAP_EXP],
5351         &rsvp_filter[RSVPF_DIFFSERV_PHBID],
5352         &rsvp_filter[RSVPF_DIFFSERV_PHBID_DSCP],
5353         &rsvp_filter[RSVPF_DIFFSERV_PHBID_CODE],
5354         &rsvp_filter[RSVPF_DIFFSERV_PHBID_BIT14],
5355         &rsvp_filter[RSVPF_DIFFSERV_PHBID_BIT15]
5356     };
5357     gint *etts[] = {
5358         &TREE(TT_DIFFSERV_MAP),
5359         &TREE(TT_DIFFSERV_MAP_PHBID)
5360     };
5361
5362     proto_item_set_text(ti, "DIFFSERV: ");
5363     offset += 3;
5364     switch (type) {
5365     case 1:
5366         proto_tree_add_text(rsvp_object_tree, tvb, offset, 1,
5367                             "C-type: 1 - E-LSP");
5368         proto_tree_add_uint(rsvp_object_tree, rsvp_filter[RSVPF_DIFFSERV_MAPNB],
5369                             tvb, offset + 4, 1,
5370                             mapnb = tvb_get_guint8(tvb, offset + 4) & 15);
5371         proto_item_append_text(ti, "E-LSP, %u MAP%s", mapnb,
5372                                (mapnb == 0) ? "" : "s");
5373         offset += 5;
5374
5375         for (count = 0; count < mapnb; count++) {
5376             dissect_diffserv_mpls_common(tvb, rsvp_object_tree, type,
5377                                          offset, hfindexes, etts);
5378             offset += 4;
5379         }
5380         break;
5381     case 2:
5382         proto_item_append_text(ti, "L-LSP");
5383         proto_tree_add_text(rsvp_object_tree, tvb, offset, 1,
5384                             "C-type: 2 - L-LSP");
5385         dissect_diffserv_mpls_common(tvb, rsvp_object_tree, type,
5386                                      offset + 3, hfindexes, etts);
5387         break;
5388     default:
5389         proto_tree_add_text(rsvp_object_tree, tvb, offset, 1,
5390                             "C-type: Unknown (%u)", type);
5391         proto_tree_add_text(rsvp_object_tree, tvb, offset + 1, obj_length - 4,
5392                             "Data (%d bytes)", obj_length - 4);
5393     }
5394 }
5395
5396 /*------------------------------------------------------------------------------
5397  * CLASSTYPE
5398  *------------------------------------------------------------------------------*/
5399 static void
5400 dissect_rsvp_diffserv_aware_te(proto_tree *ti, proto_tree *rsvp_object_tree,
5401                                tvbuff_t *tvb,
5402                                int offset, int obj_length,
5403                                int class _U_, int type)
5404 {
5405     proto_item *hidden_item;
5406     int offset2 = offset + 4;
5407     guint8 ct = 0;
5408
5409     hidden_item = proto_tree_add_item(rsvp_object_tree,
5410                                rsvp_filter[RSVPF_DSTE],
5411                                tvb, offset, 8, FALSE);
5412     PROTO_ITEM_SET_HIDDEN(hidden_item);
5413
5414     switch(type) {
5415     case 1:
5416         ct = tvb_get_guint8(tvb, offset2+3);
5417         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, "C-type: 1");
5418         proto_tree_add_item(rsvp_object_tree,
5419                             rsvp_filter[RSVPF_DSTE_CLASSTYPE],
5420                             tvb, offset2+3, 1, FALSE);
5421         proto_item_set_text(ti, "CLASSTYPE: CT %u", ct);
5422         break;
5423     default:
5424         proto_item_set_text(ti, "CLASSTYPE: (Unknown C-type)");
5425         proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
5426                             "C-type: Unknown (%u)", type);
5427         proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
5428                             "Data (%d bytes)", obj_length - 4);
5429         break;
5430     }
5431 }
5432
5433 /*------------------------------------------------------------------------------
5434  * Dissect a single RSVP message in a tree
5435  *------------------------------------------------------------------------------*/
5436 static void
5437 dissect_rsvp_msg_tree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5438                       int tree_mode, rsvp_conversation_info *rsvph)
5439 {
5440     proto_tree *rsvp_tree = NULL;
5441     proto_tree *rsvp_header_tree;
5442     proto_tree *rsvp_object_tree;
5443     proto_tree *ti;
5444     proto_item *hidden_item;
5445     guint16 cksum, computed_cksum;
5446     vec_t cksum_vec[1];
5447     int offset = 0;
5448     int len;
5449     guint8 ver_flags;
5450     guint8 message_type;
5451     int session_off, tempfilt_off;
5452     int msg_length;
5453     int obj_length;
5454     int offset2;
5455
5456     offset = 0;
5457     len = 0;
5458     ver_flags = tvb_get_guint8(tvb, 0);
5459     msg_length = tvb_get_ntohs(tvb, 6);
5460     message_type = tvb_get_guint8(tvb, 1);
5461
5462     ti = proto_tree_add_item(tree, proto_rsvp, tvb, offset, msg_length,
5463                              FALSE);
5464     rsvp_tree = proto_item_add_subtree(ti, tree_mode);
5465     if (pinfo->ipproto == IP_PROTO_RSVPE2EI)
5466         proto_item_append_text(rsvp_tree, " (E2E-IGNORE)");
5467     proto_item_append_text(rsvp_tree, ": ");
5468     proto_item_append_text(rsvp_tree, val_to_str(message_type, message_type_vals,
5469                                                  "Unknown (%u). "));
5470     find_rsvp_session_tempfilt(tvb, 0, &session_off, &tempfilt_off);
5471     if (session_off)
5472         proto_item_append_text(rsvp_tree, summary_session(tvb, session_off));
5473     if (tempfilt_off)
5474         proto_item_append_text(rsvp_tree, summary_template(tvb, tempfilt_off));
5475
5476     ti = proto_tree_add_text(rsvp_tree, tvb, offset, 8, "RSVP Header. %s",
5477                              val_to_str(message_type, message_type_vals,
5478                                         "Unknown Message (%u). "));
5479     if (pinfo->ipproto == IP_PROTO_RSVPE2EI)
5480         proto_item_append_text(ti, " (E2E-IGNORE)");
5481     rsvp_header_tree = proto_item_add_subtree(ti, TREE(TT_HDR));
5482
5483     proto_tree_add_text(rsvp_header_tree, tvb, offset, 1, "RSVP Version: %u",
5484                         (ver_flags & 0xf0)>>4);
5485     proto_tree_add_text(rsvp_header_tree, tvb, offset, 1, "Flags: %02x",
5486                         ver_flags & 0xf);
5487     proto_tree_add_uint(rsvp_header_tree, rsvp_filter[RSVPF_MSG], tvb,
5488                         offset+1, 1, message_type);
5489     switch (RSVPF_MSG + message_type) {
5490
5491     case RSVPF_PATH:
5492     case RSVPF_RESV:
5493     case RSVPF_PATHERR:
5494     case RSVPF_RESVERR:
5495     case RSVPF_PATHTEAR:
5496     case RSVPF_RESVTEAR:
5497     case RSVPF_RCONFIRM:
5498     case RSVPF_RTEARCONFIRM:
5499     case RSVPF_BUNDLE:
5500     case RSVPF_ACK:
5501     case RSVPF_SREFRESH:
5502     case RSVPF_HELLO:
5503     case RSVPF_NOTIFY:
5504         hidden_item = proto_tree_add_boolean(rsvp_header_tree, rsvp_filter[RSVPF_MSG + message_type], tvb,
5505                                       offset+1, 1, 1);
5506         PROTO_ITEM_SET_HIDDEN(hidden_item);
5507         break;
5508
5509     default:
5510         proto_tree_add_protocol_format(rsvp_header_tree, proto_malformed, tvb, offset+1, 1,
5511                                        "Invalid message type: %u", message_type);
5512         return;
5513     }
5514
5515     cksum = tvb_get_ntohs(tvb, offset+2);
5516     if (!pinfo->fragmented && (int) tvb_length(tvb) >= msg_length) {
5517         /* The packet isn't part of a fragmented datagram and isn't
5518            truncated, so we can checksum it. */
5519         cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, msg_length);
5520         cksum_vec[0].len = msg_length;
5521         computed_cksum = in_cksum(&cksum_vec[0], 1);
5522         if (computed_cksum == 0) {
5523             proto_tree_add_text(rsvp_header_tree, tvb, offset+2, 2,
5524                                 "Message Checksum: 0x%04x [correct]",
5525                                 cksum);
5526         } else {
5527             proto_tree_add_text(rsvp_header_tree, tvb, offset+2, 2,
5528                                 "Message Checksum: 0x%04x [incorrect, should be 0x%04x]",
5529                                 cksum,
5530                                 in_cksum_shouldbe(cksum, computed_cksum));
5531         }
5532     } else {
5533         proto_tree_add_text(rsvp_header_tree, tvb, offset+2, 2,
5534                             "Message Checksum: 0x%04x",
5535                             cksum);
5536     }
5537     proto_tree_add_text(rsvp_header_tree, tvb, offset+4, 1,
5538                         "Sending TTL: %u",
5539                         tvb_get_guint8(tvb, offset+4));
5540     proto_tree_add_text(rsvp_header_tree, tvb, offset+6, 2,
5541                         "Message length: %u", msg_length);
5542
5543     offset = 8;
5544     len = 8;
5545
5546     if (message_type == RSVP_MSG_BUNDLE) {
5547         /* Bundle message. Dissect component messages */
5548         if (rsvp_bundle_dissect) {
5549             int len = 8;
5550             while (len < msg_length) {
5551                 gint sub_len;
5552                 tvbuff_t *tvb_sub;
5553                 sub_len = tvb_get_ntohs(tvb, len+6);
5554                 tvb_sub = tvb_new_subset(tvb, len, sub_len, sub_len);
5555                 dissect_rsvp_msg_tree(tvb_sub, pinfo, rsvp_tree, TREE(TT_BUNDLE_COMPMSG), rsvph);
5556                 len += sub_len;
5557             }
5558         } else {
5559             proto_tree_add_text(rsvp_tree, tvb, offset, msg_length - len,
5560                                 "Bundle Component Messages Not Dissected");
5561         }
5562         return;
5563     }
5564
5565     while (len < msg_length) {
5566         guint8 class;
5567         guint8 type;
5568
5569         obj_length = tvb_get_ntohs(tvb, offset);
5570         class = tvb_get_guint8(tvb, offset+2);
5571         type = tvb_get_guint8(tvb, offset+3);
5572         ti = proto_tree_add_item(rsvp_tree, rsvp_filter[rsvp_class_to_filter_num(class)],
5573                                  tvb, offset, obj_length, FALSE);
5574         rsvp_object_tree = proto_item_add_subtree(ti, TREE(rsvp_class_to_tree_type(class)));
5575         if (obj_length < 4) {
5576             proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
5577                                 "Length: %u (bogus, must be >= 4)", obj_length);
5578             break;
5579         }
5580         proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
5581                             "Length: %u", obj_length);
5582         proto_tree_add_uint(rsvp_object_tree, rsvp_filter[RSVPF_OBJECT], tvb,
5583                             offset+2, 1, class);
5584
5585         offset2 = offset+4;
5586
5587         switch(class) {
5588
5589         case RSVP_CLASS_SESSION:
5590             dissect_rsvp_session(ti, rsvp_object_tree, tvb, offset, obj_length, class, type, rsvph);
5591             break;
5592
5593         case RSVP_CLASS_HOP:
5594             dissect_rsvp_hop(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5595             break;
5596
5597         case RSVP_CLASS_TIME_VALUES:
5598             dissect_rsvp_time_values(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5599             break;
5600
5601         case RSVP_CLASS_ERROR:
5602             dissect_rsvp_error(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5603             break;
5604
5605         case RSVP_CLASS_SCOPE:
5606             dissect_rsvp_scope(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5607             break;
5608
5609         case RSVP_CLASS_STYLE:
5610             dissect_rsvp_style(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5611             break;
5612
5613         case RSVP_CLASS_CONFIRM:
5614             dissect_rsvp_confirm(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5615             break;
5616
5617         case RSVP_CLASS_SENDER_TEMPLATE:
5618         case RSVP_CLASS_FILTER_SPEC:
5619             dissect_rsvp_template_filter(ti, rsvp_object_tree, tvb, offset, obj_length, class, type, rsvph);
5620             break;
5621
5622         case RSVP_CLASS_SENDER_TSPEC:
5623             dissect_rsvp_tspec(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5624             break;
5625
5626         case RSVP_CLASS_FLOWSPEC:
5627             dissect_rsvp_flowspec(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5628             break;
5629
5630         case RSVP_CLASS_ADSPEC:
5631             dissect_rsvp_adspec(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5632             break;
5633
5634         case RSVP_CLASS_INTEGRITY:
5635             dissect_rsvp_integrity(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5636             break;
5637
5638         case RSVP_CLASS_POLICY:
5639             dissect_rsvp_policy(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5640             break;
5641
5642         case RSVP_CLASS_LABEL_REQUEST:
5643             dissect_rsvp_label_request(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5644             break;
5645
5646         case RSVP_CLASS_RECOVERY_LABEL:
5647         case RSVP_CLASS_UPSTREAM_LABEL:
5648         case RSVP_CLASS_SUGGESTED_LABEL:
5649         case RSVP_CLASS_LABEL:
5650             dissect_rsvp_label(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5651             break;
5652
5653         case RSVP_CLASS_LABEL_SET:
5654             dissect_rsvp_label_set(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5655             break;
5656
5657         case RSVP_CLASS_SESSION_ATTRIBUTE:
5658             dissect_rsvp_session_attribute(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5659             break;
5660
5661         case RSVP_CLASS_EXPLICIT_ROUTE:
5662             dissect_rsvp_explicit_route(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5663             break;
5664
5665         case RSVP_CLASS_RECORD_ROUTE:
5666             dissect_rsvp_record_route(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5667             break;
5668
5669         case RSVP_CLASS_MESSAGE_ID:
5670             dissect_rsvp_message_id(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5671             break;
5672
5673         case RSVP_CLASS_MESSAGE_ID_ACK:
5674             dissect_rsvp_message_id_ack(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5675             break;
5676
5677         case RSVP_CLASS_MESSAGE_ID_LIST:
5678             dissect_rsvp_message_id_list(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5679             break;
5680
5681         case RSVP_CLASS_HELLO:
5682             dissect_rsvp_hello(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5683             break;
5684
5685         case RSVP_CLASS_DCLASS:
5686             dissect_rsvp_dclass(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5687             break;
5688
5689         case RSVP_CLASS_ADMIN_STATUS:
5690             dissect_rsvp_admin_status(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5691             break;
5692
5693         case RSVP_CLASS_ASSOCIATION:
5694             dissect_rsvp_association(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5695             break;
5696
5697         case RSVP_CLASS_LSP_TUNNEL_IF_ID:
5698             dissect_rsvp_lsp_tunnel_if_id(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5699             break;
5700
5701         case RSVP_CLASS_NOTIFY_REQUEST:
5702             dissect_rsvp_notify_request(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5703             break;
5704
5705         case RSVP_CLASS_GENERALIZED_UNI:
5706             dissect_rsvp_gen_uni(ti, rsvp_object_tree, tvb, offset, obj_length, class, type, rsvph);
5707             break;
5708
5709         case RSVP_CLASS_CALL_ID:
5710             dissect_rsvp_call_id(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5711             break;
5712
5713         case RSVP_CLASS_RESTART_CAP:
5714             dissect_rsvp_restart_cap(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5715             break;
5716
5717         case RSVP_CLASS_PROTECTION:
5718             dissect_rsvp_protection_info(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5719             break;
5720
5721         case RSVP_CLASS_FAST_REROUTE:
5722             dissect_rsvp_fast_reroute(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5723             break;
5724
5725         case RSVP_CLASS_DETOUR:
5726             dissect_rsvp_detour(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5727             break;
5728
5729         case RSVP_CLASS_DIFFSERV:
5730             dissect_rsvp_diffserv(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5731             break;
5732
5733         case RSVP_CLASS_CLASSTYPE:
5734             dissect_rsvp_diffserv_aware_te(ti, rsvp_object_tree, tvb, offset, obj_length, class, type);
5735             break;
5736
5737         case RSVP_CLASS_NULL:
5738         default:
5739             proto_tree_add_text(rsvp_object_tree, tvb, offset2, obj_length - 4,
5740                                 "Data (%d bytes)", obj_length - 4);
5741             break;
5742         }
5743
5744         offset += obj_length;
5745         len += obj_length;
5746     }
5747 }
5748
5749 /*------------------------------------------------------------------------------
5750  * The main loop
5751  *------------------------------------------------------------------------------*/
5752 static void
5753 dissect_rsvp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
5754 {
5755     guint8 ver_flags;
5756     guint8 message_type;
5757     int msg_length;
5758     int session_off, tempfilt_off;
5759     rsvp_conversation_info *rsvph;
5760
5761
5762     conversation_t *conversation;
5763     struct rsvp_request_key request_key, *new_request_key;
5764     struct rsvp_request_val *request_val = NULL;
5765
5766     if (check_col(pinfo->cinfo, COL_PROTOCOL))
5767         col_set_str(pinfo->cinfo, COL_PROTOCOL,
5768                     (pinfo->ipproto == IP_PROTO_RSVPE2EI) ? "RSVP-E2EI" : "RSVP");
5769     if (check_col(pinfo->cinfo, COL_INFO))
5770         col_clear(pinfo->cinfo, COL_INFO);
5771
5772     ver_flags = tvb_get_guint8(tvb, 0);
5773     message_type = tvb_get_guint8(tvb, 1);
5774     msg_length = tvb_get_ntohs(tvb, 6);
5775
5776     rsvph = ep_alloc(sizeof(rsvp_conversation_info));
5777     rsvph->session_type = 0;
5778
5779     /* Copy over the source and destination addresses from the pinfo strucutre */
5780     SET_ADDRESS(&rsvph->source, pinfo->src.type, pinfo->src.len, pinfo->src.data);
5781     SET_ADDRESS(&rsvph->destination, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data);
5782
5783     if (check_col(pinfo->cinfo, COL_INFO)) {
5784         col_add_str(pinfo->cinfo, COL_INFO,
5785             val_to_str(message_type, message_type_vals, "Unknown (%u). "));
5786         find_rsvp_session_tempfilt(tvb, 0, &session_off, &tempfilt_off);
5787         if (session_off)
5788             col_append_str(pinfo->cinfo, COL_INFO, summary_session(tvb, session_off));
5789         if (tempfilt_off)
5790             col_append_str(pinfo->cinfo, COL_INFO, summary_template(tvb, tempfilt_off));
5791     }
5792
5793     if (check_col(pinfo->cinfo, COL_INFO)) {
5794         col_add_str(pinfo->cinfo, COL_INFO,
5795                     val_to_str(message_type, message_type_vals, "Unknown (%u). "));
5796         if (message_type == RSVP_MSG_BUNDLE) {
5797             col_set_str(pinfo->cinfo, COL_INFO,
5798                         rsvp_bundle_dissect ?
5799                         "Component Messages Dissected" :
5800                         "Component Messages Not Dissected");
5801         } else {
5802             find_rsvp_session_tempfilt(tvb, 0, &session_off, &tempfilt_off);
5803             if (session_off)
5804                 col_append_str(pinfo->cinfo, COL_INFO, summary_session(tvb, session_off));
5805             if (tempfilt_off)
5806                 col_append_str(pinfo->cinfo, COL_INFO, summary_template(tvb, tempfilt_off));
5807         }
5808     }
5809
5810     if (tree) {
5811         dissect_rsvp_msg_tree(tvb, pinfo, tree, TREE(TT_RSVP), rsvph);
5812     }
5813
5814     /* Find out what conversation this packet is part of. */
5815     conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
5816                                      pinfo->ptype, pinfo->srcport,
5817                                      pinfo->destport, 0);
5818
5819     if (conversation == NULL) {
5820         /* Not part of any conversation; create a new one. */
5821         conversation =
5822             conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst,
5823                              pinfo->ptype, pinfo->srcport,
5824                              pinfo->destport, 0);
5825     }
5826
5827     /* Now build the request key */
5828     request_key.conversation = conversation->index;
5829     request_key.session_type = rsvph->session_type;
5830
5831     switch (request_key.session_type) {
5832     case RSVP_SESSION_TYPE_IPV4:
5833         SET_ADDRESS(&request_key.u.session_ipv4.destination,
5834                     rsvph->destination.type, rsvph->destination.len,
5835                     rsvph->destination.data);
5836         request_key.u.session_ipv4.protocol = rsvph->protocol;
5837         request_key.u.session_ipv4.udp_dest_port = rsvph->udp_dest_port;
5838         break;
5839
5840     case RSVP_SESSION_TYPE_IPV6:
5841         /* Not supported yet */
5842         break;
5843
5844     case RSVP_SESSION_TYPE_IPV4_LSP:
5845         SET_ADDRESS(&request_key.u.session_ipv4_lsp.destination,
5846                     rsvph->destination.type, rsvph->destination.len,
5847                     rsvph->destination.data);
5848         request_key.u.session_ipv4_lsp.udp_dest_port = rsvph->udp_dest_port;
5849         request_key.u.session_ipv4_lsp.ext_tunnel_id = rsvph->ext_tunnel_id;
5850         break;
5851
5852     case RSVP_SESSION_TYPE_AGGREGATE_IPV4:
5853         SET_ADDRESS(&request_key.u.session_agg_ipv4.destination,
5854                     rsvph->destination.type, rsvph->destination.len,
5855                     rsvph->destination.data);
5856         request_key.u.session_agg_ipv4.dscp = rsvph->dscp;
5857         break;
5858
5859     case RSVP_SESSION_TYPE_IPV4_UNI:
5860         SET_ADDRESS(&request_key.u.session_ipv4_uni.destination,
5861                     rsvph->destination.type, rsvph->destination.len,
5862                     rsvph->destination.data);
5863         request_key.u.session_ipv4_uni.udp_dest_port = rsvph->udp_dest_port;
5864         request_key.u.session_ipv4_uni.ext_tunnel_id = rsvph->ext_tunnel_id;
5865         break;
5866
5867     case RSVP_SESSION_TYPE_IPV4_E_NNI:
5868         SET_ADDRESS(&request_key.u.session_ipv4_enni.destination,
5869                     rsvph->destination.type, rsvph->destination.len,
5870                     rsvph->destination.data);
5871         request_key.u.session_ipv4_enni.udp_dest_port = rsvph->udp_dest_port;
5872         request_key.u.session_ipv4_enni.ext_tunnel_id = rsvph->ext_tunnel_id;
5873         break;
5874     default:
5875         /* This should never happen. */
5876         if (tree) {
5877             proto_tree_add_text(tree, tvb, 0, 0, "Unknown session type");
5878         }
5879         break;
5880     }
5881
5882     SET_ADDRESS(&request_key.source_info.source,
5883                 rsvph->source.type, rsvph->source.len, rsvph->source.data);
5884     request_key.source_info.udp_source_port = rsvph->udp_source_port;
5885
5886     /* See if a request with this key already exists */
5887     request_val =
5888         (struct rsvp_request_val *) g_hash_table_lookup(rsvp_request_hash,
5889                                                         &request_key);
5890
5891     /* If not, insert the new request key into the hash table */
5892     if (!request_val) {
5893         new_request_key = se_alloc(sizeof(struct rsvp_request_key));
5894         *new_request_key = request_key;
5895
5896         request_val = se_alloc(sizeof(struct rsvp_request_val));
5897         request_val->value = conversation->index;
5898
5899         g_hash_table_insert(rsvp_request_hash, new_request_key, request_val);
5900     }
5901
5902     tap_queue_packet(rsvp_tap, pinfo, rsvph);
5903 }
5904
5905 static void
5906 register_rsvp_prefs (void)
5907 {
5908     module_t *rsvp_module;
5909
5910     rsvp_module = prefs_register_protocol(proto_rsvp, NULL);
5911     prefs_register_bool_preference(
5912         rsvp_module, "process_bundle",
5913         "Dissect sub-messages in BUNDLE message",
5914         "Specifies whether Wireshark should decode and display sub-messages within BUNDLE messages",
5915         &rsvp_bundle_dissect);
5916 }
5917
5918 void
5919 proto_register_rsvp(void)
5920 {
5921     gint i;
5922
5923     /* Build the tree array */
5924     for (i=0; i<TT_MAX; i++)
5925         ett_tree[i] = &(ett_treelist[i]);
5926
5927     proto_rsvp = proto_register_protocol("Resource ReserVation Protocol (RSVP)",
5928                                          "RSVP", "rsvp");
5929     proto_register_field_array(proto_rsvp, rsvpf_info, array_length(rsvpf_info));
5930     proto_register_subtree_array(ett_tree, array_length(ett_tree));
5931     register_rsvp_prefs();
5932
5933     rsvp_dissector_table = register_dissector_table("rsvp.proto", "RSVP Protocol",
5934                                                     FT_UINT8, BASE_DEC);
5935
5936     /* Initialization routine for RSVP conversations */
5937     register_init_routine(&rsvp_init_protocol);
5938 }
5939
5940 void
5941 proto_reg_handoff_rsvp(void)
5942 {
5943         dissector_handle_t rsvp_handle;
5944
5945         rsvp_handle = create_dissector_handle(dissect_rsvp, proto_rsvp);
5946         dissector_add("ip.proto", IP_PROTO_RSVP, rsvp_handle);
5947         dissector_add("ip.proto", IP_PROTO_RSVPE2EI, rsvp_handle);
5948         dissector_add("udp.port", UDP_PORT_PRSVP, rsvp_handle);
5949         data_handle = find_dissector("data");
5950         rsvp_tap = register_tap("rsvp");
5951 }