Add a comment.
[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.5 1999/08/12 05:19:05 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-ipv6.h"
73 #include "packet-rsvp.h"
74
75 static int proto_rsvp = -1;
76
77 /* Stuff for IEEE float handling */
78
79 #define IEEE_NUMBER_WIDTH       32      /* bits in number */
80 #define IEEE_EXP_WIDTH          8       /* bits in exponent */
81 #define IEEE_MANTISSA_WIDTH     23      /* IEEE_NUMBER_WIDTH - 1 - IEEE_EXP_WIDTH */
82
83 #define IEEE_SIGN_MASK          0x80000000
84 #define IEEE_EXPONENT_MASK      0x7F800000
85 #define IEEE_MANTISSA_MASK      0x007FFFFF
86 #define IEEE_INFINITY           IEEE_EXPONENT_MASK
87
88 #define IEEE_IMPLIED_BIT (1 << IEEE_MANTISSA_WIDTH)
89 #define IEEE_INFINITE ((1 << IEEE_EXP_WIDTH) - 1)
90 #define IEEE_BIAS ((1 << (IEEE_EXP_WIDTH - 1)) - 1)
91
92 #define MINUS_INFINITY (signed)0x80000000L
93 #define PLUS_INFINITY  0x7FFFFFFF
94
95 static inline int ieee_float_is_zero (long number)
96 {
97     return(!(number & ~IEEE_SIGN_MASK));
98 }
99
100 /*
101  * simple conversion: ieee floating point to long
102  */
103 static long ieee_to_long (const void *p)
104 {
105     long number;
106     long sign;
107     long exponent;
108     long mantissa;
109
110     number = pntohl(p);
111     sign = number & IEEE_SIGN_MASK;
112     exponent = number & IEEE_EXPONENT_MASK;
113     mantissa = number & IEEE_MANTISSA_MASK;
114
115     if (ieee_float_is_zero(number)) {
116         /* number is zero, unnormalized, or not-a-number */
117         return 0;
118     }
119     if (IEEE_INFINITY == exponent) {
120         /* number is positive or negative infinity, or a special value */
121         return (sign? MINUS_INFINITY: PLUS_INFINITY);
122     }
123
124     exponent = (exponent >> IEEE_MANTISSA_WIDTH) - IEEE_BIAS;
125     if (exponent < 0) {
126         /* number is between zero and one */
127         return 0;
128     }
129
130     mantissa |= IEEE_IMPLIED_BIT;
131     if (exponent <= IEEE_MANTISSA_WIDTH)
132         mantissa >>= IEEE_MANTISSA_WIDTH - exponent;
133     else
134         mantissa <<= exponent - IEEE_MANTISSA_WIDTH;
135
136     if (sign)
137         return -mantissa;
138     else
139         return mantissa;
140 }
141
142 void 
143 dissect_rsvp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) 
144 {
145     proto_tree *rsvp_tree = NULL, *ti; 
146     proto_tree *rsvp_header_tree;
147     proto_tree *rsvp_object_tree;
148     char *packet_type, *object_type;
149     rsvp_header *hdr;
150     rsvp_object *obj;
151     int i, len, mylen;
152     int msg_length;
153     int obj_length;
154     int offset2;
155
156     hdr = (rsvp_header *)&pd[offset];
157     packet_type = match_strval(hdr->message_type, message_type_vals);
158     if (check_col(fd, COL_PROTOCOL))
159         col_add_str(fd, COL_PROTOCOL, "RSVP");
160     if (check_col(fd, COL_INFO)) {
161         if (packet_type != NULL)
162             col_add_str(fd, COL_INFO, packet_type); 
163         else
164             col_add_fstr(fd, COL_INFO, "Unknown (%d)", hdr->message_type); 
165     }
166
167     if (tree) {
168         msg_length = pntohs(pd+offset+6);
169         ti = proto_tree_add_item(tree, proto_rsvp, offset, msg_length, NULL);
170         rsvp_tree = proto_item_add_subtree(ti, ETT_RSVP);
171
172         ti = proto_tree_add_text(rsvp_tree, offset, 
173                               sizeof(rsvp_header), "RSVP Header"); 
174         rsvp_header_tree = proto_item_add_subtree(ti, ETT_RSVP_HDR);
175
176         proto_tree_add_text(rsvp_header_tree, offset, 1, "RSVP Version: %d", 
177                          (hdr->ver_flags & 0xf0)>>4);  
178         proto_tree_add_text(rsvp_header_tree, offset, 1, "Flags: %02X",
179                          hdr->ver_flags & 0xf);  
180         proto_tree_add_text(rsvp_header_tree, offset+1, 1, "Message Type: %d - %s",
181                          hdr->message_type, 
182                          packet_type?packet_type:"Unknown");
183         proto_tree_add_text(rsvp_header_tree, offset + 2 , 2, "Message Checksum");
184         proto_tree_add_text(rsvp_header_tree, offset + 4 , 1, "Sending TTL: %d",
185                          hdr->sending_ttl);
186         proto_tree_add_text(rsvp_header_tree, offset + 6 , 2, "Message length: %d",
187                          msg_length);
188
189         offset += sizeof(rsvp_header);
190         len = 0;
191         while (len + sizeof(rsvp_header) < msg_length) {
192             obj = (rsvp_object *)&pd[offset];
193             obj_length = pntohs(pd+offset);
194             if (offset + obj_length > fd->cap_len) {
195                 proto_tree_add_text(rsvp_tree, offset, 1, 
196                                  "Further data not captured");
197                 break;
198             }
199             
200             object_type = match_strval(obj->class, rsvp_class_vals);
201             if (!object_type) object_type = "Unknown";
202             ti = proto_tree_add_text(rsvp_tree, offset, 
203                                   obj_length, 
204                                   "%s (%d)", object_type, obj->class);
205
206             offset2 = offset + sizeof(rsvp_object);
207
208             switch(obj->class) {
209
210             case RSVP_CLASS_SESSION :           
211                 rsvp_object_tree = proto_item_add_subtree(ti, ETT_RSVP_SESSION);
212                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
213                                     obj_length);
214                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
215                                     "Class number: %d - %s", 
216                                     obj->class, object_type);
217                 switch(obj->type) {
218                 case 1: {
219                     rsvp_session_ipv4 *sess = (rsvp_session_ipv4 *)obj;
220                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
221                                         "C-type: 1 - IPv4");
222                     proto_tree_add_text(rsvp_object_tree, offset2, 4, 
223                                         "Destination address: %s", 
224                                         ip_to_str((guint8 *) &(sess->destination)));
225                     proto_tree_add_text(rsvp_object_tree, offset2+4, 1,
226                                         "Protocol: %d", sess->protocol);
227                     proto_tree_add_text(rsvp_object_tree, offset2+5, 1,
228                                         "Flags: %d", sess->flags);
229                     proto_tree_add_text(rsvp_object_tree, offset2+6, 2,
230                                         "Destination port: %d", 
231                                         pntohs(pd+offset2+6));
232                     break;
233                 }
234
235                 case 2: {
236                     rsvp_session_ipv6 *sess = (rsvp_session_ipv6 *)obj;
237                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
238                                         "C-type: 2 - IPv6");
239                     proto_tree_add_text(rsvp_object_tree, offset2, 4, 
240                                         "Destination address: %s", 
241                                         ip6_to_str(&(sess->destination)));
242                     proto_tree_add_text(rsvp_object_tree, offset2+16, 1,
243                                         "Protocol: %d", sess->protocol);
244                     proto_tree_add_text(rsvp_object_tree, offset2+17, 1,
245                                         "Flags: %d", sess->flags);
246                     proto_tree_add_text(rsvp_object_tree, offset2+18, 2,
247                                         "Destination port: %d", 
248                                         pntohs(pd+offset2+18));
249                     break;
250                 }
251                 
252                 default: {
253                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
254                                         "C-type: Unknown (%d)",
255                                         obj->type);
256                     i = obj_length - sizeof(rsvp_object);
257                     proto_tree_add_text(rsvp_object_tree, offset2, i,
258                                         "Data (%d bytes)", i);
259                 }
260                 }
261                 break;
262                 
263             case RSVP_CLASS_HOP :               
264                 rsvp_object_tree = proto_item_add_subtree(ti, ETT_RSVP_HOP);
265                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
266                                     obj_length);
267                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
268                                     "Class number: %d - %s", 
269                                     obj->class, object_type);
270                 switch(obj->type) {
271                 case 1: {
272                     rsvp_hop_ipv4 *hop = (rsvp_hop_ipv4 *)obj;
273                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
274                                         "C-type: 1 - IPv4");
275                     proto_tree_add_text(rsvp_object_tree, offset2, 4, 
276                                         "Neighbor address: %s", 
277                                         ip_to_str((guint8 *) &(hop->neighbor)));
278                     proto_tree_add_text(rsvp_object_tree, offset2+4, 4,
279                                         "Logical interface: %0x", 
280                                         pntohl(pd+offset2+4));
281                     break;
282                 }
283
284                 case 2: {
285                     rsvp_hop_ipv6 *hop = (rsvp_hop_ipv6 *)obj;
286                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
287                                         "C-type: 2 - IPv6");
288                     proto_tree_add_text(rsvp_object_tree, offset2, 4, 
289                                         "Neighbor address: %s", 
290                                         ip6_to_str(&(hop->neighbor)));
291                     proto_tree_add_text(rsvp_object_tree, offset2+16, 4,
292                                         "Logical interface: %0x", 
293                                         pntohl(pd+offset2+16));
294                     break;
295                 }
296                 
297                 default: {
298                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
299                                         "C-type: Unknown (%d)",
300                                         obj->type);
301                     i = obj_length - sizeof(rsvp_object);
302                     proto_tree_add_text(rsvp_object_tree, offset2, i,
303                                         "Data (%d bytes)", i);
304                 }
305                 }
306                 break;
307                 
308             case RSVP_CLASS_TIME_VALUES : 
309                 rsvp_object_tree = proto_item_add_subtree(ti, ETT_RSVP_TIME_VALUES);
310                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
311                                     obj_length);
312                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
313                                     "Class number: %d - %s", 
314                                     obj->class, object_type);
315                 switch(obj->type) {
316                 case 1: {
317                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
318                                         "C-type: 1");
319                     proto_tree_add_text(rsvp_object_tree, offset2, 4, 
320                                         "Refresh interval: %u ms (%u seconds)",
321                                         pntohl(pd+offset2),
322                                         pntohl(pd+offset2)/1000);
323                     break;
324                 }
325
326                 default: {
327                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
328                                         "C-type: Unknown (%d)",
329                                         obj->type);
330                     i = obj_length - sizeof(rsvp_object);
331                     proto_tree_add_text(rsvp_object_tree, offset2, i,
332                                         "Data (%d bytes)", i);
333                     break;
334                 }
335                 }
336                 break;
337
338             case RSVP_CLASS_ERROR :
339                 rsvp_object_tree = proto_item_add_subtree(ti, ETT_RSVP_ERROR);
340                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
341                                     obj_length);
342                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
343                                     "Class number: %d - %s", 
344                                     obj->class, object_type);
345                 switch(obj->type) {
346                 case 1: {
347                     rsvp_error_ipv4 *err = (rsvp_error_ipv4 *)obj;
348                     char *err_str = match_strval(err->error_code, rsvp_error_vals);
349                     if (!err_str) err_str = "Unknown";
350
351                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
352                                         "C-type: 1 - IPv4");
353                     proto_tree_add_text(rsvp_object_tree, offset2, 4, 
354                                         "Error node: %s",
355                                         ip_to_str((guint8 *) &(err->error_node)));
356                     proto_tree_add_text(rsvp_object_tree, offset2+4, 1,
357                                         "Flags: %02x", err->flags);
358                     proto_tree_add_text(rsvp_object_tree, offset2+5, 1,
359                                         "Error code: %d - %s", err->error_code,
360                                         err_str);
361                     proto_tree_add_text(rsvp_object_tree, offset2+6, 2,
362                                         "Error value: %d", pntohs(pd+offset2+6));
363                     
364                     break;
365                 }
366
367                 case 2: {
368                     rsvp_error_ipv6 *err = (rsvp_error_ipv6 *)obj;
369                     char *err_str = match_strval(err->error_code, rsvp_error_vals);
370                     if (!err_str) err_str = "Unknown";
371                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
372                                         "C-type: 2 - IPv6");
373                     proto_tree_add_text(rsvp_object_tree, offset2, 4, 
374                                         "Error node: %s",
375                                         ip6_to_str(&(err->error_node)));
376                     proto_tree_add_text(rsvp_object_tree, offset2+16, 1,
377                                         "Flags: %02x", err->flags);
378                     proto_tree_add_text(rsvp_object_tree, offset2+17, 1,
379                                         "Error code: %d - %s", err->error_code,
380                                         err_str);
381                     proto_tree_add_text(rsvp_object_tree, offset2+18, 2,
382                                         "Error value: %d", pntohs(pd+offset2+18));
383                     
384                     break;
385                 }
386                 
387                 default: {
388                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
389                                         "C-type: Unknown (%d)",
390                                         obj->type);
391                     i = obj_length - sizeof(rsvp_object);
392                     proto_tree_add_text(rsvp_object_tree, offset2, i,
393                                         "Data (%d bytes)", i);
394                 }
395                 }
396                 break;
397                 
398
399             case RSVP_CLASS_SCOPE : 
400                 mylen = obj_length;
401                 rsvp_object_tree = proto_item_add_subtree(ti, ETT_RSVP_SCOPE);
402                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
403                                     obj_length);
404                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
405                                     "Class number: %d - %s", 
406                                     obj->class, object_type);
407                 switch(obj->type) {
408                 case 1: {
409                     unsigned long ip;
410                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
411                                         "C-type: 1 - IPv4");
412                     while (mylen > sizeof(rsvp_object)) {
413                         ip = pntohl(pd+offset2);
414                         proto_tree_add_text(rsvp_object_tree, offset2, 4, 
415                                             "IPv4 Address: %s",
416                                             ip_to_str((guint8 *) &ip));
417                         offset2 += 4;
418                         mylen -= 4;
419                     }
420                     break;
421                 }
422
423                 case 2: {
424                     struct e_in6_addr *ip;
425                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
426                                         "C-type: 2 - IPv6");
427                     while (mylen>sizeof(rsvp_object)) {
428                         ip = (struct e_in6_addr *)pd+offset2;
429                         proto_tree_add_text(rsvp_object_tree, offset2, 16, 
430                                             "IPv6 Address: %s",
431                                             ip6_to_str(ip));
432                         offset2 += 16;
433                         mylen -= 16;
434                     }
435                     break;
436                 }
437                 
438                 default: {
439                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
440                                         "C-type: Unknown (%d)",
441                                         obj->type);
442                     i = obj_length - sizeof(rsvp_object);
443                     proto_tree_add_text(rsvp_object_tree, offset2, i,
444                                         "Data (%d bytes)", i);
445                 }
446                 }
447                 break;
448                 
449             case RSVP_CLASS_STYLE : 
450                 rsvp_object_tree = proto_item_add_subtree(ti, ETT_RSVP_STYLE);
451                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
452                                     obj_length);
453                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
454                                     "Class number: %d - %s", 
455                                     obj->class, object_type);
456                 switch(obj->type) {
457                 case 1: {
458                     unsigned long ip = pntohl(pd+offset2);
459                     char *style_str = match_strval(ip, style_vals);
460                     if (!style_str) style_str = "Unknown";
461                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
462                                         "C-type: 1");
463                     proto_tree_add_text(rsvp_object_tree, offset2+5, 1,
464                                         "Style: %ld - %s", ip, style_str);
465                     break;
466                 }
467
468                 default: {
469                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
470                                         "C-type: Unknown (%d)",
471                                         obj->type);
472                     i = obj_length - sizeof(rsvp_object);
473                     proto_tree_add_text(rsvp_object_tree, offset2, i,
474                                         "Data (%d bytes)", i);
475                     break;
476                 }
477                 }
478                 break;
479             
480             case RSVP_CLASS_CONFIRM :           
481                 rsvp_object_tree = proto_item_add_subtree(ti, ETT_RSVP_CONFIRM);
482                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
483                                     obj_length);
484                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
485                                     "Class number: %d - %s", 
486                                     obj->class, object_type);
487                 switch(obj->type) {
488                 case 1: {
489                     rsvp_confirm_ipv4 *confirm = (rsvp_confirm_ipv4 *)obj;
490                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
491                                         "C-type: 1 - IPv4");
492                     proto_tree_add_text(rsvp_object_tree, offset2, 4, 
493                                         "Receiver address: %s", 
494                                         ip_to_str((guint8 *) &(confirm->receiver)));
495                     break;
496                 }
497
498                 case 2: {
499                     rsvp_confirm_ipv6 *confirm = (rsvp_confirm_ipv6 *)obj;
500                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
501                                         "C-type: 2 - IPv6");
502                     proto_tree_add_text(rsvp_object_tree, offset2, 16, 
503                                         "Receiver address: %s", 
504                                         ip6_to_str(&(confirm->receiver)));
505                     break;
506                 }
507
508                 default: {
509                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
510                                         "C-type: Unknown (%d)",
511                                         obj->type);
512                     i = obj_length - sizeof(rsvp_object);
513                     proto_tree_add_text(rsvp_object_tree, offset2, i,
514                                         "Data (%d bytes)", i);
515                 }
516                 }
517                 break;
518
519             case RSVP_CLASS_SENDER_TEMPLATE :
520                 rsvp_object_tree = proto_item_add_subtree(ti, ETT_RSVP_SENDER_TEMPLATE);
521                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
522                                     obj_length);
523                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
524                                     "Class number: %d - %s", 
525                                     obj->class, object_type);
526                 goto common_template;
527             case RSVP_CLASS_FILTER_SPEC :
528                 rsvp_object_tree = proto_item_add_subtree(ti, ETT_RSVP_FILTER_SPEC);
529                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
530                                     obj_length);
531                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
532                                     "Class number: %d - %s", 
533                                     obj->class, object_type);
534             common_template:
535                 switch(obj->type) {
536                 case 1: {
537                     rsvp_template_ipv4 *tem = (rsvp_template_ipv4 *)obj;
538                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
539                                         "C-type: 1 - IPv4");
540                     proto_tree_add_text(rsvp_object_tree, offset2, 4, 
541                                         "Source address: %s", 
542                                         ip_to_str((guint8 *) &(tem->source)));
543                     proto_tree_add_text(rsvp_object_tree, offset2+6, 2,
544                                         "Source port: %d", pntohs(pd+offset2+6));
545                     break;
546                 }
547
548                 case 2: {
549                     rsvp_template_ipv6 *tem = (rsvp_template_ipv6 *)obj;
550                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
551                                         "C-type: 2 - IPv6");
552                     proto_tree_add_text(rsvp_object_tree, offset2, 16, 
553                                         "Source address: %s", 
554                                         ip6_to_str(&(tem->source)));
555                     proto_tree_add_text(rsvp_object_tree, offset2+18, 2,
556                                         "Source port: %d", pntohs(pd+offset2+18));
557                     break;
558                 }
559                 
560                 default: {
561                     proto_tree_add_text(rsvp_object_tree, offset+3, 1, 
562                                         "C-type: Unknown (%d)",
563                                         obj->type);
564                     i = obj_length - sizeof(rsvp_object);
565                     proto_tree_add_text(rsvp_object_tree, offset2, i,
566                                         "Data (%d bytes)", i);
567                 }
568                 }
569                 break;
570
571             case RSVP_CLASS_SENDER_TSPEC : {
572                 rsvp_tspec *tspec = (rsvp_tspec *)obj;
573                 IS_tspec *ist;
574                 QUAL_tspec *qt;
575                 service_hdr  *sh;
576                 char *str;
577
578                 mylen = obj_length;
579                 rsvp_object_tree = proto_item_add_subtree(ti, ETT_RSVP_SENDER_TSPEC);
580                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
581                                     obj_length);
582                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
583                                     "Class number: %d - %s", 
584                                     obj->class, object_type);
585
586                 proto_tree_add_text(rsvp_object_tree, offset2, 1, 
587                                  "Message format version: %d", 
588                                  tspec->version>>4);
589                 proto_tree_add_text(rsvp_object_tree, offset2+2, 2, 
590                                  "Data length: %d words, not including header", 
591                                  pntohs(pd+offset2+2));
592
593                 mylen -=4;
594                 offset2 +=4;
595                 while (mylen > 4) {
596                     sh = (service_hdr *)(pd+offset2);
597                     str = match_strval(sh->service_num, qos_vals);
598                     if (!str) str = "Unknown";
599
600                     proto_tree_add_text(rsvp_object_tree, offset2, 1, 
601                                         "Service header: %d - %s", 
602                                         sh->service_num, str);
603                     proto_tree_add_text(rsvp_object_tree, offset2+2, 2, 
604                                  "Length of service %d data: %d words, " 
605                                  "not including header", 
606                                  sh->service_num,
607                                  ntohs(sh->length));
608
609                     offset2+=4; mylen -=4; 
610
611                     switch(sh->service_num) {
612                         
613                     case QOS_TSPEC :
614                         ist = (IS_tspec *)sh;
615
616                         /* Token bucket TSPEC */
617                         str = match_strval(ist->param_id, svc_vals);
618                         if (!str) str = "Unknown";
619                         proto_tree_add_text(rsvp_object_tree, offset2, 1, 
620                                             "Parameter %d - %s", 
621                                             ist->param_id, str);
622                         proto_tree_add_text(rsvp_object_tree, offset2+1, 1, 
623                                             "Parameter %d flags: %d", 
624                                             ist->param_id, ist->flags_tspec);
625                         proto_tree_add_text(rsvp_object_tree, offset2+2, 2, 
626                                             "Parameter %d data length: %d words, " 
627                                             "not including header",
628                                             ist->param_id,
629                                             /* pntohs(pd+offset2+10)); */
630                                             ntohs(ist->parameter_length));
631                         proto_tree_add_text(rsvp_object_tree, offset2+4, 4, 
632                                             "Token bucket rate: %ld", 
633                                             ieee_to_long(pd+offset2+4));
634                         proto_tree_add_text(rsvp_object_tree, offset2+8, 4, 
635                                             "Token bucket size: %ld", 
636                                             ieee_to_long(pd+offset2+8));
637                         proto_tree_add_text(rsvp_object_tree, offset2+12, 4, 
638                                             "Peak data rate: %ld", 
639                                             ieee_to_long(pd+offset2+12));
640                         proto_tree_add_text(rsvp_object_tree, offset2+16, 4, 
641                                             "Minimum policed unit: %d", 
642                                             pntohl(pd+offset2+16));
643                         proto_tree_add_text(rsvp_object_tree, offset2+20, 4, 
644                                             "Maximum policed unit: %d", 
645                                             pntohl(pd+offset2+20));
646
647                         break;
648
649                     case QOS_QUALITATIVE :
650                         qt = (QUAL_tspec *)sh;
651
652                         /* Token bucket TSPEC */
653                         str = match_strval(qt->param_id, svc_vals);
654                         if (!str) str = "Unknown";
655                         proto_tree_add_text(rsvp_object_tree, offset2, 1, 
656                                             "Parameter %d - %s", 
657                                             qt->param_id, str);
658                         proto_tree_add_text(rsvp_object_tree, offset2+1, 1, 
659                                             "Parameter %d flags: %d", 
660                                             qt->param_id, qt->flags_tspec);
661                         proto_tree_add_text(rsvp_object_tree, offset2+2, 2, 
662                                             "Parameter %d data length: %d words, " 
663                                             "not including header",
664                                             qt->param_id,
665                                             /* pntohs(pd+offset2+10)); */
666                                             ntohs(qt->parameter_length));
667                         proto_tree_add_text(rsvp_object_tree, offset2+4, 4, 
668                                             "Maximum policed unit: %d", 
669                                             pntohl(pd+offset2+4));
670
671                         break;
672
673                     }
674                     offset2 += ntohs(sh->length)*4; 
675                     mylen -= ntohs(sh->length)*4;
676                 }
677                     
678                 break;
679             }
680
681             case RSVP_CLASS_FLOWSPEC : {
682                 rsvp_flowspec *flowspec = (rsvp_flowspec *)obj;
683                 IS_flowspec *isf;
684                 QUAL_flowspec *qf;
685                 service_hdr *sh;
686                 int mylen;
687
688                 char *str;
689
690                 mylen = obj_length;
691                 rsvp_object_tree = proto_item_add_subtree(ti, ETT_RSVP_FLOWSPEC);
692                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
693                                     obj_length);
694                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
695                                     "Class number: %d - %s", 
696                                     obj->class, object_type);
697
698                 proto_tree_add_text(rsvp_object_tree, offset2, 1, 
699                                  "Message format version: %d", 
700                                  flowspec->version>>4);
701                 proto_tree_add_text(rsvp_object_tree, offset2+2, 2, 
702                                  "Data length: %d words, not including header", 
703                                  pntohs(pd+offset2+2));
704
705                 mylen -=4;
706                 offset2+=4;
707                 while (mylen > 4) {
708                     sh = (service_hdr *)(pd+offset2);
709                     str = match_strval(sh->service_num, intsrv_services_str);
710                     if (!str) str = "Unknown";
711
712                     proto_tree_add_text(rsvp_object_tree, offset2, 1, 
713                                         "Service header: %d - %s", 
714                                         sh->service_num, str);
715                     proto_tree_add_text(rsvp_object_tree, offset2+2, 2, 
716                                  "Length of service %d data: %d words, " 
717                                  "not including header", 
718                                  sh->service_num,
719                                  ntohs(sh->length));
720
721                     offset2+=4; mylen -=4; 
722
723                     switch(sh->service_num) {
724
725                     case QOS_CONTROLLED_LOAD :
726                     case QOS_GUARANTEED :
727                         /* Treat both these the same for now */
728                         isf = (IS_flowspec *)sh;
729
730                         str = match_strval(isf->tspec.param_id, svc_vals);
731                         if (!str) str = "Unknown";
732                         proto_tree_add_text(rsvp_object_tree, offset2, 1, 
733                                             "Parameter %d - %s", 
734                                             isf->tspec.param_id, str);
735                         proto_tree_add_text(rsvp_object_tree, offset2+1, 1, 
736                                             "Parameter %d flags: %d", 
737                                             isf->tspec.param_id, isf->tspec.flags_tspec);
738                         proto_tree_add_text(rsvp_object_tree, offset2+2, 2, 
739                                             "Parameter %d data length: %d words, " 
740                                             "not including header",
741                                             isf->tspec.param_id,
742                                             ntohs(isf->tspec.parameter_length));
743                         proto_tree_add_text(rsvp_object_tree, offset2+4, 4, 
744                                             "Token bucket rate: %ld", 
745                                             ieee_to_long(pd+offset2+4));
746                         proto_tree_add_text(rsvp_object_tree, offset2+8, 4, 
747                                             "Token bucket size: %ld", 
748                                             ieee_to_long(pd+offset2+8));
749                         proto_tree_add_text(rsvp_object_tree, offset2+12, 4, 
750                                             "Peak data rate: %ld", 
751                                             ieee_to_long(pd+offset2+12));
752                         proto_tree_add_text(rsvp_object_tree, offset2+16, 4, 
753                                             "Minimum policed unit: %d", 
754                                             pntohl(pd+offset2+16));
755                         proto_tree_add_text(rsvp_object_tree, offset2+20, 4, 
756                                             "Maximum policed unit: %d", 
757                                             pntohl(pd+offset2+20));
758                         if (sh->service_num!=QOS_GUARANTEED)
759                             break;
760                         
761                         /* Guaranteed-rate RSpec */
762                         str = match_strval(isf->rspec.param_id, svc_vals);
763                         if (!str) str="Unknown";
764                         proto_tree_add_text(rsvp_object_tree, offset2+24, 1, 
765                                             "Parameter %d - %s", 
766                                             isf->rspec.param_id, str);
767                         proto_tree_add_text(rsvp_object_tree, offset2+25, 1, 
768                                             "Parameter %d flags: %d", 
769                                             isf->rspec.param_id, isf->rspec.flags_rspec);
770                         proto_tree_add_text(rsvp_object_tree, offset2+26, 2, 
771                                             "Parameter %d data length: %d words, " 
772                                             "not including header",
773                                             isf->rspec.param_id,
774                                             ntohs(isf->rspec.param2_length));
775
776                         proto_tree_add_text(rsvp_object_tree, offset2+28, 4, 
777                                             "Rate: %ld", 
778                                             ieee_to_long(pd+offset2+28));
779                         proto_tree_add_text(rsvp_object_tree, offset2+32, 4, 
780                                             "Slack term: %d", 
781                                             pntohl(pd+offset2+32));
782                         break;
783
784                     case QOS_QUALITATIVE :
785                         qf = (QUAL_flowspec *)sh;
786
787                         str = match_strval(qf->param_id, svc_vals);
788                         if (!str) str = "Unknown";
789                         proto_tree_add_text(rsvp_object_tree, offset2, 1, 
790                                             "Parameter %d - %s", 
791                                             qf->param_id, str);
792                         proto_tree_add_text(rsvp_object_tree, offset2+1, 1, 
793                                             "Parameter %d flags: %d", 
794                                             qf->param_id, qf->flags_tspec);
795                         proto_tree_add_text(rsvp_object_tree, offset2+2, 2, 
796                                             "Parameter %d data length: %d words, " 
797                                             "not including header",
798                                             qf->param_id,
799                                             ntohs(qf->parameter_length));
800                         proto_tree_add_text(rsvp_object_tree, offset2+4, 4, 
801                                             "Maximum policed unit: %ld", 
802                                             pntohl(pd+offset2+4));
803                         
804                         break;
805                     }
806                     offset2 += ntohs(sh->length)*4;
807                     mylen -= ntohs(sh->length)*4;
808                 }
809
810                 break;
811             }
812
813             case RSVP_CLASS_ADSPEC : {
814                 proto_tree *adspec_tree;
815                 service_hdr *shdr;
816                 param_hdr *phdr; 
817
818                 char *str;
819                 int tree_num;
820
821                 mylen = obj_length;
822                 rsvp_object_tree = proto_item_add_subtree(ti, ETT_RSVP_ADSPEC);
823                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
824                                     obj_length);
825                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
826                                     "Class number: %d - %s", 
827                                     obj->class, object_type);
828                 
829                 proto_tree_add_text(rsvp_object_tree, offset2, 1, 
830                                     "Message format version: %d", 
831                                     (*((unsigned char *)pd+offset2))>>4);
832                 proto_tree_add_text(rsvp_object_tree, offset2+2, 2, 
833                                     "Data length: %d words, not including header", 
834                                     pntohs(pd+offset2+2));
835                 offset2+=4;
836                 tree_num=ETT_RSVP_ADSPEC_SUBTREE1;
837                 mylen -= 4;
838                 while (mylen > 4) {
839                     shdr = (service_hdr *)(pd + offset2);
840                     str = match_strval(shdr->service_num, intsrv_services_str);
841
842                     ti = proto_tree_add_text(rsvp_object_tree, offset2, 
843                                              (pntohs(&shdr->length)+1)<<2,
844                                              str?str:"Unknown");
845                     adspec_tree = proto_item_add_subtree(ti, tree_num++);
846                     proto_tree_add_text(adspec_tree, offset2, 1,
847                                         "Service header %d - %s",
848                                         shdr->service_num, str);
849                     proto_tree_add_text(adspec_tree, offset2+1, 1,
850                                         (shdr->break_bit&0x80)?
851                                         "Break bit set":"Break bit not set");
852                     proto_tree_add_text(adspec_tree, offset2+2, 2, 
853                                         "Data length: %d words, not including header", 
854                                         pntohs(&shdr->length));
855                     offset2+=4; i=(pntohs(&shdr->length)+1)<<2; mylen-=4;
856                     while (i>4) {
857                         phdr = (param_hdr *)(pd + offset2);
858                         str = match_strval(phdr->id, adspec_params);
859                         if (str) {
860                             switch(phdr->id) {
861                             case 4:
862                             case 8:
863                             case 10:
864                             case 133:
865                             case 134:
866                             case 135:
867                             case 136:
868                                 /* 32-bit unsigned integer */
869                                 proto_tree_add_text(adspec_tree, offset2, 
870                                                     (pntohs(&phdr->length)+1)<<2,
871                                                     "%s - %lu (type %d, length %d)",
872                                                     str, 
873                                                     (unsigned long)pntohl(&phdr->dataval), 
874                                                     phdr->id, pntohs(&phdr->length));
875                                 break;
876                                 
877                             case 6:
878                                 /* IEEE float */
879                                 proto_tree_add_text(adspec_tree, offset2, 
880                                                     (pntohs(&phdr->length)+1)<<2,
881                                                     "%s - %lu (type %d, length %d)",
882                                                     str, 
883                                                     ieee_to_long(&phdr->dataval), 
884                                                     phdr->id, pntohs(&phdr->length));
885                                 break;
886                             default: 
887                                 proto_tree_add_text(adspec_tree, offset2, 
888                                                     (pntohs(&phdr->length)+1)<<2,
889                                                     "%s (type %d, length %d)",
890                                                     str, 
891                                                     phdr->id, pntohs(&phdr->length));
892                             }
893                         } else {
894                             proto_tree_add_text(adspec_tree, offset2, 
895                                                 (pntohs(&phdr->length)+1)<<2,
896                                                 "Unknown (type %d, length %d)",
897                                                 phdr->id, pntohs(&phdr->length));
898                         }
899                         offset2+=(pntohs(&phdr->length)+1)<<2;
900                         i-=(pntohs(&phdr->length)+1)<<2;
901                         mylen-=(pntohs(&phdr->length)+1)<<2;
902                     }
903                 }
904                 break;
905             }
906
907             case RSVP_CLASS_INTEGRITY :
908                 rsvp_object_tree = proto_item_add_subtree(ti, ETT_RSVP_INTEGRITY);
909                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
910                                     obj_length);
911                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
912                                     "Class number: %d - %s", 
913                                     obj->class, object_type);
914                 goto default_class;
915
916             case RSVP_CLASS_POLICY :
917                 rsvp_object_tree = proto_item_add_subtree(ti, ETT_RSVP_POLICY);
918                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
919                                     obj_length);
920                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
921                                     "Class number: %d - %s", 
922                                     obj->class, object_type);
923                 goto default_class;
924
925             default :
926                 rsvp_object_tree = proto_item_add_subtree(ti, ETT_RSVP_UNKNOWN_CLASS);
927                 proto_tree_add_text(rsvp_object_tree, offset, 2, "Length: %d", 
928                                     obj_length);
929                 proto_tree_add_text(rsvp_object_tree, offset+2, 1, 
930                                     "Class number: %d - %s", 
931                                     obj->class, object_type);
932             default_class:
933                 i = obj_length - sizeof(rsvp_object);
934                 proto_tree_add_text(rsvp_object_tree, offset2, i,
935                                  "Data (%d bytes)", i);
936                 break;
937
938             case RSVP_CLASS_NULL :
939                 break;
940
941             }  
942             
943             offset += obj_length;
944             len += obj_length;
945         }
946     }
947 }
948
949 void
950 proto_register_rsvp(void)
951 {
952 /*        static hf_register_info hf[] = {
953                 { &variable,
954                 { "Name",           "rsvp.abbreviation", TYPE, VALS_POINTER }},
955         };*/
956
957         proto_rsvp = proto_register_protocol("Resource ReserVation Protocol (RSVP)", "rsvp");
958  /*       proto_register_field_array(proto_rsvp, hf, array_length(hf));*/
959 }