Put into the "Capture Preferences" dialog box a check box to control
[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.11 1999/12/13 19:59:29 gram 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
39  
40 #ifdef HAVE_CONFIG_H
41 # include "config.h"
42 #endif
43
44 #include <stdio.h>
45
46 #ifdef HAVE_UNISTD_H
47 #include <unistd.h>
48 #endif
49
50 #include <stdlib.h>
51 #include <string.h>
52
53 #ifdef HAVE_SYS_TYPES_H
54 # include <sys/types.h>
55 #endif
56
57 #ifdef HAVE_NETINET_IN_H
58 # include <netinet/in.h>
59 #endif
60
61 #ifdef NEED_SNPRINTF_H
62 # ifdef HAVE_STDARG_H
63 #  include <stdarg.h>
64 # else
65 #  include <varargs.h>
66 # endif
67 # include "snprintf.h"
68 #endif
69
70 #include <glib.h>
71 #include "packet.h"
72 #include "packet-ip.h"
73 #include "packet-ipv6.h"
74 #include "packet-rsvp.h"
75
76 static int proto_rsvp = -1;
77
78 static gint ett_rsvp = -1;
79 static gint ett_rsvp_hdr = -1;
80 static gint ett_rsvp_session = -1;
81 static gint ett_rsvp_hop = -1;
82 static gint ett_rsvp_time_values = -1;
83 static gint ett_rsvp_error = -1;
84 static gint ett_rsvp_scope = -1;
85 static gint ett_rsvp_style = -1;
86 static gint ett_rsvp_confirm = -1;
87 static gint ett_rsvp_sender_template = -1;
88 static gint ett_rsvp_filter_spec = -1;
89 static gint ett_rsvp_sender_tspec = -1;
90 static gint ett_rsvp_flowspec = -1;
91 static gint ett_rsvp_adspec = -1;
92 static gint ett_rsvp_adspec_subtree = -1;
93 static gint ett_rsvp_integrity = -1;
94 static gint ett_rsvp_policy = -1;
95 static gint ett_rsvp_unknown_class = -1;
96
97 /* Stuff for IEEE float handling */
98
99 #define IEEE_NUMBER_WIDTH       32      /* bits in number */
100 #define IEEE_EXP_WIDTH          8       /* bits in exponent */
101 #define IEEE_MANTISSA_WIDTH     23      /* IEEE_NUMBER_WIDTH - 1 - IEEE_EXP_WIDTH */
102
103 #define IEEE_SIGN_MASK          0x80000000
104 #define IEEE_EXPONENT_MASK      0x7F800000
105 #define IEEE_MANTISSA_MASK      0x007FFFFF
106 #define IEEE_INFINITY           IEEE_EXPONENT_MASK
107
108 #define IEEE_IMPLIED_BIT (1 << IEEE_MANTISSA_WIDTH)
109 #define IEEE_INFINITE ((1 << IEEE_EXP_WIDTH) - 1)
110 #define IEEE_BIAS ((1 << (IEEE_EXP_WIDTH - 1)) - 1)
111
112 #define MINUS_INFINITY (signed)0x80000000L
113 #define PLUS_INFINITY  0x7FFFFFFF
114
115 static const value_string proto_vals[] = { {IP_PROTO_ICMP, "ICMP"},
116                                            {IP_PROTO_IGMP, "IGMP"},
117                                            {IP_PROTO_TCP,  "TCP" },
118                                            {IP_PROTO_UDP,  "UDP" },
119                                            {IP_PROTO_OSPF, "OSPF"},
120                                            {0,             NULL  } };
121
122 /* Filter keys */
123 enum rsvp_filter_keys {
124
125     /* Message types */
126     RSVPF_MSG,          /* Message type */
127     /* Shorthand for message types */
128     RSVPF_PATH,
129     RSVPF_RESV,
130     RSVPF_PATHERR,
131     RSVPF_RESVERR,
132     RSVPF_PATHTEAR,
133     RSVPF_RESVTEAR,
134     RSVPF_RCONFIRM,
135
136     /* Does the message contain an object of this type? */
137     RSVPF_OBJECT,
138     /* Object present shorthands */
139     RSVPF_SESSION,
140     RSVPF_DUMMY_1,
141     RSVPF_HOP,
142     RSVPF_INTEGRITY,
143     RSVPF_TIME_VALUES,
144     RSVPF_ERROR,
145     RSVPF_SCOPE,
146     RSVPF_STYLE,
147     RSVPF_FLOWSPEC,
148     RSVPF_FILTER_SPEC,
149     RSVPF_SENDER,
150     RSVPF_TSPEC,
151     RSVPF_ADSPEC,
152     RSVPF_POLICY,
153     RSVPF_CONFIRM,
154     RSVPF_UNKNOWN_OBJ, 
155
156     /* Session object */
157     RSVPF_SESSION_IP,
158     RSVPF_SESSION_PROTO,
159     RSVPF_SESSION_PORT,
160
161     /* Sender template */
162     RSVPF_SENDER_IP,
163     RSVPF_SENDER_PORT,
164
165     /* Sentinel */
166     RSVPF_MAX
167 };
168
169 static int rsvp_filter[RSVPF_MAX];
170
171 static hf_register_info rsvpf_info[] = {
172
173     /* Message type number */
174     {&rsvp_filter[RSVPF_MSG], 
175      { "Message Type", "rsvp.msg", FT_UINT8, BASE_NONE, message_type_vals, 0x0,
176         "" }},
177
178     /* Message type shorthands */
179     {&rsvp_filter[RSVPF_PATH], 
180      { "Path Message", "rsvp.path", FT_UINT8, BASE_NONE, NULL, 0x0,
181         "" }},
182
183     {&rsvp_filter[RSVPF_RESV], 
184      { "Resv Message", "rsvp.resv", FT_UINT8, BASE_NONE, NULL, 0x0,
185         "" }},
186
187     {&rsvp_filter[RSVPF_PATHERR], 
188      { "Path Error Message", "rsvp.perr", FT_UINT8, BASE_NONE, NULL, 0x0,
189         "" }},
190
191     {&rsvp_filter[RSVPF_RESVERR], 
192      { "Resv Error Message", "rsvp.rerr", FT_UINT8, BASE_NONE, NULL, 0x0,
193         "" }},
194
195     {&rsvp_filter[RSVPF_PATHTEAR], 
196      { "Path Tear Message", "rsvp.ptear", FT_UINT8, BASE_NONE, NULL, 0x0,
197         "" }},
198
199     {&rsvp_filter[RSVPF_RESVTEAR], 
200      { "Resv Tear Message", "rsvp.rtear", FT_UINT8, BASE_NONE, NULL, 0x0,
201         "" }},
202
203     {&rsvp_filter[RSVPF_RCONFIRM], 
204      { "Resv Confirm Message", "rsvp.resvconf", FT_UINT8, BASE_NONE, NULL, 0x0,
205         "" }},
206
207     /* Object present */
208     {&rsvp_filter[RSVPF_OBJECT], 
209      { "", "rsvp.object", FT_UINT8, BASE_NONE, rsvp_class_vals, 0x0,
210         "" }},
211
212     /* Object present shorthands */
213     {&rsvp_filter[RSVPF_SESSION], 
214      { "SESSION", "rsvp.session", FT_UINT8, BASE_NONE, NULL, 0x0,
215         "" }},
216
217     {&rsvp_filter[RSVPF_HOP], 
218      { "HOP", "rsvp.hop", FT_UINT8, BASE_NONE, NULL, 0x0,
219         "" }},
220
221     {&rsvp_filter[RSVPF_INTEGRITY], 
222      { "INTEGRITY", "rsvp.integrity", FT_UINT8, BASE_NONE, NULL, 0x0,
223         "" }},
224
225     {&rsvp_filter[RSVPF_TIME_VALUES], 
226      { "TIME VALUES", "rsvp.time", FT_UINT8, BASE_NONE, NULL, 0x0,
227         "" }},
228
229     {&rsvp_filter[RSVPF_ERROR], 
230      { "ERROR", "rsvp.error", FT_UINT8, BASE_NONE, NULL, 0x0,
231         "" }},
232
233     {&rsvp_filter[RSVPF_SCOPE], 
234      { "SCOPE", "rsvp.scope", FT_UINT8, BASE_NONE, NULL, 0x0,
235         "" }},
236
237     {&rsvp_filter[RSVPF_STYLE], 
238      { "STYLE", "rsvp.style", FT_UINT8, BASE_NONE, NULL, 0x0,
239         "" }},
240
241     {&rsvp_filter[RSVPF_FLOWSPEC], 
242      { "FLOWSPEC", "rsvp.flowspec", FT_UINT8, BASE_NONE, NULL, 0x0,
243         "" }},
244
245     {&rsvp_filter[RSVPF_FILTER_SPEC], 
246      { "FILTERSPEC", "rsvp.filter", FT_UINT8, BASE_NONE, NULL, 0x0,
247         "" }},
248
249     {&rsvp_filter[RSVPF_SENDER], 
250      { "SENDER TEMPLATE", "rsvp.sender", FT_UINT8, BASE_NONE, NULL, 0x0,
251         "" }},
252
253     {&rsvp_filter[RSVPF_TSPEC], 
254      { "SENDER TSPEC", "rsvp.tspec", FT_UINT8, BASE_NONE, NULL, 0x0,
255         "" }},
256
257     {&rsvp_filter[RSVPF_ADSPEC], 
258      { "ADSPEC", "rsvp.adspec", FT_UINT8, BASE_NONE, NULL, 0x0,
259         "" }},
260
261     {&rsvp_filter[RSVPF_POLICY], 
262      { "POLICY", "rsvp.policy", FT_UINT8, BASE_NONE, NULL, 0x0,
263         "" }},
264
265     {&rsvp_filter[RSVPF_CONFIRM], 
266      { "CONFIRM", "rsvp.confirm", FT_UINT8, BASE_NONE, NULL, 0x0,
267         "" }},
268
269     {&rsvp_filter[RSVPF_UNKNOWN_OBJ], 
270      { "Unknown object", "rsvp.obj_unknown", FT_UINT8, BASE_NONE, NULL, 0x0,
271         "" }},
272
273     /* Session fields */
274     {&rsvp_filter[RSVPF_SESSION_IP], 
275      { "Destination address", "rsvp.session.ip", FT_IPv4, BASE_NONE, NULL, 0x0,
276         "" }},
277
278     {&rsvp_filter[RSVPF_SESSION_PORT], 
279      { "Port number", "rsvp.session.port", FT_UINT16, BASE_NONE, NULL, 0x0,
280         "" }},
281
282     {&rsvp_filter[RSVPF_SESSION_PROTO], 
283      { "Protocol", "rsvp.session.proto", FT_UINT8, BASE_NONE, VALS(proto_vals), 0x0,
284         "" }},
285
286     /* Sender template fields */
287     {&rsvp_filter[RSVPF_SENDER_IP], 
288      { "Sender Template IPv4 address", "rsvp.template.ip", FT_IPv4, BASE_NONE, NULL, 0x0,
289         "" }},
290
291     {&rsvp_filter[RSVPF_SENDER_PORT], 
292      { "Sender Template port number", "rsvp.template.port", FT_UINT16, BASE_NONE, NULL, 0x0,
293         "" }}
294 };
295
296 static inline int rsvp_class_to_filter_num(int classnum)
297 {
298     switch(classnum) {
299     case RSVP_CLASS_SESSION :
300     case RSVP_CLASS_HOP :
301     case RSVP_CLASS_INTEGRITY :
302     case RSVP_CLASS_TIME_VALUES :
303     case RSVP_CLASS_ERROR :
304     case RSVP_CLASS_SCOPE :
305     case RSVP_CLASS_STYLE :
306     case RSVP_CLASS_FLOWSPEC :
307     case RSVP_CLASS_FILTER_SPEC :
308     case RSVP_CLASS_SENDER_TEMPLATE :
309     case RSVP_CLASS_SENDER_TSPEC :
310     case RSVP_CLASS_ADSPEC :
311     case RSVP_CLASS_POLICY :
312     case RSVP_CLASS_CONFIRM :
313         return classnum + RSVPF_OBJECT;
314         
315     default:
316         return RSVPF_UNKNOWN_OBJ;
317     }
318 }
319
320 static inline int ieee_float_is_zero (long number)
321 {
322     return(!(number & ~IEEE_SIGN_MASK));
323 }
324
325 /*
326  * simple conversion: ieee floating point to long
327  */
328 static long ieee_to_long (const void *p)
329 {
330     long number;
331     long sign;
332     long exponent;
333     long mantissa;
334
335     number = pntohl(p);
336     sign = number & IEEE_SIGN_MASK;
337     exponent = number & IEEE_EXPONENT_MASK;
338     mantissa = number & IEEE_MANTISSA_MASK;
339
340     if (ieee_float_is_zero(number)) {
341         /* number is zero, unnormalized, or not-a-number */
342         return 0;
343     }
344     if (IEEE_INFINITY == exponent) {
345         /* number is positive or negative infinity, or a special value */
346         return (sign? MINUS_INFINITY: PLUS_INFINITY);
347     }
348
349     exponent = (exponent >> IEEE_MANTISSA_WIDTH) - IEEE_BIAS;
350     if (exponent < 0) {
351         /* number is between zero and one */
352         return 0;
353     }
354
355     mantissa |= IEEE_IMPLIED_BIT;
356     if (exponent <= IEEE_MANTISSA_WIDTH)
357         mantissa >>= IEEE_MANTISSA_WIDTH - exponent;
358     else
359         mantissa <<= exponent - IEEE_MANTISSA_WIDTH;
360
361     if (sign)
362         return -mantissa;
363     else
364         return mantissa;
365 }
366
367 void 
368 dissect_rsvp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) 
369 {
370     proto_tree *rsvp_tree = NULL, *ti; 
371     proto_tree *rsvp_header_tree;
372     proto_tree *rsvp_object_tree;
373     char *packet_type, *object_type;
374     rsvp_header *hdr;
375     rsvp_object *obj;
376     int i, len, mylen;
377     int msg_length;
378     int obj_length;
379     int offset2;
380
381     hdr = (rsvp_header *)&pd[offset];
382     packet_type = match_strval(hdr->message_type, message_type_vals);
383     if (check_col(fd, COL_PROTOCOL))
384         col_add_str(fd, COL_PROTOCOL, "RSVP");
385     if (check_col(fd, COL_INFO)) {
386         if (packet_type != NULL)
387             col_add_str(fd, COL_INFO, packet_type); 
388         else
389             col_add_fstr(fd, COL_INFO, "Unknown (%d)", hdr->message_type); 
390     }
391
392     if (tree) {
393         msg_length = pntohs(pd+offset+6);
394         ti = proto_tree_add_item(tree, proto_rsvp, offset, msg_length, NULL);
395         rsvp_tree = proto_item_add_subtree(ti, ett_rsvp);
396
397         ti = proto_tree_add_text(rsvp_tree, offset, 
398                               sizeof(rsvp_header), "RSVP Header"); 
399         rsvp_header_tree = proto_item_add_subtree(ti, ett_rsvp_hdr);
400
401         proto_tree_add_text(rsvp_header_tree, offset, 1, "RSVP Version: %d", 
402                          (hdr->ver_flags & 0xf0)>>4);  
403         proto_tree_add_text(rsvp_header_tree, offset, 1, "Flags: %02X",
404                          hdr->ver_flags & 0xf);  
405         proto_tree_add_item(rsvp_header_tree, rsvp_filter[RSVPF_MSG], 
406                             offset+1, 1, hdr->message_type);
407         if (hdr->message_type >= RSVPF_MAX) {
408                 proto_tree_add_text(rsvp_header_tree, offset+1, 1, "Message Type: %d - Unknown",
409                                  hdr->message_type);
410                 return;
411         }
412         proto_tree_add_item_hidden(rsvp_header_tree, rsvp_filter[RSVPF_MSG + hdr->message_type], 
413                             offset+1, 1, 1);
414         proto_tree_add_text(rsvp_header_tree, offset + 2 , 2, "Message Checksum");
415         proto_tree_add_text(rsvp_header_tree, offset + 4 , 1, "Sending TTL: %d",
416                          hdr->sending_ttl);
417         proto_tree_add_text(rsvp_header_tree, offset + 6 , 2, "Message length: %d",
418                          msg_length);
419
420         offset += sizeof(rsvp_header);
421         len = 0;
422         while (len + sizeof(rsvp_header) < msg_length) {
423             obj = (rsvp_object *)&pd[offset];
424             obj_length = pntohs(pd+offset);
425             if (offset + obj_length > fd->cap_len) {
426                 proto_tree_add_text(rsvp_tree, offset, 1, 
427                                  "Further data not captured");
428                 break;
429             }
430             
431             object_type = match_strval(obj->class, rsvp_class_vals);
432             if (!object_type) object_type = "Unknown";
433             /*
434             ti = proto_tree_add_text(rsvp_tree, offset, 
435                                   obj_length, 
436                                   "%s (%d)", object_type, obj->class);
437             */
438             ti = proto_tree_add_item_hidden(rsvp_tree, rsvp_filter[RSVPF_OBJECT], 
439                                      offset, obj_length, obj->class);
440             ti = proto_tree_add_item(rsvp_tree, rsvp_filter[rsvp_class_to_filter_num(obj->class)], 
441                                      offset, obj_length, obj->class);
442
443             offset2 = offset + sizeof(rsvp_object);
444
445             switch(obj->class) {
446
447             case RSVP_CLASS_SESSION :           
448                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_session);
449                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
450                                     obj_length);
451                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
452                                     "Class number: %d - %s", 
453                                     obj->class, object_type);
454                 switch(obj->type) {
455                 case 1: {
456                     /*rsvp_session_ipv4 *sess = (rsvp_session_ipv4 *)obj;*/
457                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
458                                         "C-type: 1 - IPv4");
459                     /*
460                     proto_tree_add_text(rsvp_object_tree, offset2, 4, 
461                                         "Destination address: %s", 
462                                         ip_to_str((guint8 *) &(sess->destination)));
463                     */
464                     proto_tree_add_item(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_IP], 
465                                         offset2, 4, pntohl(pd+offset2));
466
467                     /* proto_tree_add_text(rsvp_object_tree, offset2+4, 1,
468                        "Protocol: %d", sess->protocol);*/
469                     proto_tree_add_item(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_PROTO], 
470                                         offset2+4, 1, pntohs(pd+offset2+4));
471                     proto_tree_add_text(rsvp_object_tree, offset2+5, 1,
472                                         "Flags: %d", pntohs(pd+offset2+5));
473                     /* proto_tree_add_text(rsvp_object_tree, offset2+6, 2,
474                                         "Destination port: %d", 
475                                         pntohs(pd+offset2+6)); */
476                     proto_tree_add_item(rsvp_object_tree, rsvp_filter[RSVPF_SESSION_PORT], 
477                                         offset2+6, 2, pntohs(pd+offset2+6));
478                     break;
479                 }
480
481                 case 2: {
482                     rsvp_session_ipv6 *sess = (rsvp_session_ipv6 *)obj;
483                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
484                                         "C-type: 2 - IPv6");
485                     proto_tree_add_text(rsvp_object_tree, offset2, 4, 
486                                         "Destination address: %s", 
487                                         ip6_to_str(&(sess->destination)));
488                     proto_tree_add_text(rsvp_object_tree, offset2+16, 1,
489                                         "Protocol: %d", sess->protocol);
490                     proto_tree_add_text(rsvp_object_tree, offset2+17, 1,
491                                         "Flags: %d", sess->flags);
492                     proto_tree_add_text(rsvp_object_tree, offset2+18, 2,
493                                         "Destination port: %d", 
494                                         pntohs(pd+offset2+18));
495                     break;
496                 }
497                 
498                 default: {
499                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
500                                         "C-type: Unknown (%d)",
501                                         obj->type);
502                     i = obj_length - sizeof(rsvp_object);
503                     proto_tree_add_text(rsvp_object_tree, offset2, i,
504                                         "Data (%d bytes)", i);
505                 }
506                 }
507                 break;
508                 
509             case RSVP_CLASS_HOP :               
510                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_hop);
511                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
512                                     obj_length);
513                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
514                                     "Class number: %d - %s", 
515                                     obj->class, object_type);
516                 switch(obj->type) {
517                 case 1: {
518                     rsvp_hop_ipv4 *hop = (rsvp_hop_ipv4 *)obj;
519                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
520                                         "C-type: 1 - IPv4");
521                     proto_tree_add_text(rsvp_object_tree, offset2, 4, 
522                                         "Neighbor address: %s", 
523                                         ip_to_str((guint8 *) &(hop->neighbor)));
524                     proto_tree_add_text(rsvp_object_tree, offset2+4, 4,
525                                         "Logical interface: %0x", 
526                                         pntohl(pd+offset2+4));
527                     break;
528                 }
529
530                 case 2: {
531                     rsvp_hop_ipv6 *hop = (rsvp_hop_ipv6 *)obj;
532                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
533                                         "C-type: 2 - IPv6");
534                     proto_tree_add_text(rsvp_object_tree, offset2, 4, 
535                                         "Neighbor address: %s", 
536                                         ip6_to_str(&(hop->neighbor)));
537                     proto_tree_add_text(rsvp_object_tree, offset2+16, 4,
538                                         "Logical interface: %0x", 
539                                         pntohl(pd+offset2+16));
540                     break;
541                 }
542                 
543                 default: {
544                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
545                                         "C-type: Unknown (%d)",
546                                         obj->type);
547                     i = obj_length - sizeof(rsvp_object);
548                     proto_tree_add_text(rsvp_object_tree, offset2, i,
549                                         "Data (%d bytes)", i);
550                 }
551                 }
552                 break;
553                 
554             case RSVP_CLASS_TIME_VALUES : 
555                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_time_values);
556                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
557                                     obj_length);
558                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
559                                     "Class number: %d - %s", 
560                                     obj->class, object_type);
561                 switch(obj->type) {
562                 case 1: {
563                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
564                                         "C-type: 1");
565                     proto_tree_add_text(rsvp_object_tree, offset2, 4, 
566                                         "Refresh interval: %u ms (%u seconds)",
567                                         pntohl(pd+offset2),
568                                         pntohl(pd+offset2)/1000);
569                     break;
570                 }
571
572                 default: {
573                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
574                                         "C-type: Unknown (%d)",
575                                         obj->type);
576                     i = obj_length - sizeof(rsvp_object);
577                     proto_tree_add_text(rsvp_object_tree, offset2, i,
578                                         "Data (%d bytes)", i);
579                     break;
580                 }
581                 }
582                 break;
583
584             case RSVP_CLASS_ERROR :
585                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_error);
586                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
587                                     obj_length);
588                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
589                                     "Class number: %d - %s", 
590                                     obj->class, object_type);
591                 switch(obj->type) {
592                 case 1: {
593                     rsvp_error_ipv4 *err = (rsvp_error_ipv4 *)obj;
594                     char *err_str = match_strval(err->error_code, rsvp_error_vals);
595                     if (!err_str) err_str = "Unknown";
596
597                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
598                                         "C-type: 1 - IPv4");
599                     proto_tree_add_text(rsvp_object_tree, offset2, 4, 
600                                         "Error node: %s",
601                                         ip_to_str((guint8 *) &(err->error_node)));
602                     proto_tree_add_text(rsvp_object_tree, offset2+4, 1,
603                                         "Flags: %02x", err->flags);
604                     proto_tree_add_text(rsvp_object_tree, offset2+5, 1,
605                                         "Error code: %d - %s", err->error_code,
606                                         err_str);
607                     proto_tree_add_text(rsvp_object_tree, offset2+6, 2,
608                                         "Error value: %d", pntohs(pd+offset2+6));
609                     
610                     break;
611                 }
612
613                 case 2: {
614                     rsvp_error_ipv6 *err = (rsvp_error_ipv6 *)obj;
615                     char *err_str = match_strval(err->error_code, rsvp_error_vals);
616                     if (!err_str) err_str = "Unknown";
617                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
618                                         "C-type: 2 - IPv6");
619                     proto_tree_add_text(rsvp_object_tree, offset2, 4, 
620                                         "Error node: %s",
621                                         ip6_to_str(&(err->error_node)));
622                     proto_tree_add_text(rsvp_object_tree, offset2+16, 1,
623                                         "Flags: %02x", err->flags);
624                     proto_tree_add_text(rsvp_object_tree, offset2+17, 1,
625                                         "Error code: %d - %s", err->error_code,
626                                         err_str);
627                     proto_tree_add_text(rsvp_object_tree, offset2+18, 2,
628                                         "Error value: %d", pntohs(pd+offset2+18));
629                     
630                     break;
631                 }
632                 
633                 default: {
634                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
635                                         "C-type: Unknown (%d)",
636                                         obj->type);
637                     i = obj_length - sizeof(rsvp_object);
638                     proto_tree_add_text(rsvp_object_tree, offset2, i,
639                                         "Data (%d bytes)", i);
640                 }
641                 }
642                 break;
643                 
644
645             case RSVP_CLASS_SCOPE : 
646                 mylen = obj_length;
647                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_scope);
648                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
649                                     obj_length);
650                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
651                                     "Class number: %d - %s", 
652                                     obj->class, object_type);
653                 switch(obj->type) {
654                 case 1: {
655                     unsigned long ip;
656                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
657                                         "C-type: 1 - IPv4");
658                     while (mylen > sizeof(rsvp_object)) {
659                         ip = pntohl(pd+offset2);
660                         proto_tree_add_text(rsvp_object_tree, offset2, 4, 
661                                             "IPv4 Address: %s",
662                                             ip_to_str((guint8 *) &ip));
663                         offset2 += 4;
664                         mylen -= 4;
665                     }
666                     break;
667                 }
668
669                 case 2: {
670                     struct e_in6_addr *ip;
671                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
672                                         "C-type: 2 - IPv6");
673                     while (mylen>sizeof(rsvp_object)) {
674                         ip = (struct e_in6_addr *)pd+offset2;
675                         proto_tree_add_text(rsvp_object_tree, offset2, 16, 
676                                             "IPv6 Address: %s",
677                                             ip6_to_str(ip));
678                         offset2 += 16;
679                         mylen -= 16;
680                     }
681                     break;
682                 }
683                 
684                 default: {
685                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
686                                         "C-type: Unknown (%d)",
687                                         obj->type);
688                     i = obj_length - sizeof(rsvp_object);
689                     proto_tree_add_text(rsvp_object_tree, offset2, i,
690                                         "Data (%d bytes)", i);
691                 }
692                 }
693                 break;
694                 
695             case RSVP_CLASS_STYLE : 
696                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_style);
697                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
698                                     obj_length);
699                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
700                                     "Class number: %d - %s", 
701                                     obj->class, object_type);
702                 switch(obj->type) {
703                 case 1: {
704                     unsigned long ip = pntohl(pd+offset2);
705                     char *style_str = match_strval(ip, style_vals);
706                     if (!style_str) style_str = "Unknown";
707                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
708                                         "C-type: 1");
709                     proto_tree_add_text(rsvp_object_tree, offset2+5, 1,
710                                         "Style: %ld - %s", ip, style_str);
711                     break;
712                 }
713
714                 default: {
715                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
716                                         "C-type: Unknown (%d)",
717                                         obj->type);
718                     i = obj_length - sizeof(rsvp_object);
719                     proto_tree_add_text(rsvp_object_tree, offset2, i,
720                                         "Data (%d bytes)", i);
721                     break;
722                 }
723                 }
724                 break;
725             
726             case RSVP_CLASS_CONFIRM :           
727                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_confirm);
728                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
729                                     obj_length);
730                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
731                                     "Class number: %d - %s", 
732                                     obj->class, object_type);
733                 switch(obj->type) {
734                 case 1: {
735                     rsvp_confirm_ipv4 *confirm = (rsvp_confirm_ipv4 *)obj;
736                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
737                                         "C-type: 1 - IPv4");
738                     proto_tree_add_text(rsvp_object_tree, offset2, 4, 
739                                         "Receiver address: %s", 
740                                         ip_to_str((guint8 *) &(confirm->receiver)));
741                     break;
742                 }
743
744                 case 2: {
745                     rsvp_confirm_ipv6 *confirm = (rsvp_confirm_ipv6 *)obj;
746                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
747                                         "C-type: 2 - IPv6");
748                     proto_tree_add_text(rsvp_object_tree, offset2, 16, 
749                                         "Receiver address: %s", 
750                                         ip6_to_str(&(confirm->receiver)));
751                     break;
752                 }
753
754                 default: {
755                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
756                                         "C-type: Unknown (%d)",
757                                         obj->type);
758                     i = obj_length - sizeof(rsvp_object);
759                     proto_tree_add_text(rsvp_object_tree, offset2, i,
760                                         "Data (%d bytes)", i);
761                 }
762                 }
763                 break;
764
765             case RSVP_CLASS_SENDER_TEMPLATE :
766                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_sender_template);
767                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
768                                     obj_length);
769                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
770                                     "Class number: %d - %s", 
771                                     obj->class, object_type);
772                 goto common_template;
773             case RSVP_CLASS_FILTER_SPEC :
774                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_filter_spec);
775                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
776                                     obj_length);
777                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
778                                     "Class number: %d - %s", 
779                                     obj->class, object_type);
780             common_template:
781                 switch(obj->type) {
782                 case 1: {
783                     rsvp_template_ipv4 *tem = (rsvp_template_ipv4 *)obj;
784                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
785                                         "C-type: 1 - IPv4");
786                     proto_tree_add_text(rsvp_object_tree, offset2, 4, 
787                                         "Source address: %s", 
788                                         ip_to_str((guint8 *) &(tem->source)));
789                     proto_tree_add_text(rsvp_object_tree, offset2+6, 2,
790                                         "Source port: %d", pntohs(pd+offset2+6));
791                     break;
792                 }
793
794                 case 2: {
795                     rsvp_template_ipv6 *tem = (rsvp_template_ipv6 *)obj;
796                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
797                                         "C-type: 2 - IPv6");
798                     proto_tree_add_text(rsvp_object_tree, offset2, 16, 
799                                         "Source address: %s", 
800                                         ip6_to_str(&(tem->source)));
801                     proto_tree_add_text(rsvp_object_tree, offset2+18, 2,
802                                         "Source port: %d", pntohs(pd+offset2+18));
803                     break;
804                 }
805                 
806                 default: {
807                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
808                                         "C-type: Unknown (%d)",
809                                         obj->type);
810                     i = obj_length - sizeof(rsvp_object);
811                     proto_tree_add_text(rsvp_object_tree, offset2, i,
812                                         "Data (%d bytes)", i);
813                 }
814                 }
815                 break;
816
817             case RSVP_CLASS_SENDER_TSPEC : {
818                 rsvp_tspec *tspec = (rsvp_tspec *)obj;
819                 IS_tspec *ist;
820                 QUAL_tspec *qt;
821                 service_hdr  *sh;
822                 char *str;
823
824                 mylen = obj_length;
825                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_sender_tspec);
826                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
827                                     obj_length);
828                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
829                                     "Class number: %d - %s", 
830                                     obj->class, object_type);
831
832                 proto_tree_add_text(rsvp_object_tree, offset2, 1, 
833                                  "Message format version: %d", 
834                                  tspec->version>>4);
835                 proto_tree_add_text(rsvp_object_tree, offset2+2, 2, 
836                                  "Data length: %d words, not including header", 
837                                  pntohs(pd+offset2+2));
838
839                 mylen -=4;
840                 offset2 +=4;
841                 while (mylen > 4) {
842                     sh = (service_hdr *)(pd+offset2);
843                     str = match_strval(sh->service_num, qos_vals);
844                     if (!str) str = "Unknown";
845
846                     proto_tree_add_text(rsvp_object_tree, offset2, 1, 
847                                         "Service header: %d - %s", 
848                                         sh->service_num, str);
849                     proto_tree_add_text(rsvp_object_tree, offset2+2, 2, 
850                                  "Length of service %d data: %d words, " 
851                                  "not including header", 
852                                  sh->service_num,
853                                  ntohs(sh->length));
854
855                     offset2+=4; mylen -=4; 
856
857                     switch(sh->service_num) {
858                         
859                     case QOS_TSPEC :
860                         ist = (IS_tspec *)sh;
861
862                         /* Token bucket TSPEC */
863                         str = match_strval(ist->param_id, svc_vals);
864                         if (!str) str = "Unknown";
865                         proto_tree_add_text(rsvp_object_tree, offset2, 1, 
866                                             "Parameter %d - %s", 
867                                             ist->param_id, str);
868                         proto_tree_add_text(rsvp_object_tree, offset2+1, 1, 
869                                             "Parameter %d flags: %d", 
870                                             ist->param_id, ist->flags_tspec);
871                         proto_tree_add_text(rsvp_object_tree, offset2+2, 2, 
872                                             "Parameter %d data length: %d words, " 
873                                             "not including header",
874                                             ist->param_id,
875                                             /* pntohs(pd+offset2+10)); */
876                                             ntohs(ist->parameter_length));
877                         proto_tree_add_text(rsvp_object_tree, offset2+4, 4, 
878                                             "Token bucket rate: %ld", 
879                                             ieee_to_long(pd+offset2+4));
880                         proto_tree_add_text(rsvp_object_tree, offset2+8, 4, 
881                                             "Token bucket size: %ld", 
882                                             ieee_to_long(pd+offset2+8));
883                         proto_tree_add_text(rsvp_object_tree, offset2+12, 4, 
884                                             "Peak data rate: %ld", 
885                                             ieee_to_long(pd+offset2+12));
886                         proto_tree_add_text(rsvp_object_tree, offset2+16, 4, 
887                                             "Minimum policed unit: %d", 
888                                             pntohl(pd+offset2+16));
889                         proto_tree_add_text(rsvp_object_tree, offset2+20, 4, 
890                                             "Maximum policed unit: %d", 
891                                             pntohl(pd+offset2+20));
892
893                         break;
894
895                     case QOS_QUALITATIVE :
896                         qt = (QUAL_tspec *)sh;
897
898                         /* Token bucket TSPEC */
899                         str = match_strval(qt->param_id, svc_vals);
900                         if (!str) str = "Unknown";
901                         proto_tree_add_text(rsvp_object_tree, offset2, 1, 
902                                             "Parameter %d - %s", 
903                                             qt->param_id, str);
904                         proto_tree_add_text(rsvp_object_tree, offset2+1, 1, 
905                                             "Parameter %d flags: %d", 
906                                             qt->param_id, qt->flags_tspec);
907                         proto_tree_add_text(rsvp_object_tree, offset2+2, 2, 
908                                             "Parameter %d data length: %d words, " 
909                                             "not including header",
910                                             qt->param_id,
911                                             /* pntohs(pd+offset2+10)); */
912                                             ntohs(qt->parameter_length));
913                         proto_tree_add_text(rsvp_object_tree, offset2+4, 4, 
914                                             "Maximum policed unit: %d", 
915                                             pntohl(pd+offset2+4));
916
917                         break;
918
919                     }
920                     offset2 += ntohs(sh->length)*4; 
921                     mylen -= ntohs(sh->length)*4;
922                 }
923                     
924                 break;
925             }
926
927             case RSVP_CLASS_FLOWSPEC : {
928                 rsvp_flowspec *flowspec = (rsvp_flowspec *)obj;
929                 IS_flowspec *isf;
930                 QUAL_flowspec *qf;
931                 service_hdr *sh;
932                 int mylen;
933
934                 char *str;
935
936                 mylen = obj_length;
937                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_flowspec);
938                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
939                                     obj_length);
940                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
941                                     "Class number: %d - %s", 
942                                     obj->class, object_type);
943
944                 proto_tree_add_text(rsvp_object_tree, offset2, 1, 
945                                  "Message format version: %d", 
946                                  flowspec->version>>4);
947                 proto_tree_add_text(rsvp_object_tree, offset2+2, 2, 
948                                  "Data length: %d words, not including header", 
949                                  pntohs(pd+offset2+2));
950
951                 mylen -=4;
952                 offset2+=4;
953                 while (mylen > 4) {
954                     sh = (service_hdr *)(pd+offset2);
955                     str = match_strval(sh->service_num, intsrv_services_str);
956                     if (!str) str = "Unknown";
957
958                     proto_tree_add_text(rsvp_object_tree, offset2, 1, 
959                                         "Service header: %d - %s", 
960                                         sh->service_num, str);
961                     proto_tree_add_text(rsvp_object_tree, offset2+2, 2, 
962                                  "Length of service %d data: %d words, " 
963                                  "not including header", 
964                                  sh->service_num,
965                                  ntohs(sh->length));
966
967                     offset2+=4; mylen -=4; 
968
969                     switch(sh->service_num) {
970
971                     case QOS_CONTROLLED_LOAD :
972                     case QOS_GUARANTEED :
973                         /* Treat both these the same for now */
974                         isf = (IS_flowspec *)sh;
975
976                         str = match_strval(isf->tspec.param_id, svc_vals);
977                         if (!str) str = "Unknown";
978                         proto_tree_add_text(rsvp_object_tree, offset2, 1, 
979                                             "Parameter %d - %s", 
980                                             isf->tspec.param_id, str);
981                         proto_tree_add_text(rsvp_object_tree, offset2+1, 1, 
982                                             "Parameter %d flags: %d", 
983                                             isf->tspec.param_id, isf->tspec.flags_tspec);
984                         proto_tree_add_text(rsvp_object_tree, offset2+2, 2, 
985                                             "Parameter %d data length: %d words, " 
986                                             "not including header",
987                                             isf->tspec.param_id,
988                                             ntohs(isf->tspec.parameter_length));
989                         proto_tree_add_text(rsvp_object_tree, offset2+4, 4, 
990                                             "Token bucket rate: %ld", 
991                                             ieee_to_long(pd+offset2+4));
992                         proto_tree_add_text(rsvp_object_tree, offset2+8, 4, 
993                                             "Token bucket size: %ld", 
994                                             ieee_to_long(pd+offset2+8));
995                         proto_tree_add_text(rsvp_object_tree, offset2+12, 4, 
996                                             "Peak data rate: %ld", 
997                                             ieee_to_long(pd+offset2+12));
998                         proto_tree_add_text(rsvp_object_tree, offset2+16, 4, 
999                                             "Minimum policed unit: %d", 
1000                                             pntohl(pd+offset2+16));
1001                         proto_tree_add_text(rsvp_object_tree, offset2+20, 4, 
1002                                             "Maximum policed unit: %d", 
1003                                             pntohl(pd+offset2+20));
1004                         if (sh->service_num!=QOS_GUARANTEED)
1005                             break;
1006                         
1007                         /* Guaranteed-rate RSpec */
1008                         str = match_strval(isf->rspec.param_id, svc_vals);
1009                         if (!str) str="Unknown";
1010                         proto_tree_add_text(rsvp_object_tree, offset2+24, 1, 
1011                                             "Parameter %d - %s", 
1012                                             isf->rspec.param_id, str);
1013                         proto_tree_add_text(rsvp_object_tree, offset2+25, 1, 
1014                                             "Parameter %d flags: %d", 
1015                                             isf->rspec.param_id, isf->rspec.flags_rspec);
1016                         proto_tree_add_text(rsvp_object_tree, offset2+26, 2, 
1017                                             "Parameter %d data length: %d words, " 
1018                                             "not including header",
1019                                             isf->rspec.param_id,
1020                                             ntohs(isf->rspec.param2_length));
1021
1022                         proto_tree_add_text(rsvp_object_tree, offset2+28, 4, 
1023                                             "Rate: %ld", 
1024                                             ieee_to_long(pd+offset2+28));
1025                         proto_tree_add_text(rsvp_object_tree, offset2+32, 4, 
1026                                             "Slack term: %d", 
1027                                             pntohl(pd+offset2+32));
1028                         break;
1029
1030                     case QOS_QUALITATIVE :
1031                         qf = (QUAL_flowspec *)sh;
1032
1033                         str = match_strval(qf->param_id, svc_vals);
1034                         if (!str) str = "Unknown";
1035                         proto_tree_add_text(rsvp_object_tree, offset2, 1, 
1036                                             "Parameter %d - %s", 
1037                                             qf->param_id, str);
1038                         proto_tree_add_text(rsvp_object_tree, offset2+1, 1, 
1039                                             "Parameter %d flags: %d", 
1040                                             qf->param_id, qf->flags_tspec);
1041                         proto_tree_add_text(rsvp_object_tree, offset2+2, 2, 
1042                                             "Parameter %d data length: %d words, " 
1043                                             "not including header",
1044                                             qf->param_id,
1045                                             ntohs(qf->parameter_length));
1046                         proto_tree_add_text(rsvp_object_tree, offset2+4, 4, 
1047                                             "Maximum policed unit: %ld", 
1048                                             pntohl(pd+offset2+4));
1049                         
1050                         break;
1051                     }
1052                     offset2 += ntohs(sh->length)*4;
1053                     mylen -= ntohs(sh->length)*4;
1054                 }
1055
1056                 break;
1057             }
1058
1059             case RSVP_CLASS_ADSPEC : {
1060                 proto_tree *adspec_tree;
1061                 service_hdr *shdr;
1062                 param_hdr *phdr; 
1063
1064                 char *str;
1065
1066                 mylen = obj_length;
1067                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_adspec);
1068                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
1069                                     obj_length);
1070                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
1071                                     "Class number: %d - %s", 
1072                                     obj->class, object_type);
1073                 
1074                 proto_tree_add_text(rsvp_object_tree, offset2, 1, 
1075                                     "Message format version: %d", 
1076                                     (*((unsigned char *)pd+offset2))>>4);
1077                 proto_tree_add_text(rsvp_object_tree, offset2+2, 2, 
1078                                     "Data length: %d words, not including header", 
1079                                     pntohs(pd+offset2+2));
1080                 offset2+=4;
1081                 mylen -= 4;
1082                 while (mylen > 4) {
1083                     shdr = (service_hdr *)(pd + offset2);
1084                     str = match_strval(shdr->service_num, intsrv_services_str);
1085
1086                     ti = proto_tree_add_text(rsvp_object_tree, offset2, 
1087                                              (pntohs(&shdr->length)+1)<<2,
1088                                              str?str:"Unknown");
1089                     adspec_tree = proto_item_add_subtree(ti,
1090                                         ett_rsvp_adspec_subtree);
1091                     proto_tree_add_text(adspec_tree, offset2, 1,
1092                                         "Service header %d - %s",
1093                                         shdr->service_num, str);
1094                     proto_tree_add_text(adspec_tree, offset2+1, 1,
1095                                         (shdr->break_bit&0x80)?
1096                                         "Break bit set":"Break bit not set");
1097                     proto_tree_add_text(adspec_tree, offset2+2, 2, 
1098                                         "Data length: %d words, not including header", 
1099                                         pntohs(&shdr->length));
1100                     offset2+=4; i=(pntohs(&shdr->length)+1)<<2; mylen-=4;
1101                     while (i>4) {
1102                         phdr = (param_hdr *)(pd + offset2);
1103                         str = match_strval(phdr->id, adspec_params);
1104                         if (str) {
1105                             switch(phdr->id) {
1106                             case 4:
1107                             case 8:
1108                             case 10:
1109                             case 133:
1110                             case 134:
1111                             case 135:
1112                             case 136:
1113                                 /* 32-bit unsigned integer */
1114                                 proto_tree_add_text(adspec_tree, offset2, 
1115                                                     (pntohs(&phdr->length)+1)<<2,
1116                                                     "%s - %lu (type %d, length %d)",
1117                                                     str, 
1118                                                     (unsigned long)pntohl(&phdr->dataval), 
1119                                                     phdr->id, pntohs(&phdr->length));
1120                                 break;
1121                                 
1122                             case 6:
1123                                 /* IEEE float */
1124                                 proto_tree_add_text(adspec_tree, offset2, 
1125                                                     (pntohs(&phdr->length)+1)<<2,
1126                                                     "%s - %lu (type %d, length %d)",
1127                                                     str, 
1128                                                     ieee_to_long(&phdr->dataval), 
1129                                                     phdr->id, pntohs(&phdr->length));
1130                                 break;
1131                             default: 
1132                                 proto_tree_add_text(adspec_tree, offset2, 
1133                                                     (pntohs(&phdr->length)+1)<<2,
1134                                                     "%s (type %d, length %d)",
1135                                                     str, 
1136                                                     phdr->id, pntohs(&phdr->length));
1137                             }
1138                         } else {
1139                             proto_tree_add_text(adspec_tree, offset2, 
1140                                                 (pntohs(&phdr->length)+1)<<2,
1141                                                 "Unknown (type %d, length %d)",
1142                                                 phdr->id, pntohs(&phdr->length));
1143                         }
1144                         offset2+=(pntohs(&phdr->length)+1)<<2;
1145                         i-=(pntohs(&phdr->length)+1)<<2;
1146                         mylen-=(pntohs(&phdr->length)+1)<<2;
1147                     }
1148                 }
1149                 break;
1150             }
1151
1152             case RSVP_CLASS_INTEGRITY :
1153                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_integrity);
1154                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
1155                                     obj_length);
1156                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
1157                                     "Class number: %d - %s", 
1158                                     obj->class, object_type);
1159                 goto default_class;
1160
1161             case RSVP_CLASS_POLICY :
1162                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_policy);
1163                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
1164                                     obj_length);
1165                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
1166                                     "Class number: %d - %s", 
1167                                     obj->class, object_type);
1168                 goto default_class;
1169
1170             default :
1171                 rsvp_object_tree = proto_item_add_subtree(ti, ett_rsvp_unknown_class);
1172                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
1173                                     obj_length);
1174                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
1175                                     "Class number: %d - %s", 
1176                                     obj->class, object_type);
1177             default_class:
1178                 i = obj_length - sizeof(rsvp_object);
1179                 proto_tree_add_text(rsvp_object_tree, offset2, i,
1180                                  "Data (%d bytes)", i);
1181                 break;
1182
1183             case RSVP_CLASS_NULL :
1184                 break;
1185
1186             }  
1187             
1188             offset += obj_length;
1189             len += obj_length;
1190         }
1191     }
1192 }
1193
1194 void
1195 proto_register_rsvp(void)
1196 {
1197         static gint *ett[] = {
1198                 &ett_rsvp,
1199                 &ett_rsvp_hdr,
1200                 &ett_rsvp_session,
1201                 &ett_rsvp_hop,
1202                 &ett_rsvp_time_values,
1203                 &ett_rsvp_error,
1204                 &ett_rsvp_scope,
1205                 &ett_rsvp_style,
1206                 &ett_rsvp_confirm,
1207                 &ett_rsvp_sender_template,
1208                 &ett_rsvp_filter_spec,
1209                 &ett_rsvp_sender_tspec,
1210                 &ett_rsvp_flowspec,
1211                 &ett_rsvp_adspec,
1212                 &ett_rsvp_adspec_subtree,
1213                 &ett_rsvp_integrity,
1214                 &ett_rsvp_policy,
1215                 &ett_rsvp_unknown_class,
1216         };
1217
1218         proto_rsvp = proto_register_protocol("Resource ReserVation Protocol (RSVP)", "rsvp");
1219         proto_register_field_array(proto_rsvp, rsvpf_info, array_length(rsvpf_info));
1220         proto_register_subtree_array(ett, array_length(ett));
1221 }