FT_UINTn and FT_INTn fields must always have a base selected for them;
[obnox/wireshark/wip.git] / packet-rsvp.c
1 /* packet-rsvp.c
2  * Routines for RSVP packet disassembly
3  *
4  * (c) Copyright Ashok Narayanan <ashokn@cisco.com>
5  *
6  * $Id: packet-rsvp.c,v 1.37 2001/04/19 22:55:31 guy Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@zing.org>
10  * Copyright 1998 Gerald Combs
11  * 
12  * 
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  * 
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  * 
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26  */
27
28 /*
29  * NOTES
30  *
31  * This module defines routines to disassemble RSVP packets, as defined in
32  * RFC 2205. All objects from RC2205 are supported, in IPv4 and IPv6 mode.
33  * In addition, the Integrated Services traffic specification objects
34  * defined in RFC2210 are also supported. 
35  *
36  * IPv6 support is not completely tested
37  *
38  * Mar 3, 2000: Added support for MPLS/TE objects, as defined in 
39  * <draft-ietf-mpls-rsvp-lsp-tunnel-04.txt>
40  */
41
42  
43 #ifdef HAVE_CONFIG_H
44 # include "config.h"
45 #endif
46
47 #include <stdio.h>
48
49 #ifdef HAVE_UNISTD_H
50 #include <unistd.h>
51 #endif
52
53 #include <stdlib.h>
54 #include <string.h>
55
56 #ifdef HAVE_SYS_TYPES_H
57 # include <sys/types.h>
58 #endif
59
60 #ifdef HAVE_NETINET_IN_H
61 # include <netinet/in.h>
62 #endif
63
64 #include <glib.h>
65
66 #ifdef NEED_SNPRINTF_H
67 # include "snprintf.h"
68 #endif
69
70 #include "packet.h"
71 #include "in_cksum.h"
72 #include "packet-ip.h"
73 #include "packet-ipv6.h"
74 #include "ieee-float.h"
75 #include "etypes.h"
76
77 static int proto_rsvp = -1;
78
79 static gint ett_rsvp = -1;
80 static gint ett_rsvp_hdr = -1;
81 static gint ett_rsvp_session = -1;
82 static gint ett_rsvp_hop = -1;
83 static gint ett_rsvp_time_values = -1;
84 static gint ett_rsvp_error = -1;
85 static gint ett_rsvp_scope = -1;
86 static gint ett_rsvp_style = -1;
87 static gint ett_rsvp_confirm = -1;
88 static gint ett_rsvp_sender_template = -1;
89 static gint ett_rsvp_filter_spec = -1;
90 static gint ett_rsvp_sender_tspec = -1;
91 static gint ett_rsvp_flowspec = -1;
92 static gint ett_rsvp_adspec = -1;
93 static gint ett_rsvp_adspec_subtree = -1;
94 static gint ett_rsvp_integrity = -1;
95 static gint ett_rsvp_policy = -1;
96 static gint ett_rsvp_label = -1;
97 static gint ett_rsvp_label_request = -1;
98 static gint ett_rsvp_session_attribute = -1;
99 static gint ett_rsvp_session_attribute_flags = -1;
100 static gint ett_rsvp_explicit_route = -1;
101 static gint ett_rsvp_explicit_route_subobj = -1;
102 static gint ett_rsvp_record_route = -1;
103 static gint ett_rsvp_record_route_subobj = -1;
104 static gint ett_rsvp_unknown_class = -1;
105
106
107 /*
108  * RSVP message types
109  */
110 typedef enum {
111     RSVP_MSG_PATH=1, RSVP_MSG_RESV, RSVP_MSG_PERR, RSVP_MSG_RERR,
112     RSVP_MSG_PTEAR, RSVP_MSG_RTEAR, RSVP_MSG_CONFIRM, 
113     RSVP_MSG_RTEAR_CONFIRM=10
114 } rsvp_message_types;
115
116 static value_string message_type_vals[] = { 
117     {RSVP_MSG_PATH, "PATH Message"},
118     {RSVP_MSG_RESV, "RESV Message"},
119     {RSVP_MSG_PERR, "PATH ERROR Message"},
120     {RSVP_MSG_RERR, "RESV ERROR Message"},
121     {RSVP_MSG_PTEAR, "PATH TEAR Message"},
122     {RSVP_MSG_RTEAR, "RESV TEAR Message"},
123     {RSVP_MSG_CONFIRM, "CONFIRM Message"},
124     {RSVP_MSG_RTEAR_CONFIRM, "RESV TEAR CONFIRM Message"},
125     {0, NULL}
126 };
127
128 /* 
129  * RSVP classes
130  */
131 #define MAX_RSVP_CLASS 15
132
133 enum rsvp_classes {
134     RSVP_CLASS_NULL=0,
135     RSVP_CLASS_SESSION,
136
137     RSVP_CLASS_HOP=3,
138     RSVP_CLASS_INTEGRITY,
139     RSVP_CLASS_TIME_VALUES,
140     RSVP_CLASS_ERROR,
141     RSVP_CLASS_SCOPE,
142     RSVP_CLASS_STYLE,
143     RSVP_CLASS_FLOWSPEC,
144     RSVP_CLASS_FILTER_SPEC,
145     RSVP_CLASS_SENDER_TEMPLATE,
146     RSVP_CLASS_SENDER_TSPEC,
147     RSVP_CLASS_ADSPEC,
148     RSVP_CLASS_POLICY,
149     RSVP_CLASS_CONFIRM,
150     RSVP_CLASS_LABEL,
151
152     RSVP_CLASS_LABEL_REQUEST=19,
153     RSVP_CLASS_EXPLICIT_ROUTE,
154     RSVP_CLASS_RECORD_ROUTE,
155
156     RSVP_CLASS_SESSION_ATTRIBUTE=207,
157 };
158
159 static value_string rsvp_class_vals[] = { 
160     {RSVP_CLASS_NULL, "NULL object"},
161     {RSVP_CLASS_SESSION, "SESSION object"},
162     {RSVP_CLASS_HOP, "HOP object"},
163     {RSVP_CLASS_INTEGRITY, "INTEGRITY object"},
164     {RSVP_CLASS_TIME_VALUES, "TIME VALUES object"},
165     {RSVP_CLASS_ERROR, "ERROR object"},
166     {RSVP_CLASS_SCOPE, "SCOPE object"},
167     {RSVP_CLASS_STYLE, "STYLE object"},
168     {RSVP_CLASS_FLOWSPEC, "FLOWSPEC object"},
169     {RSVP_CLASS_FILTER_SPEC, "FILTER SPEC object"},
170     {RSVP_CLASS_SENDER_TEMPLATE, "SENDER TEMPLATE object"},
171     {RSVP_CLASS_SENDER_TSPEC, "SENDER TSPEC object"},
172     {RSVP_CLASS_ADSPEC, "ADSPEC object"},
173     {RSVP_CLASS_POLICY, "POLICY object"},
174     {RSVP_CLASS_CONFIRM, "CONFIRM object"},
175     {RSVP_CLASS_LABEL, "LABEL object"},
176     {RSVP_CLASS_LABEL_REQUEST, "LABEL REQUEST object"},
177     {RSVP_CLASS_EXPLICIT_ROUTE, "EXPLICIT ROUTE object"},
178     {RSVP_CLASS_RECORD_ROUTE, "RECORD ROUTE object"},
179     {RSVP_CLASS_SESSION_ATTRIBUTE, "SESSION ATTRIBUTE object"},
180     {0, NULL}
181 };
182
183 /*
184  * RSVP error values
185  */
186 enum rsvp_error_types {
187     RSVP_ERROR_CONFIRM = 0,
188     RSVP_ERROR_ADMISSION,
189     RSVP_ERROR_POLICY,
190     RSVP_ERROR_NO_PATH,
191     RSVP_ERROR_NO_SENDER,
192     RSVP_ERROR_CONFLICT_RESV_STYLE,
193     RSVP_ERROR_UNKNOWN_RESV_STYLE,
194     RSVP_ERROR_CONFLICT_DEST_PORTS,
195     RSVP_ERROR_CONFLICT_SRC_PORTS,
196     RSVP_ERROR_PREEMPTED=12,
197     RSVP_ERROR_UNKNOWN_CLASS,
198     RSVP_ERROR_UNKNOWN_C_TYPE,
199     RSVP_ERROR_TRAFFIC = 21,
200     RSVP_ERROR_TRAFFIC_SYSTEM,
201     RSVP_ERROR_SYSTEM
202 };
203
204 static value_string rsvp_error_vals[] = {
205     {RSVP_ERROR_CONFIRM, "Confirmation"},
206     {RSVP_ERROR_ADMISSION, "Admission Control Failure "},
207     {RSVP_ERROR_POLICY, "Policy Control Failure"},
208     {RSVP_ERROR_NO_PATH, "No PATH information for this RESV message"},
209     {RSVP_ERROR_NO_SENDER, "No sender information for this RESV message"},
210     {RSVP_ERROR_CONFLICT_RESV_STYLE, "Conflicting reservation styles"},
211     {RSVP_ERROR_UNKNOWN_RESV_STYLE, "Unknown reservation style"},
212     {RSVP_ERROR_CONFLICT_DEST_PORTS, "Conflicting destination ports"},
213     {RSVP_ERROR_CONFLICT_SRC_PORTS, "Conflicting source ports"},
214     {RSVP_ERROR_PREEMPTED, "Service preempted"},
215     {RSVP_ERROR_UNKNOWN_CLASS, "Unknown object class"},
216     {RSVP_ERROR_UNKNOWN_C_TYPE, "Unknown object C-type"},
217     {RSVP_ERROR_TRAFFIC, "Traffic Control Error"},
218     {RSVP_ERROR_TRAFFIC_SYSTEM, "Traffic Control System Error"},
219     {0, NULL}
220 };
221
222 /*
223  * Defines the reservation style plus style-specific information that
224  * is not a FLOWSPEC or FILTER_SPEC object, in a RESV message.
225  */
226 #define RSVP_DISTINCT (1 << 3)
227 #define RSVP_SHARED (2 << 3)
228 #define RSVP_SHARING_MASK (RSVP_DISTINCT | RSVP_SHARED)
229
230 #define RSVP_SCOPE_WILD 1
231 #define RSVP_SCOPE_EXPLICIT 2
232 #define RSVP_SCOPE_MASK 0x07
233
234 #define RSVP_WF (RSVP_SHARED | RSVP_SCOPE_WILD)
235 #define RSVP_FF (RSVP_DISTINCT | RSVP_SCOPE_EXPLICIT)
236 #define RSVP_SE (RSVP_SHARED | RSVP_SCOPE_EXPLICIT)
237
238 static value_string style_vals[] = {
239     { RSVP_WF, "Wildcard Filter" },
240     { RSVP_FF, "Fixed Filter" },
241     { RSVP_SE, "Shared-Explicit" },
242     { 0,       NULL }
243 };
244
245 /*
246  * Defines a desired QoS, in a RESV message.
247  */
248 enum    qos_service_type {
249     QOS_QUALITATIVE =     128,          /* Qualitative service */
250     QOS_CONTROLLED_LOAD=    5,          /* Controlled Load Service */
251     QOS_GUARANTEED =        2,          /* Guaranteed service */
252     QOS_TSPEC =             1           /* Traffic specification */
253     };
254
255 static value_string qos_vals[] = {
256     { QOS_QUALITATIVE, "Qualitative QoS" },
257     { QOS_CONTROLLED_LOAD, "Controlled-load QoS" },
258     { QOS_GUARANTEED, "Guaranteed rate QoS" },
259     { QOS_TSPEC, "Traffic specification" },
260     { 0, NULL }
261 };
262
263 static value_string svc_vals[] = {
264     { 127, "Token bucket TSpec" },
265     { 128, "Qualitative TSpec" },
266     { 130, "Guaranteed-rate RSpec" },
267     { 0, NULL }
268 };
269
270 enum rsvp_spec_types { INTSRV = 2 };
271
272 enum intsrv_services {
273         INTSRV_GENERAL = 1,
274         INTSRV_GTD = 2,
275         INTSRV_CLOAD = 5,
276         INTSRV_QUALITATIVE = 128
277 };
278
279 static value_string intsrv_services_str[] = { 
280     {INTSRV_GENERAL, "Default General Parameters"},
281     {INTSRV_GTD, "Guaranteed"},
282     {INTSRV_CLOAD, "Controlled Load"},
283     {INTSRV_QUALITATIVE, "Qualitative"},
284     { 0, NULL }
285 };
286
287 enum intsrv_field_name {
288         INTSRV_NON_IS_HOPS = 1, INTSRV_COMPOSED_NON_IS_HOPS,
289         INTSRV_IS_HOPS, INTSRV_COMPOSED_IS_HOPS,
290         INTSRV_PATH_BANDWIDTH, INTSRV_MIN_PATH_BANDWIDTH,
291         INTSRV_IF_LATENCY, INTSRV_PATH_LATENCY,
292         INTSRV_MTU, INTSRV_COMPOSED_MTU,
293
294         INTSRV_TOKEN_BUCKET_TSPEC = 127,
295         INTSRV_QUALITATIVE_TSPEC = 128,
296         INTSRV_GTD_RSPEC = 130,
297
298         INTSRV_DELAY = 131,     /* Gtd Parameter C - Max Delay Bound - bytes */
299         INTSRV_MAX_JITTER,      /* Gtd Parameter D - Max Jitter */
300         INTSRV_E2E_DELAY,       /* Gtd Parameter Ctot */
301         INTSRV_E2E_MAX_JITTER,  /* Gtd Parameter Dtot */
302         INTSRV_SHP_DELAY,       /* Gtd Parameter Csum */
303         INTSRV_SHP_MAX_JITTER   /* Gtd Parameter Dsum */
304 };
305
306 static value_string adspec_params[] = { 
307     {4, "IS Hop Count"},
308     {6, "Path b/w estimate"},
309     {8, "Minimum path latency"},
310     {10, "Composed MTU"},
311     {133, "End-to-end composed value for C"},
312     {134, "End-to-end composed value for D"},
313     {135, "Since-last-reshaping point composed C"},
314     {136, "Since-last-reshaping point composed D"},
315     { 0, NULL }
316 };
317
318 /* -------------------- Stuff for MPLS/TE objects -------------------- */
319
320 static const value_string proto_vals[] = { {IP_PROTO_ICMP, "ICMP"},
321                                            {IP_PROTO_IGMP, "IGMP"},
322                                            {IP_PROTO_TCP,  "TCP" },
323                                            {IP_PROTO_UDP,  "UDP" },
324                                            {IP_PROTO_OSPF, "OSPF"},
325                                            {0,             NULL  } };
326
327 /* Filter keys */
328 enum rsvp_filter_keys {
329
330     /* Message types */
331     RSVPF_MSG,          /* Message type */
332     /* Shorthand for message types */
333     RSVPF_PATH,
334     RSVPF_RESV,
335     RSVPF_PATHERR,
336     RSVPF_RESVERR,
337     RSVPF_PATHTEAR,
338     RSVPF_RESVTEAR,
339     RSVPF_RCONFIRM,
340     RSVPF_JUNK_MSG8,
341     RSVPF_JUNK_MSG9,
342     RSVPF_RTEARCONFIRM,
343
344     /* Does the message contain an object of this type? */
345     RSVPF_OBJECT,
346     /* Object present shorthands */
347     RSVPF_SESSION,
348     RSVPF_DUMMY_1,
349     RSVPF_HOP,
350     RSVPF_INTEGRITY,
351     RSVPF_TIME_VALUES,
352     RSVPF_ERROR,
353     RSVPF_SCOPE,
354     RSVPF_STYLE,
355     RSVPF_FLOWSPEC,
356     RSVPF_FILTER_SPEC,
357     RSVPF_SENDER,
358     RSVPF_TSPEC,
359     RSVPF_ADSPEC,
360     RSVPF_POLICY,
361     RSVPF_CONFIRM,
362     RSVPF_LABEL,
363     RSVPF_DUMMY_2,
364     RSVPF_DUMMY_3,
365     RSVPF_LABEL_REQUEST,
366     RSVPF_EXPLICIT_ROUTE,
367     RSVPF_RECORD_ROUTE,
368
369     RSVPF_SESSION_ATTRIBUTE,
370
371     RSVPF_UNKNOWN_OBJ, 
372
373     /* Session object */
374     RSVPF_SESSION_IP,
375     RSVPF_SESSION_PROTO,
376     RSVPF_SESSION_PORT,
377     RSVPF_SESSION_TUNNEL_ID,
378     RSVPF_SESSION_EXT_TUNNEL_ID,
379
380     /* Sender template */
381     RSVPF_SENDER_IP,
382     RSVPF_SENDER_PORT,
383     RSVPF_SENDER_LSP_ID,
384
385     /* Sentinel */
386     RSVPF_MAX
387 };
388
389 static int rsvp_filter[RSVPF_MAX];
390
391 static hf_register_info rsvpf_info[] = {
392
393     /* Message type number */
394     {&rsvp_filter[RSVPF_MSG], 
395      { "Message Type", "rsvp.msg", FT_UINT8, BASE_DEC, VALS(message_type_vals), 0x0,
396         "" }},
397
398     /* Message type shorthands */
399     {&rsvp_filter[RSVPF_PATH], 
400      { "Path Message", "rsvp.path", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
401         "" }},
402
403     {&rsvp_filter[RSVPF_RESV], 
404      { "Resv Message", "rsvp.resv", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
405         "" }},
406
407     {&rsvp_filter[RSVPF_PATHERR], 
408      { "Path Error Message", "rsvp.perr", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
409         "" }},
410
411     {&rsvp_filter[RSVPF_RESVERR], 
412      { "Resv Error Message", "rsvp.rerr", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
413         "" }},
414
415     {&rsvp_filter[RSVPF_PATHTEAR], 
416      { "Path Tear Message", "rsvp.ptear", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
417         "" }},
418
419     {&rsvp_filter[RSVPF_RESVTEAR], 
420      { "Resv Tear Message", "rsvp.rtear", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
421         "" }},
422
423     {&rsvp_filter[RSVPF_RCONFIRM], 
424      { "Resv Confirm Message", "rsvp.resvconf", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
425         "" }},
426
427     {&rsvp_filter[RSVPF_RTEARCONFIRM], 
428      { "Resv Tear Confirm Message", "rsvp.rtearconf", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
429         "" }},
430
431     /* Object class */
432     {&rsvp_filter[RSVPF_OBJECT], 
433      { "Object class", "rsvp.object", FT_UINT8, BASE_DEC, VALS(rsvp_class_vals), 0x0,
434         "" }},
435
436     /* Object present shorthands */
437     {&rsvp_filter[RSVPF_SESSION], 
438      { "SESSION", "rsvp.session", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
439         "" }},
440
441     {&rsvp_filter[RSVPF_HOP], 
442      { "HOP", "rsvp.hop", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
443         "" }},
444
445     {&rsvp_filter[RSVPF_INTEGRITY], 
446      { "INTEGRITY", "rsvp.integrity", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
447         "" }},
448
449     {&rsvp_filter[RSVPF_TIME_VALUES], 
450      { "TIME VALUES", "rsvp.time", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
451         "" }},
452
453     {&rsvp_filter[RSVPF_ERROR], 
454      { "ERROR", "rsvp.error", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
455         "" }},
456
457     {&rsvp_filter[RSVPF_SCOPE], 
458      { "SCOPE", "rsvp.scope", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
459         "" }},
460
461     {&rsvp_filter[RSVPF_STYLE], 
462      { "STYLE", "rsvp.style", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
463         "" }},
464
465     {&rsvp_filter[RSVPF_FLOWSPEC], 
466      { "FLOWSPEC", "rsvp.flowspec", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
467         "" }},
468
469     {&rsvp_filter[RSVPF_FILTER_SPEC], 
470      { "FILTERSPEC", "rsvp.filter", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
471         "" }},
472
473     {&rsvp_filter[RSVPF_SENDER], 
474      { "SENDER TEMPLATE", "rsvp.sender", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
475         "" }},
476
477     {&rsvp_filter[RSVPF_TSPEC], 
478      { "SENDER TSPEC", "rsvp.tspec", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
479         "" }},
480
481     {&rsvp_filter[RSVPF_ADSPEC], 
482      { "ADSPEC", "rsvp.adspec", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
483         "" }},
484
485     {&rsvp_filter[RSVPF_POLICY], 
486      { "POLICY", "rsvp.policy", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
487         "" }},
488
489     {&rsvp_filter[RSVPF_CONFIRM], 
490      { "CONFIRM", "rsvp.confirm", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
491         "" }},
492
493     {&rsvp_filter[RSVPF_LABEL], 
494      { "LABEL", "rsvp.label", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
495         "" }},
496
497     {&rsvp_filter[RSVPF_LABEL_REQUEST], 
498      { "LABEL REQUEST", "rsvp.label_request", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
499         "" }},
500
501     {&rsvp_filter[RSVPF_SESSION_ATTRIBUTE], 
502      { "SESSION ATTRIBUTE", "rsvp.session_attribute", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
503         "" }},
504
505     {&rsvp_filter[RSVPF_EXPLICIT_ROUTE], 
506      { "EXPLICIT ROUTE", "rsvp.explicit_route", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
507         "" }},
508
509     {&rsvp_filter[RSVPF_RECORD_ROUTE], 
510      { "RECORD ROUTE", "rsvp.record_route", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
511         "" }},
512
513     {&rsvp_filter[RSVPF_UNKNOWN_OBJ], 
514      { "Unknown object", "rsvp.obj_unknown", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
515         "" }},
516
517     /* Session fields */
518     {&rsvp_filter[RSVPF_SESSION_IP], 
519      { "Destination address", "rsvp.session.ip", FT_IPv4, BASE_NONE, NULL, 0x0,
520         "" }},
521
522     {&rsvp_filter[RSVPF_SESSION_PORT], 
523      { "Port number", "rsvp.session.port", FT_UINT16, BASE_DEC, NULL, 0x0,
524         "" }},
525
526     {&rsvp_filter[RSVPF_SESSION_PROTO], 
527      { "Protocol", "rsvp.session.proto", FT_UINT8, BASE_DEC, VALS(proto_vals), 0x0,
528         "" }},
529
530     {&rsvp_filter[RSVPF_SESSION_TUNNEL_ID], 
531      { "Tunnel ID", "rsvp.session.tunnel_id", FT_UINT16, BASE_DEC, NULL, 0x0,
532         "" }},
533
534     {&rsvp_filter[RSVPF_SESSION_EXT_TUNNEL_ID], 
535      { "Extended tunnel ID", "rsvp.session.ext_tunnel_id", FT_UINT32, BASE_DEC, NULL, 0x0,
536         "" }},
537
538     /* Sender template/Filterspec fields */
539     {&rsvp_filter[RSVPF_SENDER_IP], 
540      { "Sender IPv4 address", "rsvp.sender.ip", FT_IPv4, BASE_NONE, NULL, 0x0,
541         "" }},
542
543     {&rsvp_filter[RSVPF_SENDER_PORT], 
544      { "Sender port number", "rsvp.sender.port", FT_UINT16, BASE_DEC, NULL, 0x0,
545        "" }},
546
547     {&rsvp_filter[RSVPF_SENDER_LSP_ID], 
548      { "Sender LSP ID", "rsvp.sender.lsp_id", FT_UINT16, BASE_DEC, NULL, 0x0,
549         "" }}
550 };
551
552 static inline int rsvp_class_to_filter_num(int classnum)
553 {
554     switch(classnum) {
555     case RSVP_CLASS_SESSION :
556     case RSVP_CLASS_HOP :
557     case RSVP_CLASS_INTEGRITY :
558     case RSVP_CLASS_TIME_VALUES :
559     case RSVP_CLASS_ERROR :
560     case RSVP_CLASS_SCOPE :
561     case RSVP_CLASS_STYLE :
562     case RSVP_CLASS_FLOWSPEC :
563     case RSVP_CLASS_FILTER_SPEC :
564     case RSVP_CLASS_SENDER_TEMPLATE :
565     case RSVP_CLASS_SENDER_TSPEC :
566     case RSVP_CLASS_ADSPEC :
567     case RSVP_CLASS_POLICY :
568     case RSVP_CLASS_CONFIRM :
569     case RSVP_CLASS_LABEL :
570     case RSVP_CLASS_LABEL_REQUEST :
571     case RSVP_CLASS_EXPLICIT_ROUTE :
572     case RSVP_CLASS_RECORD_ROUTE :
573         return classnum + RSVPF_OBJECT;
574         break;
575
576     case RSVP_CLASS_SESSION_ATTRIBUTE :
577         return RSVPF_SESSION_ATTRIBUTE;
578         
579     default:
580         return RSVPF_UNKNOWN_OBJ;
581     }
582 }
583
584 static void 
585 dissect_rsvp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) 
586 {
587     int offset = 0;
588     proto_tree *rsvp_tree = NULL, *ti, *ti2; 
589     proto_tree *rsvp_header_tree;
590     proto_tree *rsvp_object_tree;
591     proto_tree *rsvp_sa_flags_tree;
592     proto_tree *rsvp_ero_subtree;
593     guint8 ver_flags;
594     guint8 message_type;
595     guint16 cksum, computed_cksum;
596     vec_t cksum_vec[1];
597     int i, j, k, l, len;
598     int msg_length;
599     int obj_length;
600     int mylen;
601     int offset2;
602
603     if (check_col(pinfo->fd, COL_PROTOCOL))
604         col_set_str(pinfo->fd, COL_PROTOCOL, "RSVP");
605     if (check_col(pinfo->fd, COL_INFO))
606         col_clear(pinfo->fd, COL_INFO);
607
608     ver_flags = tvb_get_guint8(tvb, offset+0);
609     message_type = tvb_get_guint8(tvb, offset+1);
610     if (check_col(pinfo->fd, COL_INFO)) {
611         col_add_str(pinfo->fd, COL_INFO,
612             val_to_str(message_type, message_type_vals, "Unknown (%u)")); 
613     }
614
615     if (tree) {
616         msg_length = tvb_get_ntohs(tvb, offset+6);
617         ti = proto_tree_add_item(tree, proto_rsvp, tvb, offset, msg_length,
618             FALSE);
619         rsvp_tree = proto_item_add_subtree(ti, ett_rsvp);
620
621         ti = proto_tree_add_text(rsvp_tree, tvb, offset, 8, "RSVP Header"); 
622         rsvp_header_tree = proto_item_add_subtree(ti, ett_rsvp_hdr);
623
624         proto_tree_add_text(rsvp_header_tree, tvb, offset, 1, "RSVP Version: %u", 
625                             (ver_flags & 0xf0)>>4);  
626         proto_tree_add_text(rsvp_header_tree, tvb, offset, 1, "Flags: %02x",
627                             ver_flags & 0xf);
628         proto_tree_add_uint(rsvp_header_tree, rsvp_filter[RSVPF_MSG], tvb, 
629                             offset+1, 1, message_type);
630         if (message_type <= RSVPF_RTEARCONFIRM &&
631                         message_type != RSVPF_JUNK_MSG8 &&
632                         message_type != RSVPF_JUNK_MSG9 ) {
633                proto_tree_add_boolean_hidden(rsvp_header_tree, rsvp_filter[RSVPF_MSG + message_type], tvb, 
634                                    offset+1, 1, 1);
635         }
636         cksum = tvb_get_ntohs(tvb, offset+2);
637         if (!pinfo->fragmented && tvb_length(tvb) >= msg_length) {
638             /* The packet isn't part of a fragmented datagram and isn't
639                truncated, so we can checksum it. */
640             cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, msg_length);
641             cksum_vec[0].len = msg_length;
642             computed_cksum = in_cksum(&cksum_vec[0], 1);
643             if (computed_cksum == 0) {
644                 proto_tree_add_text(rsvp_header_tree, tvb, offset+2, 2,
645                                     "Message Checksum: 0x%04x (correct)",
646                                     cksum);
647             } else {
648                 proto_tree_add_text(rsvp_header_tree, tvb, offset+2, 2,
649                                     "Message Checksum: 0x%04x (incorrect, should be 0x%04x)",
650                                     cksum,
651                                     in_cksum_shouldbe(cksum, computed_cksum));
652             }
653         } else {
654             proto_tree_add_text(rsvp_header_tree, tvb, offset+2, 2,
655                                 "Message Checksum: 0x%04x",
656                                 cksum);
657         }
658         proto_tree_add_text(rsvp_header_tree, tvb, offset+4, 1,
659                             "Sending TTL: %u",
660                             tvb_get_guint8(tvb, offset+4));
661         proto_tree_add_text(rsvp_header_tree, tvb, offset+6, 2,
662                             "Message length: %u", msg_length);
663
664         offset += 8;
665         len = 8;
666         while (len < msg_length) {
667             guint8 class;       
668             guint8 type;
669             char *object_type;
670
671             obj_length = tvb_get_ntohs(tvb, offset);
672             class = tvb_get_guint8(tvb, offset+2);
673             type = tvb_get_guint8(tvb, offset+3);
674             object_type = val_to_str(class, rsvp_class_vals, "Unknown");
675             proto_tree_add_uint_hidden(rsvp_tree, rsvp_filter[RSVPF_OBJECT], tvb, 
676                                             offset, obj_length, class);
677             ti = proto_tree_add_boolean(rsvp_tree, rsvp_filter[rsvp_class_to_filter_num(class)],
678                                      tvb, offset, obj_length, TRUE);
679
680             offset2 = offset+4;
681
682             switch(class) {
683
684             case RSVP_CLASS_SESSION :           
685                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_session);
686                 proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
687                                     "Length: %u", obj_length);
688                 proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
689                                     "Class number: %u - %s", 
690                                     class, object_type);
691                 mylen = obj_length - 4;
692                 switch(type) {
693                 case 1: {
694                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1,
695                                         "C-type: 1 - IPv4");
696                     proto_tree_add_item(rsvp_object_tree,
697                                         rsvp_filter[RSVPF_SESSION_IP],
698                                         tvb, offset2, 4, FALSE);
699
700                     proto_tree_add_item(rsvp_object_tree,
701                                         rsvp_filter[RSVPF_SESSION_PROTO], tvb, 
702                                         offset2+4, 1, FALSE);
703                     proto_tree_add_text(rsvp_object_tree, tvb, offset2+5, 1,
704                                         "Flags: %x",
705                                         tvb_get_ntohs(tvb, offset2+5));
706                     proto_tree_add_item(rsvp_object_tree,
707                                         rsvp_filter[RSVPF_SESSION_PORT], tvb, 
708                                         offset2+6, 2, FALSE);
709                     break;
710                 }
711
712                 case 2: {
713                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
714                                         "C-type: 2 - IPv6");
715                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16,
716                                         "Destination address: %s", 
717                                         ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
718                     proto_tree_add_text(rsvp_object_tree, tvb, offset2+16, 1,
719                                         "Protocol: %u",
720                                         tvb_get_guint8(tvb, offset2+16));
721                     proto_tree_add_text(rsvp_object_tree, tvb, offset2+17, 1,
722                                         "Flags: %x",
723                                         tvb_get_guint8(tvb, offset2+17));
724                     proto_tree_add_text(rsvp_object_tree, tvb, offset2+18, 2,
725                                         "Destination port: %u", 
726                                         tvb_get_ntohs(tvb, offset2+18));
727                     break;
728                 }
729                 
730                 case 7: {
731                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
732                                         "C-type: 7 - IPv4 LSP");
733                     proto_tree_add_item(rsvp_object_tree,
734                                         rsvp_filter[RSVPF_SESSION_IP],
735                                         tvb, offset2, 4, FALSE);
736
737                     proto_tree_add_item(rsvp_object_tree,
738                                         rsvp_filter[RSVPF_SESSION_TUNNEL_ID],
739                                         tvb, offset2+6, 2, FALSE);
740
741                     proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 4, 
742                                         "Extended Tunnel ID: %u (%s)",
743                                         tvb_get_ntohl(tvb, offset2+8),
744                                         ip_to_str(tvb_get_ptr(tvb, offset2+8, 4)));
745                     proto_tree_add_item_hidden(rsvp_object_tree,
746                                         rsvp_filter[RSVPF_SESSION_EXT_TUNNEL_ID],
747                                         tvb, offset2+8, 4, FALSE);
748                     break;
749                 }
750
751                 default: {
752                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
753                                         "C-type: Unknown (%u)",
754                                         type);
755                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
756                                         "Data (%d bytes)", mylen);
757                 }
758                 }
759                 break;
760                 
761             case RSVP_CLASS_HOP :               
762                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_hop);
763                 proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
764                                     "Length: %u", obj_length);
765                 proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
766                                     "Class number: %u - %s", 
767                                     class, object_type);
768                 mylen = obj_length - 4;
769                 switch(type) {
770                 case 1: {
771                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
772                                         "C-type: 1 - IPv4");
773                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4, 
774                                         "Neighbor address: %s", 
775                                         ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
776                     proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
777                                         "Logical interface: %u", 
778                                         tvb_get_ntohl(tvb, offset2+4));
779                     break;
780                 }
781
782                 case 2: {
783                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
784                                         "C-type: 2 - IPv6");
785                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16,
786                                         "Neighbor address: %s", 
787                                         ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
788                     proto_tree_add_text(rsvp_object_tree, tvb, offset2+16, 4,
789                                         "Logical interface: 0x%08x", 
790                                         tvb_get_ntohl(tvb, offset2+16));
791                     break;
792                 }
793                 
794                 default: {
795                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
796                                         "C-type: Unknown (%u)",
797                                         type);
798                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
799                                         "Data (%d bytes)", mylen);
800                 }
801                 }
802                 break;
803                 
804             case RSVP_CLASS_TIME_VALUES : 
805                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_time_values);
806                 proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
807                                     "Length: %u", obj_length);
808                 proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
809                                     "Class number: %u - %s", 
810                                     class, object_type);
811                 mylen = obj_length - 4;
812                 switch(type) {
813                 case 1: {
814                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
815                                         "C-type: 1");
816                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4, 
817                                         "Refresh interval: %u ms (%u seconds)",
818                                         tvb_get_ntohl(tvb, offset2),
819                                         tvb_get_ntohl(tvb, offset2)/1000);
820                     break;
821                 }
822
823                 default: {
824                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
825                                         "C-type: Unknown (%u)",
826                                         type);
827                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
828                                         "Data (%d bytes)", mylen);
829                     break;
830                 }
831                 }
832                 break;
833
834             case RSVP_CLASS_ERROR :
835                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_error);
836                 proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
837                                     "Length: %u", obj_length);
838                 proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
839                                     "Class number: %u - %s", 
840                                     class, object_type);
841                 mylen = obj_length - 4;
842                 switch(type) {
843                 case 1: {
844                     guint8 error_code;
845
846                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
847                                         "C-type: 1 - IPv4");
848                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4, 
849                                         "Error node: %s",
850                                         ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
851                     proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 1,
852                                         "Flags: 0x%02x",
853                                         tvb_get_guint8(tvb, offset2+4));
854                     error_code = tvb_get_guint8(tvb, offset2+5);
855                     proto_tree_add_text(rsvp_object_tree, tvb, offset2+5, 1,
856                                         "Error code: %u - %s", error_code,
857                                         val_to_str(error_code, rsvp_error_vals, "Unknown"));
858                     proto_tree_add_text(rsvp_object_tree, tvb, offset2+6, 2,
859                                         "Error value: %u",
860                                         tvb_get_ntohs(tvb, offset2+6));
861                     break;
862                 }
863
864                 case 2: {
865                     guint8 error_code;
866
867                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
868                                         "C-type: 2 - IPv6");
869                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16,
870                                         "Error node: %s",
871                                         ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
872                     proto_tree_add_text(rsvp_object_tree, tvb, offset2+16, 1,
873                                         "Flags: 0x%02x",
874                                         tvb_get_guint8(tvb, offset2+16));
875                     error_code = tvb_get_guint8(tvb, offset2+17);
876                     proto_tree_add_text(rsvp_object_tree, tvb, offset2+17, 1,
877                                         "Error code: %u - %s", error_code,
878                                         val_to_str(error_code, rsvp_error_vals, "Unknown"));
879                     proto_tree_add_text(rsvp_object_tree, tvb, offset2+18, 2,
880                                         "Error value: %u",
881                                         tvb_get_ntohs(tvb, offset2+18));
882                     break;
883                 }
884                 
885                 default: {
886                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
887                                         "C-type: Unknown (%u)",
888                                         type);
889                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
890                                         "Data (%d bytes)", mylen);
891                 }
892                 }
893                 break;
894                 
895
896             case RSVP_CLASS_SCOPE : 
897                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_scope);
898                 proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
899                                     "Length: %u", obj_length);
900                 proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
901                                     "Class number: %u - %s", 
902                                     class, object_type);
903                 mylen = obj_length - 4;
904                 switch(type) {
905                 case 1: {
906                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
907                                         "C-type: 1 - IPv4");
908                     while (mylen > 0) {
909                         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4, 
910                                             "IPv4 Address: %s",
911                                             ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
912                         offset2 += 4;
913                         mylen -= 4;
914                     }
915                     break;
916                 }
917
918                 case 2: {
919                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
920                                         "C-type: 2 - IPv6");
921                     while (mylen > 0) {
922                         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16, 
923                                             "IPv6 Address: %s",
924                                             ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
925                         offset2 += 16;
926                         mylen -= 16;
927                     }
928                     break;
929                 }
930                 
931                 default: {
932                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
933                                         "C-type: Unknown (%u)",
934                                         type);
935                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
936                                         "Data (%d bytes)", mylen);
937                 }
938                 }
939                 break;
940                 
941             case RSVP_CLASS_STYLE : 
942                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_style);
943                 proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
944                                     "Length: %u", obj_length);
945                 proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
946                                     "Class number: %u - %s", 
947                                     class, object_type);
948                 mylen = obj_length - 4;
949                 switch(type) {
950                 case 1: {
951                     guint32 style;
952
953                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
954                                         "C-type: 1");
955                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
956                                         "Flags: 0x%02x",
957                                         tvb_get_guint8(tvb, offset2));
958                     style = tvb_get_ntoh24(tvb, offset2+1);
959                     ti = proto_tree_add_text(rsvp_object_tree, tvb, offset2+1,
960                         3, "Style: 0x%06X - %s",
961                         style,
962                         val_to_str(style, style_vals, "Unknown"));
963                     break;
964                 }
965
966                 default: {
967                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
968                                         "C-type: Unknown (%u)",
969                                         type);
970                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
971                                         "Data (%d bytes)", mylen);
972                     break;
973                 }
974                 }
975                 break;
976             
977             case RSVP_CLASS_CONFIRM :           
978                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_confirm);
979                 proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
980                                     "Length: %u", obj_length);
981                 proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
982                                     "Class number: %u - %s", 
983                                     class, object_type);
984                 mylen = obj_length - 4;
985                 switch(type) {
986                 case 1: {
987                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
988                                         "C-type: 1 - IPv4");
989                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, 4, 
990                                         "Receiver address: %s", 
991                                         ip_to_str(tvb_get_ptr(tvb, offset2, 4)));
992                     break;
993                 }
994
995                 case 2: {
996                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
997                                         "C-type: 2 - IPv6");
998                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16, 
999                                         "Receiver address: %s", 
1000                                         ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
1001                     break;
1002                 }
1003
1004                 default: {
1005                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1006                                         "C-type: Unknown (%u)",
1007                                         type);
1008                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
1009                                         "Data (%d bytes)", mylen);
1010                 }
1011                 }
1012                 break;
1013
1014             case RSVP_CLASS_SENDER_TEMPLATE :
1015                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_sender_template);
1016                 proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
1017                                     "Length: %u", obj_length);
1018                 proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
1019                                     "Class number: %u - %s", 
1020                                     class, object_type);
1021                 goto common_template;
1022             case RSVP_CLASS_FILTER_SPEC :
1023                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_filter_spec);
1024                 proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
1025                                     "Length: %u", obj_length);
1026                 proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
1027                                     "Class number: %u - %s", 
1028                                     class, object_type);
1029             common_template:
1030                 mylen = obj_length - 4;
1031                 switch(type) {
1032                 case 1: {
1033                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1034                                         "C-type: 1 - IPv4");
1035                     proto_tree_add_item(rsvp_object_tree,
1036                                         rsvp_filter[RSVPF_SENDER_IP],
1037                                         tvb, offset2, 4, FALSE);
1038                     proto_tree_add_item(rsvp_object_tree,
1039                                         rsvp_filter[RSVPF_SENDER_PORT],
1040                                         tvb, offset2+6, 2, FALSE);
1041                     break;
1042                 }
1043
1044                 case 2: {
1045                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1046                                         "C-type: 2 - IPv6");
1047                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, 16, 
1048                                         "Source address: %s", 
1049                                         ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2, 16)));
1050                     proto_tree_add_text(rsvp_object_tree, tvb, offset2+18, 2,
1051                                         "Source port: %u",
1052                                         tvb_get_ntohs(tvb, offset2+18));
1053                     break;
1054                 }
1055                 
1056                 case 7: {
1057                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1058                                         "C-type: 7 - IPv4 LSP");
1059                     proto_tree_add_item(rsvp_object_tree,
1060                                         rsvp_filter[RSVPF_SENDER_IP],
1061                                         tvb, offset2, 4, FALSE);
1062                     proto_tree_add_item(rsvp_object_tree,
1063                                         rsvp_filter[RSVPF_SENDER_LSP_ID],
1064                                         tvb, offset2+6, 2, FALSE);
1065                     break;
1066                 }
1067
1068                 default: {
1069                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1070                                         "C-type: Unknown (%u)",
1071                                         type);
1072                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
1073                                         "Data (%d bytes)", mylen);
1074                 }
1075                 }
1076                 break;
1077
1078             case RSVP_CLASS_SENDER_TSPEC : {
1079                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_sender_tspec);
1080                 proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
1081                                     "Length: %u", obj_length);
1082                 proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
1083                                     "Class number: %u - %s", 
1084                                     class, object_type);
1085                 mylen = obj_length - 4;
1086
1087                 proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1, 
1088                                     "Message format version: %u", 
1089                                     tvb_get_guint8(tvb, offset2)>>4);
1090                 proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2, 
1091                                     "Data length: %u words, not including header", 
1092                                     tvb_get_ntohs(tvb, offset2+2));
1093
1094                 mylen -= 4;
1095                 offset2 += 4;
1096                 while (mylen > 0) {
1097                     guint8 service_num;
1098                     guint8 param_id;
1099                     guint16 length;
1100
1101                     service_num = tvb_get_guint8(tvb, offset2);
1102                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1, 
1103                                         "Service header: %u - %s", 
1104                                         service_num,
1105                                         val_to_str(service_num, qos_vals, "Unknown"));
1106                     length = tvb_get_ntohs(tvb, offset2+2);
1107                     proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2, 
1108                                         "Length of service %u data: %u words, " 
1109                                         "not including header", 
1110                                         service_num, length);
1111
1112                     mylen -= 4;
1113                     offset2 += 4;
1114
1115                     switch(service_num) {
1116                         
1117                     case QOS_TSPEC :
1118                         /* Token bucket TSPEC */
1119                         param_id = tvb_get_guint8(tvb, offset2);
1120                         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1, 
1121                                             "Parameter %u - %s", 
1122                                             param_id,
1123                                             val_to_str(param_id, svc_vals, "Unknown"));
1124                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+1, 1,
1125                                             "Parameter %u flags: 0x%02x",
1126                                             param_id,
1127                                             tvb_get_guint8(tvb, offset2+1));
1128                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
1129                                             "Parameter %u data length: %u words, " 
1130                                             "not including header",
1131                                             param_id,
1132                                             tvb_get_ntohs(tvb, offset2+2));
1133                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
1134                                             "Token bucket rate: %ld", 
1135                                             tvb_ieee_to_long(tvb, offset2+4));
1136                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 4,
1137                                             "Token bucket size: %ld", 
1138                                             tvb_ieee_to_long(tvb, offset2+8));
1139                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+12, 4,
1140                                             "Peak data rate: %ld", 
1141                                             tvb_ieee_to_long(tvb, offset2+12));
1142                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+16, 4,
1143                                             "Minimum policed unit: %u", 
1144                                             tvb_get_ntohl(tvb, offset2+16));
1145                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+20, 4,
1146                                             "Maximum policed unit: %u", 
1147                                             tvb_get_ntohl(tvb, offset2+20));
1148                         break;
1149
1150                     case QOS_QUALITATIVE :
1151                         /* Token bucket TSPEC */
1152                         param_id = tvb_get_guint8(tvb, offset2);
1153                         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1, 
1154                                             "Parameter %u - %s", 
1155                                             param_id,
1156                                             val_to_str(param_id, svc_vals, "Unknown"));
1157                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+1, 1,
1158                                             "Parameter %u flags: %x", 
1159                                             param_id,
1160                                             tvb_get_guint8(tvb, offset2+1));
1161                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
1162                                             "Parameter %u data length: %u words, " 
1163                                             "not including header",
1164                                             param_id,
1165                                             tvb_get_ntohs(tvb, offset2+2));
1166                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
1167                                             "Maximum policed unit: %u", 
1168                                             tvb_get_ntohl(tvb, offset2+4));
1169                         break;
1170
1171                     }
1172                     offset2 += length*4; 
1173                     mylen -= length*4;
1174                 }
1175                 break;
1176             }
1177
1178             case RSVP_CLASS_FLOWSPEC : {
1179                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_flowspec);
1180                 proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
1181                                     "Length: %u", obj_length);
1182                 proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
1183                                     "Class number: %u - %s", 
1184                                     class, object_type);
1185                 mylen = obj_length - 4;
1186
1187                 proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1, 
1188                                     "Message format version: %u", 
1189                                     tvb_get_guint8(tvb, offset2)>>4);
1190                 proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2, 
1191                                     "Data length: %u words, not including header", 
1192                                     tvb_get_ntohs(tvb, offset2+2));
1193
1194                 mylen -= 4;
1195                 offset2+= 4;
1196                 while (mylen > 0) {
1197                     guint8 service_num;
1198                     guint16 length;
1199                     guint8 param_id;
1200
1201                     service_num = tvb_get_guint8(tvb, offset2);
1202                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1, 
1203                                         "Service header: %u - %s", 
1204                                         service_num,
1205                                         val_to_str(service_num, intsrv_services_str, "Unknown"));
1206                     length = tvb_get_ntohs(tvb, offset2+2);
1207                     proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2, 
1208                                         "Length of service %u data: %u words, " 
1209                                         "not including header", 
1210                                         service_num,
1211                                         length);
1212
1213                     mylen -= 4;
1214                     offset2 += 4;
1215
1216                     switch(service_num) {
1217
1218                     case QOS_CONTROLLED_LOAD :
1219                     case QOS_GUARANTEED :
1220                         /* Treat both these the same for now */
1221                         param_id = tvb_get_guint8(tvb, offset2);
1222                         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1, 
1223                                             "Parameter %u - %s", 
1224                                             param_id,
1225                                             val_to_str(param_id, svc_vals, "Unknown"));
1226                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+1, 1,
1227                                             "Parameter %u flags: %x", 
1228                                             param_id,
1229                                             tvb_get_guint8(tvb, offset2+1));
1230                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
1231                                             "Parameter %u data length: %u words, " 
1232                                             "not including header",
1233                                             param_id,
1234                                             tvb_get_ntohs(tvb, offset2+2));
1235                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
1236                                             "Token bucket rate: %ld", 
1237                                             tvb_ieee_to_long(tvb, offset2+4));
1238                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+8, 4,
1239                                             "Token bucket size: %ld", 
1240                                             tvb_ieee_to_long(tvb, offset2+8));
1241                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+12, 4,
1242                                             "Peak data rate: %ld", 
1243                                             tvb_ieee_to_long(tvb, offset2+12));
1244                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+16, 4,
1245                                             "Minimum policed unit: %u", 
1246                                             tvb_get_ntohl(tvb, offset2+16));
1247                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+20, 4,
1248                                             "Maximum policed unit: %u", 
1249                                             tvb_get_ntohl(tvb, offset2+20));
1250                         if (service_num != QOS_GUARANTEED)
1251                             break;
1252                         
1253                         /* Guaranteed-rate RSpec */
1254                         param_id = tvb_get_guint8(tvb, offset2+24);
1255                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+24, 1,
1256                                             "Parameter %u - %s", 
1257                                             param_id,
1258                                             val_to_str(param_id, svc_vals, "Unknown"));
1259                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+25, 1, 
1260                                             "Parameter %u flags: %x", 
1261                                             param_id,
1262                                             tvb_get_guint8(tvb, offset2+25));
1263                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+26, 2,
1264                                             "Parameter %u data length: %u words, " 
1265                                             "not including header",
1266                                             param_id,
1267                                             tvb_get_ntohs(tvb, offset2+26));
1268
1269                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+28, 4,
1270                                             "Rate: %ld", 
1271                                             tvb_ieee_to_long(tvb, offset2+28));
1272                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+32, 4,
1273                                             "Slack term: %u", 
1274                                             tvb_get_ntohl(tvb, offset2+32));
1275                         break;
1276
1277                     case QOS_QUALITATIVE :
1278                         param_id = tvb_get_guint8(tvb, offset2);
1279                         proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1, 
1280                                             "Parameter %u - %s", 
1281                                             param_id,
1282                                             val_to_str(param_id, svc_vals, "Unknown"));
1283                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+1, 1,
1284                                             "Parameter %u flags: %x", 
1285                                             param_id,
1286                                             tvb_get_guint8(tvb, offset2+1));
1287                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
1288                                             "Parameter %u data length: %u words, " 
1289                                             "not including header",
1290                                             param_id,
1291                                             tvb_get_ntohs(tvb, offset2+2));
1292                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, 4,
1293                                             "Maximum policed unit: %u", 
1294                                             tvb_get_ntohl(tvb, offset2+4));
1295                         
1296                         break;
1297                     }
1298                     offset2 += length*4;
1299                     mylen -= length*4;
1300                 }
1301                 break;
1302             }
1303
1304             case RSVP_CLASS_ADSPEC : {
1305                 proto_tree *adspec_tree;
1306
1307                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_adspec);
1308                 proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
1309                                     "Length: %u", obj_length);
1310                 proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
1311                                     "Class number: %u - %s", 
1312                                     class, object_type);
1313                 mylen = obj_length - 4;
1314
1315                 proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
1316                                     "Message format version: %u", 
1317                                     tvb_get_guint8(tvb, offset2)>>4);
1318                 proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
1319                                     "Data length: %u words, not including header", 
1320                                     tvb_get_ntohs(tvb, offset2+2));
1321                 mylen -= 4;
1322                 offset2 += 4;
1323                 while (mylen > 0) {
1324                     guint8 service_num;
1325                     guint8 break_bit;
1326                     guint16 length;
1327                     char *str;
1328
1329                     service_num = tvb_get_guint8(tvb, offset2);
1330                     str = val_to_str(service_num, intsrv_services_str, "Unknown");
1331                     break_bit = tvb_get_guint8(tvb, offset2+1);
1332                     length = tvb_get_ntohs(tvb, offset2+2);
1333                     ti = proto_tree_add_text(rsvp_object_tree, tvb, offset2, 
1334                                              (length+1)*4,
1335                                              str);
1336                     adspec_tree = proto_item_add_subtree(ti,
1337                                                          ett_rsvp_adspec_subtree);
1338                     proto_tree_add_text(adspec_tree, tvb, offset2, 1,
1339                                         "Service header %u - %s",
1340                                         service_num, str);
1341                     proto_tree_add_text(adspec_tree, tvb, offset2+1, 1,
1342                                         (break_bit&0x80)?
1343                                         "Break bit set":"Break bit not set");
1344                     proto_tree_add_text(adspec_tree, tvb, offset2+2, 2, 
1345                                         "Data length: %u words, not including header", 
1346                                         length);
1347                     mylen -= 4;
1348                     offset2 += 4;
1349                     i = length*4;
1350                     while (i > 0) {
1351                         guint8 id;
1352                         guint16 phdr_length;
1353
1354                         id = tvb_get_guint8(tvb, offset2);
1355                         phdr_length = tvb_get_ntohs(tvb, offset2+2);
1356                         str = match_strval(id, adspec_params);
1357                         if (str) {
1358                             switch(id) {
1359                             case 4:
1360                             case 8:
1361                             case 10:
1362                             case 133:
1363                             case 134:
1364                             case 135:
1365                             case 136:
1366                                 /* 32-bit unsigned integer */
1367                                 proto_tree_add_text(adspec_tree, tvb, offset2,
1368                                                     (phdr_length+1)<<2,
1369                                                     "%s - %u (type %u, length %u)",
1370                                                     str,
1371                                                     tvb_get_ntohl(tvb, offset2+4),
1372                                                     id, phdr_length);
1373                                 break;
1374                                 
1375                             case 6:
1376                                 /* IEEE float */
1377                                 proto_tree_add_text(adspec_tree, tvb, offset2,
1378                                                     (phdr_length+1)<<2,
1379                                                     "%s - %lu (type %u, length %u)",
1380                                                     str,
1381                                                     tvb_ieee_to_long(tvb, offset2+4),
1382                                                     id, phdr_length);
1383                                 break;
1384                             default: 
1385                                 proto_tree_add_text(adspec_tree, tvb, offset2, 
1386                                                     (phdr_length+1)<<2,
1387                                                     "%s (type %u, length %u)",
1388                                                     str,
1389                                                     id, phdr_length);
1390                             }
1391                         } else {
1392                             proto_tree_add_text(adspec_tree, tvb, offset2, 
1393                                                 (phdr_length+1)<<2,
1394                                                 "Unknown (type %u, length %u)",
1395                                                 id, phdr_length);
1396                         }
1397                         offset2 += (phdr_length+1)<<2;
1398                         i -= (phdr_length+1)<<2;
1399                         mylen -= (phdr_length+1)<<2;
1400                     }
1401                 }
1402                 break;
1403             }
1404
1405             case RSVP_CLASS_INTEGRITY :
1406                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_integrity);
1407                 proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
1408                                     "Length: %u", obj_length);
1409                 proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
1410                                     "Class number: %u - %s", 
1411                                     class, object_type);
1412                 goto default_class;
1413
1414             case RSVP_CLASS_POLICY :
1415                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_policy);
1416                 proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
1417                                     "Length: %u", obj_length);
1418                 proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
1419                                     "Class number: %u - %s", 
1420                                     class, object_type);
1421                 goto default_class;
1422
1423             case RSVP_CLASS_LABEL_REQUEST : 
1424                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_label_request);
1425                 proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
1426                                     "Length: %u", obj_length);
1427                 proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
1428                                     "Class number: %u - %s", 
1429                                     class, object_type);
1430                 mylen = obj_length - 4;
1431                 switch(type) {
1432                 case 1: {
1433                     unsigned short l3pid = tvb_get_ntohs(tvb, offset2+2);
1434                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1435                                         "C-type: 1");
1436                     proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 2,
1437                                         "L3PID: %s (0x%04x)",
1438                                         val_to_str(l3pid, etype_vals, "Unknown"),
1439                                         l3pid);
1440                     break;
1441                 }
1442
1443                 default: {
1444                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1445                                         "C-type: Unknown (%u)",
1446                                         type);
1447                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
1448                                         "Data (%d bytes)", mylen);
1449                     break;
1450                 }
1451                 }
1452                 break;
1453             
1454             case RSVP_CLASS_LABEL : 
1455                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_label);
1456                 proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
1457                                     "Length: %u", obj_length);
1458                 proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
1459                                     "Class number: %u - %s", 
1460                                     class, object_type);
1461                 mylen = obj_length - 4;
1462                 switch(type) {
1463                 case 1: {
1464                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1465                                         "C-type: 1");
1466                     for (i=1, l = 0; l < mylen; l+=4, i++)
1467                         proto_tree_add_text(rsvp_object_tree, tvb, offset2+l, 4,
1468                                             "Label %d: %u %s", 
1469                                             i, tvb_get_ntohl(tvb, offset2+l), 
1470                                             l == mylen - 4 ? 
1471                                             "(Top label)" : "");
1472                     break;
1473                 }
1474
1475                 default: {
1476                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1477                                         "C-type: Unknown (%u)",
1478                                         type);
1479                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
1480                                         "Data (%d bytes)", mylen);
1481                     break;
1482                 }
1483                 }
1484                 break;
1485             
1486             case RSVP_CLASS_SESSION_ATTRIBUTE : 
1487                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_session_attribute);
1488                 proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
1489                                     "Length: %u", obj_length);
1490                 proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
1491                                     "Class number: %u - %s", 
1492                                     class, object_type);
1493                 mylen = obj_length - 4;
1494                 switch(type) {
1495                 case 7: {
1496                     guint8 flags;
1497                     guint8 name_len;
1498
1499                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1500                                         "C-type: 7 - IPv4 LSP");
1501                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, 1,
1502                                         "Setup priority: %u",
1503                                         tvb_get_guint8(tvb, offset2));
1504                     proto_tree_add_text(rsvp_object_tree, tvb, offset2+1, 1,
1505                                         "Hold priority: %u",
1506                                         tvb_get_guint8(tvb, offset2+1));
1507                     flags = tvb_get_guint8(tvb, offset2+2);
1508                     ti2 = proto_tree_add_text(rsvp_object_tree, tvb, offset2+2, 1,
1509                                               "Flags: 0x%02x", flags);
1510                     rsvp_sa_flags_tree = proto_item_add_subtree(ti2, 
1511                                                                 ett_rsvp_session_attribute_flags);
1512                     proto_tree_add_text(rsvp_sa_flags_tree, tvb, offset2+2, 1,
1513                                         decode_boolean_bitfield(flags, 0x01, 8,
1514                                             "Local protection desired",
1515                                             "Local protection not desired"));
1516                     proto_tree_add_text(rsvp_sa_flags_tree, tvb, offset2+2, 1,
1517                                         decode_boolean_bitfield(flags, 0x02, 8,
1518                                             "Merging permitted",
1519                                             "Merging not permitted"));
1520                     proto_tree_add_text(rsvp_sa_flags_tree, tvb, offset2+2, 1,
1521                                         decode_boolean_bitfield(flags, 0x04, 8,
1522                                             "Ingress node may reroute",
1523                                             "Ingress node may not reroute"));
1524                     
1525                     name_len = tvb_get_guint8(tvb, offset2+3);
1526                     proto_tree_add_text(rsvp_object_tree, tvb, offset2+3, 1,
1527                                         "Name length: %u", name_len);
1528                     proto_tree_add_text(rsvp_object_tree, tvb, offset2+4, name_len,
1529                                         "Name: %.*s",
1530                                         name_len,
1531                                         tvb_get_ptr(tvb, offset2+4, name_len));
1532                     break;
1533                 }
1534
1535                 default: {
1536                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1537                                         "C-type: Unknown (%u)",
1538                                         type);
1539                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
1540                                         "Data (%d bytes)", mylen);
1541                     break;
1542                 }
1543                 }
1544                 break;
1545
1546             case RSVP_CLASS_EXPLICIT_ROUTE : 
1547                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_explicit_route);
1548                 proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
1549                                     "Length: %u", obj_length);
1550                 proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
1551                                     "Class number: %u - %s", 
1552                                     class, object_type);
1553                 mylen = obj_length - 4;
1554                 switch(type) {
1555                 case 1: {
1556                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1557                                         "C-type: 1");
1558                     for (i=1, l = 0; l < mylen; i++) {
1559                         j = tvb_get_guint8(tvb, offset2+l) & 0x7f;
1560                         switch(j) {
1561                         case 1: /* IPv4 */
1562                             k = tvb_get_guint8(tvb, offset2+l) & 0x80;
1563                             ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
1564                                                       offset2+l, 8,
1565                                                       "IPv4 Subobject - %s, %s",
1566                                                       ip_to_str(tvb_get_ptr(tvb, offset2+l+2, 4)),
1567                                                       k ? "Loose" : "Strict");
1568                             rsvp_ero_subtree = 
1569                                 proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); 
1570                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
1571                                                 k ? "Loose Hop " : "Strict Hop");
1572                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
1573                                                 "Type: 1 (IPv4)");
1574                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+1, 1,
1575                                                 "Length: %u",
1576                                                 tvb_get_guint8(tvb, offset2+l+1));
1577                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+2, 4,
1578                                                 "IPv4 hop: %s",
1579                                                 ip_to_str(tvb_get_ptr(tvb, offset2+l+2, 4)));
1580                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+6, 1, 
1581                                                 "Prefix length: %u",
1582                                                 tvb_get_guint8(tvb, offset2+l+6));
1583                             break;
1584
1585                         case 2: /* IPv6 */
1586                             ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
1587                                                       offset2+l, 20,
1588                                                       "IPv6 Subobject");
1589                             rsvp_ero_subtree = 
1590                                 proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); 
1591                             k = tvb_get_guint8(tvb, offset2+l) & 0x80;
1592                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
1593                                                 k ? "Loose Hop " : "Strict Hop");
1594                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
1595                                                 "Type: 2 (IPv6)");
1596                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+1, 1,
1597                                                 "Length: %u",
1598                                                 tvb_get_guint8(tvb, offset2+l+1));
1599                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+2, 16,
1600                                                 "IPv6 hop: %s",
1601                                                 ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2+l+2, 16)));
1602                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+18, 1,
1603                                                 "Prefix length: %u",
1604                                                 tvb_get_guint8(tvb, offset2+l+6));
1605                             break;
1606
1607                         case 32: /* AS */
1608                             k = tvb_get_ntohs(tvb, offset2+l+2);
1609                             ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
1610                                                       offset2+l, 4,
1611                                                       "Autonomous System %u",
1612                                                       k);
1613                             rsvp_ero_subtree = 
1614                                 proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); 
1615                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
1616                                                 k ? "Loose Hop " : "Strict Hop");
1617                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
1618                                                 "Type: 32 (Autonomous System Number)");
1619                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+1, 1,
1620                                                 "Length: %u",
1621                                                 tvb_get_guint8(tvb, offset2+l+1));
1622                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+2, 2,
1623                                                 "Autonomous System %u", k);
1624                             break;
1625
1626                         case 64: /* Path Term */
1627                             k = tvb_get_guint8(tvb, offset2+l) & 0x80;
1628                             ti2 = proto_tree_add_text(rsvp_object_tree, tvb,
1629                                                       offset2+l, 4,
1630                                                       "LSP Path Termination");
1631                             rsvp_ero_subtree = 
1632                                 proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); 
1633                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
1634                                                 k ? "Loose Hop " : "Strict Hop");
1635                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
1636                                                 "Type: 64 (MPLS LSP Path Termination)");
1637                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+1, 1,
1638                                                 "Length: %u",
1639                                                 tvb_get_guint8(tvb, offset2+l+1));
1640                             break;
1641
1642                         default: /* Unknown subobject */
1643                             k = tvb_get_guint8(tvb, offset2+l) & 0x80;
1644                             ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
1645                                                       offset2+l,
1646                                                       tvb_get_guint8(tvb, offset2+l+1),
1647                                                       "Unknown subobject: %d", j);
1648                             rsvp_ero_subtree = 
1649                                 proto_item_add_subtree(ti2, ett_rsvp_explicit_route_subobj); 
1650                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
1651                                                 k ? "Loose Hop " : "Strict Hop");
1652                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
1653                                                 "Type: %u (Unknown)", j);
1654                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+1, 1,
1655                                                 "Length: %u",
1656                                                 tvb_get_guint8(tvb, offset2+l+1));
1657
1658                         }
1659
1660                         l += tvb_get_guint8(tvb, offset2+l+1);
1661                     }
1662                     break;
1663                 }
1664                 default: {
1665                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1666                                         "C-type: Unknown (%u)",
1667                                         type);
1668                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
1669                                         "Data (%d bytes)", mylen);
1670                     break;
1671                 }
1672                 }
1673                 break;
1674             
1675
1676             case RSVP_CLASS_RECORD_ROUTE : 
1677                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_record_route);
1678                 proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
1679                                     "Length: %u", obj_length);
1680                 proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
1681                                     "Class number: %u - %s", 
1682                                     class, object_type);
1683                 mylen = obj_length - 4;
1684                 switch(type) {
1685                 case 1: {
1686                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1687                                         "C-type: 1");
1688                     for (i=1, l = 0; l < mylen; i++) {
1689                         j = tvb_get_guint8(tvb, offset2+l);
1690                         switch(j) {
1691                         case 1: /* IPv4 */
1692                             ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
1693                                                       offset2+l, 8,
1694                                                       "IPv4 Subobject - %s",
1695                                                       ip_to_str(tvb_get_ptr(tvb, offset2+l+2, 4)));
1696                             rsvp_ero_subtree = 
1697                                 proto_item_add_subtree(ti2, ett_rsvp_record_route_subobj); 
1698                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
1699                                                 "Type: 1 (IPv4)");
1700                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+1, 1,
1701                                                 "Length: %u",
1702                                                 tvb_get_guint8(tvb, offset2+l+1));
1703                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+2, 4,
1704                                                 "IPv4 hop: %s",
1705                                                 ip_to_str(tvb_get_ptr(tvb, offset2+l+2, 4)));
1706                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+6, 1,
1707                                                 "Prefix length: %u",
1708                                                 tvb_get_guint8(tvb, offset2+l+6));
1709                             break;
1710
1711                         case 2: /* IPv6 */
1712                             ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
1713                                                       offset2+l, 20,
1714                                                       "IPv6 Subobject");
1715                             rsvp_ero_subtree = 
1716                                 proto_item_add_subtree(ti2, ett_rsvp_record_route_subobj); 
1717                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
1718                                                 "Type: 2 (IPv6)");
1719                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+1, 1,
1720                                                 "Length: %u",
1721                                                 tvb_get_guint8(tvb, offset2+l+1));
1722                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+2, 16,
1723                                                 "IPv6 hop: %s",
1724                                                 ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset2+l+2, 16)));
1725                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+18, 1,
1726                                                 "Prefix length: %u",
1727                                                 tvb_get_guint8(tvb, offset2+l+6));
1728                             break;
1729
1730                         default: /* Unknown subobject */
1731                             k = tvb_get_guint8(tvb, offset2+l) & 0x80;
1732                             ti2 = proto_tree_add_text(rsvp_object_tree, tvb, 
1733                                                       offset2+l,
1734                                                       tvb_get_guint8(tvb, offset2+l+1),
1735                                                       "Unknown subobject: %u",
1736                                                       j);
1737                             rsvp_ero_subtree = 
1738                                 proto_item_add_subtree(ti2, ett_rsvp_record_route_subobj); 
1739                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
1740                                                 k ? "Loose Hop " : "Strict Hop");
1741                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l, 1,
1742                                                 "Type: %u (Unknown)", j);
1743                             proto_tree_add_text(rsvp_ero_subtree, tvb, offset2+l+1, 1,
1744                                                 "Length: %u",
1745                                                 tvb_get_guint8(tvb, offset2+l+1));
1746
1747                         }
1748
1749                         l += tvb_get_guint8(tvb, offset2+l+1);
1750                     }
1751                     break;
1752                 }
1753                 
1754                 default: {
1755                     proto_tree_add_text(rsvp_object_tree, tvb, offset+3, 1, 
1756                                         "C-type: Unknown (%u)",
1757                                         type);
1758                     proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
1759                                         "Data (%d bytes)", mylen);
1760                     break;
1761                 }
1762                 }
1763                 break;
1764             
1765             default :
1766                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_unknown_class);
1767                 proto_tree_add_text(rsvp_object_tree, tvb, offset, 2,
1768                                     "Length: %u", obj_length);
1769                 proto_tree_add_text(rsvp_object_tree, tvb, offset+2, 1, 
1770                                     "Class number: %u - %s", 
1771                                     class, object_type);
1772             default_class:
1773                 mylen = obj_length - 4;
1774                 proto_tree_add_text(rsvp_object_tree, tvb, offset2, mylen,
1775                                     "Data (%d bytes)", mylen);
1776                 break;
1777
1778             case RSVP_CLASS_NULL :
1779                 break;
1780
1781             }  
1782             
1783             offset += obj_length;
1784             len += obj_length;
1785         }
1786     }
1787 }
1788
1789 void
1790 proto_register_rsvp(void)
1791 {
1792         static gint *ett[] = {
1793                 &ett_rsvp,
1794                 &ett_rsvp_hdr,
1795                 &ett_rsvp_session,
1796                 &ett_rsvp_hop,
1797                 &ett_rsvp_time_values,
1798                 &ett_rsvp_error,
1799                 &ett_rsvp_scope,
1800                 &ett_rsvp_style,
1801                 &ett_rsvp_confirm,
1802                 &ett_rsvp_sender_template,
1803                 &ett_rsvp_filter_spec,
1804                 &ett_rsvp_sender_tspec,
1805                 &ett_rsvp_flowspec,
1806                 &ett_rsvp_adspec,
1807                 &ett_rsvp_adspec_subtree,
1808                 &ett_rsvp_integrity,
1809                 &ett_rsvp_policy,
1810                 &ett_rsvp_label,
1811                 &ett_rsvp_label_request,
1812                 &ett_rsvp_session_attribute,
1813                 &ett_rsvp_session_attribute_flags,
1814                 &ett_rsvp_explicit_route,
1815                 &ett_rsvp_explicit_route_subobj,
1816                 &ett_rsvp_record_route,
1817                 &ett_rsvp_record_route_subobj,
1818                 &ett_rsvp_unknown_class,
1819         };
1820
1821         proto_rsvp = proto_register_protocol("Resource ReserVation Protocol (RSVP)",
1822             "RSVP", "rsvp");
1823         proto_register_field_array(proto_rsvp, rsvpf_info, array_length(rsvpf_info));
1824         proto_register_subtree_array(ett, array_length(ett));
1825 }
1826
1827 void
1828 proto_reg_handoff_rsvp(void)
1829 {
1830         dissector_add("ip.proto", IP_PROTO_RSVP, dissect_rsvp, proto_rsvp);
1831 }