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