1/*
2 * Copyright (c) 1998-2007 The TCPDUMP project
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that: (1) source code
6 * distributions retain the above copyright notice and this paragraph
7 * in its entirety, and (2) distributions including binary code include
8 * the above copyright notice and this paragraph in its entirety in
9 * the documentation or other materials provided with the distribution.
10 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
11 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
12 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13 * FOR A PARTICULAR PURPOSE.
14 *
15 * Original code by Hannes Gredler (hannes@juniper.net)
16 */
17
18#ifndef lint
19static const char rcsid[] _U_ =
20    "@(#) $Header: /tcpdump/master/tcpdump/print-rsvp.c,v 1.33.2.15 2007/09/13 17:33:54 guy Exp $";
21#endif
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include <tcpdump-stdinc.h>
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32
33#include "interface.h"
34#include "extract.h"
35#include "addrtoname.h"
36#include "ethertype.h"
37#include "gmpls.h"
38#include "af.h"
39
40/*
41 * RFC 2205 common header
42 *
43 *               0             1              2             3
44 *        +-------------+-------------+-------------+-------------+
45 *        | Vers | Flags|  Msg Type   |       RSVP Checksum       |
46 *        +-------------+-------------+-------------+-------------+
47 *        |  Send_TTL   | (Reserved)  |        RSVP Length        |
48 *        +-------------+-------------+-------------+-------------+
49 *
50 */
51
52struct rsvp_common_header {
53    u_int8_t version_flags;
54    u_int8_t msg_type;
55    u_int8_t checksum[2];
56    u_int8_t ttl;
57    u_int8_t reserved;
58    u_int8_t length[2];
59};
60
61/*
62 * RFC2205 object header
63 *
64 *
65 *               0             1              2             3
66 *        +-------------+-------------+-------------+-------------+
67 *        |       Length (bytes)      |  Class-Num  |   C-Type    |
68 *        +-------------+-------------+-------------+-------------+
69 *        |                                                       |
70 *        //                  (Object contents)                   //
71 *        |                                                       |
72 *        +-------------+-------------+-------------+-------------+
73 */
74
75struct rsvp_object_header {
76    u_int8_t length[2];
77    u_int8_t class_num;
78    u_int8_t ctype;
79};
80
81#define RSVP_VERSION            1
82#define	RSVP_EXTRACT_VERSION(x) (((x)&0xf0)>>4)
83#define	RSVP_EXTRACT_FLAGS(x)   ((x)&0x0f)
84
85#define	RSVP_MSGTYPE_PATH       1
86#define	RSVP_MSGTYPE_RESV       2
87#define	RSVP_MSGTYPE_PATHERR    3
88#define	RSVP_MSGTYPE_RESVERR    4
89#define	RSVP_MSGTYPE_PATHTEAR   5
90#define	RSVP_MSGTYPE_RESVTEAR   6
91#define	RSVP_MSGTYPE_RESVCONF   7
92#define RSVP_MSGTYPE_AGGREGATE  12
93#define RSVP_MSGTYPE_ACK        13
94#define RSVP_MSGTYPE_HELLO_OLD  14      /* ancient Hellos */
95#define RSVP_MSGTYPE_SREFRESH   15
96#define	RSVP_MSGTYPE_HELLO      20
97
98static const struct tok rsvp_msg_type_values[] = {
99    { RSVP_MSGTYPE_PATH,	"Path" },
100    { RSVP_MSGTYPE_RESV,	"Resv" },
101    { RSVP_MSGTYPE_PATHERR,	"PathErr" },
102    { RSVP_MSGTYPE_RESVERR,	"ResvErr" },
103    { RSVP_MSGTYPE_PATHTEAR,	"PathTear" },
104    { RSVP_MSGTYPE_RESVTEAR,	"ResvTear" },
105    { RSVP_MSGTYPE_RESVCONF,	"ResvConf" },
106    { RSVP_MSGTYPE_AGGREGATE,	"Aggregate" },
107    { RSVP_MSGTYPE_ACK,	        "Acknowledgement" },
108    { RSVP_MSGTYPE_HELLO_OLD,	"Hello (Old)" },
109    { RSVP_MSGTYPE_SREFRESH,	"Refresh" },
110    { RSVP_MSGTYPE_HELLO,	"Hello" },
111    { 0, NULL}
112};
113
114static const struct tok rsvp_header_flag_values[] = {
115    { 0x01,	              "Refresh reduction capable" }, /* rfc2961 */
116    { 0, NULL}
117};
118
119#define	RSVP_OBJ_SESSION            1   /* rfc2205 */
120#define	RSVP_OBJ_RSVP_HOP           3   /* rfc2205, rfc3473 */
121#define	RSVP_OBJ_INTEGRITY          4   /* rfc2747 */
122#define	RSVP_OBJ_TIME_VALUES        5   /* rfc2205 */
123#define	RSVP_OBJ_ERROR_SPEC         6
124#define	RSVP_OBJ_SCOPE              7
125#define	RSVP_OBJ_STYLE              8   /* rfc2205 */
126#define	RSVP_OBJ_FLOWSPEC           9   /* rfc2215 */
127#define	RSVP_OBJ_FILTERSPEC         10  /* rfc2215 */
128#define	RSVP_OBJ_SENDER_TEMPLATE    11
129#define	RSVP_OBJ_SENDER_TSPEC       12  /* rfc2215 */
130#define	RSVP_OBJ_ADSPEC             13  /* rfc2215 */
131#define	RSVP_OBJ_POLICY_DATA        14
132#define	RSVP_OBJ_CONFIRM            15  /* rfc2205 */
133#define	RSVP_OBJ_LABEL              16  /* rfc3209 */
134#define	RSVP_OBJ_LABEL_REQ          19  /* rfc3209 */
135#define	RSVP_OBJ_ERO                20  /* rfc3209 */
136#define	RSVP_OBJ_RRO                21  /* rfc3209 */
137#define	RSVP_OBJ_HELLO              22  /* rfc3209 */
138#define	RSVP_OBJ_MESSAGE_ID         23  /* rfc2961 */
139#define	RSVP_OBJ_MESSAGE_ID_ACK     24  /* rfc2961 */
140#define	RSVP_OBJ_MESSAGE_ID_LIST    25  /* rfc2961 */
141#define	RSVP_OBJ_RECOVERY_LABEL     34  /* rfc3473 */
142#define	RSVP_OBJ_UPSTREAM_LABEL     35  /* rfc3473 */
143#define	RSVP_OBJ_LABEL_SET          36  /* rfc3473 */
144#define	RSVP_OBJ_PROTECTION         37  /* rfc3473 */
145#define	RSVP_OBJ_DETOUR             63  /* draft-ietf-mpls-rsvp-lsp-fastreroute-07 */
146#define	RSVP_OBJ_CLASSTYPE          66  /* rfc4124 */
147#define RSVP_OBJ_CLASSTYPE_OLD      125 /* draft-ietf-tewg-diff-te-proto-07 */
148#define	RSVP_OBJ_SUGGESTED_LABEL    129 /* rfc3473 */
149#define	RSVP_OBJ_ACCEPT_LABEL_SET   130 /* rfc3473 */
150#define	RSVP_OBJ_RESTART_CAPABILITY 131 /* rfc3473 */
151#define	RSVP_OBJ_NOTIFY_REQ         195 /* rfc3473 */
152#define	RSVP_OBJ_ADMIN_STATUS       196 /* rfc3473 */
153#define	RSVP_OBJ_PROPERTIES         204 /* juniper proprietary */
154#define	RSVP_OBJ_FASTREROUTE        205 /* draft-ietf-mpls-rsvp-lsp-fastreroute-07 */
155#define	RSVP_OBJ_SESSION_ATTRIBUTE  207 /* rfc3209 */
156#define RSVP_OBJ_GENERALIZED_UNI    229 /* OIF RSVP extensions UNI 1.0 Signaling, Rel. 2 */
157#define RSVP_OBJ_CALL_ID            230 /* rfc3474 */
158#define RSVP_OBJ_CALL_OPS           236 /* rfc3474 */
159
160static const struct tok rsvp_obj_values[] = {
161    { RSVP_OBJ_SESSION,            "Session" },
162    { RSVP_OBJ_RSVP_HOP,           "RSVP Hop" },
163    { RSVP_OBJ_INTEGRITY,          "Integrity" },
164    { RSVP_OBJ_TIME_VALUES,        "Time Values" },
165    { RSVP_OBJ_ERROR_SPEC,         "Error Spec" },
166    { RSVP_OBJ_SCOPE,              "Scope" },
167    { RSVP_OBJ_STYLE,              "Style" },
168    { RSVP_OBJ_FLOWSPEC,           "Flowspec" },
169    { RSVP_OBJ_FILTERSPEC,         "FilterSpec" },
170    { RSVP_OBJ_SENDER_TEMPLATE,    "Sender Template" },
171    { RSVP_OBJ_SENDER_TSPEC,       "Sender TSpec" },
172    { RSVP_OBJ_ADSPEC,             "Adspec" },
173    { RSVP_OBJ_POLICY_DATA,        "Policy Data" },
174    { RSVP_OBJ_CONFIRM,            "Confirm" },
175    { RSVP_OBJ_LABEL,              "Label" },
176    { RSVP_OBJ_LABEL_REQ,          "Label Request" },
177    { RSVP_OBJ_ERO,                "ERO" },
178    { RSVP_OBJ_RRO,                "RRO" },
179    { RSVP_OBJ_HELLO,              "Hello" },
180    { RSVP_OBJ_MESSAGE_ID,         "Message ID" },
181    { RSVP_OBJ_MESSAGE_ID_ACK,     "Message ID Ack" },
182    { RSVP_OBJ_MESSAGE_ID_LIST,    "Message ID List" },
183    { RSVP_OBJ_RECOVERY_LABEL,     "Recovery Label" },
184    { RSVP_OBJ_UPSTREAM_LABEL,     "Upstream Label" },
185    { RSVP_OBJ_LABEL_SET,          "Label Set" },
186    { RSVP_OBJ_ACCEPT_LABEL_SET,   "Acceptable Label Set" },
187    { RSVP_OBJ_DETOUR,             "Detour" },
188    { RSVP_OBJ_CLASSTYPE,          "Class Type" },
189    { RSVP_OBJ_CLASSTYPE_OLD,      "Class Type (old)" },
190    { RSVP_OBJ_SUGGESTED_LABEL,    "Suggested Label" },
191    { RSVP_OBJ_PROPERTIES,         "Properties" },
192    { RSVP_OBJ_FASTREROUTE,        "Fast Re-Route" },
193    { RSVP_OBJ_SESSION_ATTRIBUTE,  "Session Attribute" },
194    { RSVP_OBJ_GENERALIZED_UNI,    "Generalized UNI" },
195    { RSVP_OBJ_CALL_ID,            "Call-ID" },
196    { RSVP_OBJ_CALL_OPS,           "Call Capability" },
197    { RSVP_OBJ_RESTART_CAPABILITY, "Restart Capability" },
198    { RSVP_OBJ_NOTIFY_REQ,         "Notify Request" },
199    { RSVP_OBJ_PROTECTION,         "Protection" },
200    { RSVP_OBJ_ADMIN_STATUS,       "Administrative Status" },
201    { 0, NULL}
202};
203
204#define	RSVP_CTYPE_IPV4        1
205#define	RSVP_CTYPE_IPV6        2
206#define	RSVP_CTYPE_TUNNEL_IPV4 7
207#define	RSVP_CTYPE_TUNNEL_IPV6 8
208#define	RSVP_CTYPE_UNI_IPV4    11 /* OIF RSVP extensions UNI 1.0 Signaling Rel. 2 */
209#define RSVP_CTYPE_1           1
210#define RSVP_CTYPE_2           2
211#define RSVP_CTYPE_3           3
212#define RSVP_CTYPE_4           4
213
214/*
215 * the ctypes are not globally unique so for
216 * translating it to strings we build a table based
217 * on objects offsetted by the ctype
218 */
219
220static const struct tok rsvp_ctype_values[] = {
221    { 256*RSVP_OBJ_RSVP_HOP+RSVP_CTYPE_IPV4,	             "IPv4" },
222    { 256*RSVP_OBJ_RSVP_HOP+RSVP_CTYPE_IPV6,	             "IPv6" },
223    { 256*RSVP_OBJ_RSVP_HOP+RSVP_CTYPE_3,	             "IPv4 plus opt. TLVs" },
224    { 256*RSVP_OBJ_RSVP_HOP+RSVP_CTYPE_4,	             "IPv6 plus opt. TLVs" },
225    { 256*RSVP_OBJ_NOTIFY_REQ+RSVP_CTYPE_IPV4,	             "IPv4" },
226    { 256*RSVP_OBJ_NOTIFY_REQ+RSVP_CTYPE_IPV6,	             "IPv6" },
227    { 256*RSVP_OBJ_CONFIRM+RSVP_CTYPE_IPV4,	             "IPv4" },
228    { 256*RSVP_OBJ_CONFIRM+RSVP_CTYPE_IPV6,	             "IPv6" },
229    { 256*RSVP_OBJ_TIME_VALUES+RSVP_CTYPE_1,	             "1" },
230    { 256*RSVP_OBJ_FLOWSPEC+RSVP_CTYPE_1,	             "obsolete" },
231    { 256*RSVP_OBJ_FLOWSPEC+RSVP_CTYPE_2,	             "IntServ" },
232    { 256*RSVP_OBJ_SENDER_TSPEC+RSVP_CTYPE_2,	             "IntServ" },
233    { 256*RSVP_OBJ_ADSPEC+RSVP_CTYPE_2,	                     "IntServ" },
234    { 256*RSVP_OBJ_FILTERSPEC+RSVP_CTYPE_IPV4,	             "IPv4" },
235    { 256*RSVP_OBJ_FILTERSPEC+RSVP_CTYPE_IPV6,	             "IPv6" },
236    { 256*RSVP_OBJ_FILTERSPEC+RSVP_CTYPE_3,	             "IPv6 Flow-label" },
237    { 256*RSVP_OBJ_FILTERSPEC+RSVP_CTYPE_TUNNEL_IPV4,	     "Tunnel IPv4" },
238    { 256*RSVP_OBJ_SESSION+RSVP_CTYPE_IPV4,	             "IPv4" },
239    { 256*RSVP_OBJ_SESSION+RSVP_CTYPE_IPV6,	             "IPv6" },
240    { 256*RSVP_OBJ_SESSION+RSVP_CTYPE_TUNNEL_IPV4,           "Tunnel IPv4" },
241    { 256*RSVP_OBJ_SESSION+RSVP_CTYPE_UNI_IPV4,              "UNI IPv4" },
242    { 256*RSVP_OBJ_SENDER_TEMPLATE+RSVP_CTYPE_IPV4,          "IPv4" },
243    { 256*RSVP_OBJ_SENDER_TEMPLATE+RSVP_CTYPE_IPV6,          "IPv6" },
244    { 256*RSVP_OBJ_SENDER_TEMPLATE+RSVP_CTYPE_TUNNEL_IPV4,   "Tunnel IPv4" },
245    { 256*RSVP_OBJ_MESSAGE_ID+RSVP_CTYPE_1,                  "1" },
246    { 256*RSVP_OBJ_MESSAGE_ID_ACK+RSVP_CTYPE_1,              "Message id ack" },
247    { 256*RSVP_OBJ_MESSAGE_ID_ACK+RSVP_CTYPE_2,              "Message id nack" },
248    { 256*RSVP_OBJ_MESSAGE_ID_LIST+RSVP_CTYPE_1,             "1" },
249    { 256*RSVP_OBJ_STYLE+RSVP_CTYPE_1,                       "1" },
250    { 256*RSVP_OBJ_HELLO+RSVP_CTYPE_1,                       "Hello Request" },
251    { 256*RSVP_OBJ_HELLO+RSVP_CTYPE_2,                       "Hello Ack" },
252    { 256*RSVP_OBJ_LABEL_REQ+RSVP_CTYPE_1,	             "without label range" },
253    { 256*RSVP_OBJ_LABEL_REQ+RSVP_CTYPE_2,	             "with ATM label range" },
254    { 256*RSVP_OBJ_LABEL_REQ+RSVP_CTYPE_3,                   "with FR label range" },
255    { 256*RSVP_OBJ_LABEL_REQ+RSVP_CTYPE_4,                   "Generalized Label" },
256    { 256*RSVP_OBJ_LABEL+RSVP_CTYPE_1,                       "Label" },
257    { 256*RSVP_OBJ_LABEL+RSVP_CTYPE_2,                       "Generalized Label" },
258    { 256*RSVP_OBJ_LABEL+RSVP_CTYPE_3,                       "Waveband Switching" },
259    { 256*RSVP_OBJ_SUGGESTED_LABEL+RSVP_CTYPE_1,             "Label" },
260    { 256*RSVP_OBJ_SUGGESTED_LABEL+RSVP_CTYPE_2,             "Generalized Label" },
261    { 256*RSVP_OBJ_SUGGESTED_LABEL+RSVP_CTYPE_3,             "Waveband Switching" },
262    { 256*RSVP_OBJ_UPSTREAM_LABEL+RSVP_CTYPE_1,              "Label" },
263    { 256*RSVP_OBJ_UPSTREAM_LABEL+RSVP_CTYPE_2,              "Generalized Label" },
264    { 256*RSVP_OBJ_UPSTREAM_LABEL+RSVP_CTYPE_3,              "Waveband Switching" },
265    { 256*RSVP_OBJ_RECOVERY_LABEL+RSVP_CTYPE_1,              "Label" },
266    { 256*RSVP_OBJ_RECOVERY_LABEL+RSVP_CTYPE_2,              "Generalized Label" },
267    { 256*RSVP_OBJ_RECOVERY_LABEL+RSVP_CTYPE_3,              "Waveband Switching" },
268    { 256*RSVP_OBJ_ERO+RSVP_CTYPE_IPV4,                      "IPv4" },
269    { 256*RSVP_OBJ_RRO+RSVP_CTYPE_IPV4,                      "IPv4" },
270    { 256*RSVP_OBJ_ERROR_SPEC+RSVP_CTYPE_IPV4,               "IPv4" },
271    { 256*RSVP_OBJ_ERROR_SPEC+RSVP_CTYPE_IPV6,               "IPv6" },
272    { 256*RSVP_OBJ_ERROR_SPEC+RSVP_CTYPE_3,                  "IPv4 plus opt. TLVs" },
273    { 256*RSVP_OBJ_ERROR_SPEC+RSVP_CTYPE_4,                  "IPv6 plus opt. TLVs" },
274    { 256*RSVP_OBJ_RESTART_CAPABILITY+RSVP_CTYPE_1,          "IPv4" },
275    { 256*RSVP_OBJ_SESSION_ATTRIBUTE+RSVP_CTYPE_TUNNEL_IPV4, "Tunnel IPv4" },
276    { 256*RSVP_OBJ_FASTREROUTE+RSVP_CTYPE_TUNNEL_IPV4,       "Tunnel IPv4" }, /* old style*/
277    { 256*RSVP_OBJ_FASTREROUTE+RSVP_CTYPE_1,                 "1" }, /* new style */
278    { 256*RSVP_OBJ_DETOUR+RSVP_CTYPE_TUNNEL_IPV4,            "Tunnel IPv4" },
279    { 256*RSVP_OBJ_PROPERTIES+RSVP_CTYPE_1,                  "1" },
280    { 256*RSVP_OBJ_ADMIN_STATUS+RSVP_CTYPE_1,                "1" },
281    { 256*RSVP_OBJ_CLASSTYPE+RSVP_CTYPE_1,                   "1" },
282    { 256*RSVP_OBJ_CLASSTYPE_OLD+RSVP_CTYPE_1,               "1" },
283    { 256*RSVP_OBJ_LABEL_SET+RSVP_CTYPE_1,                   "1" },
284    { 256*RSVP_OBJ_GENERALIZED_UNI+RSVP_CTYPE_1,             "1" },
285    { 0, NULL}
286};
287
288struct rsvp_obj_integrity_t {
289    u_int8_t flags;
290    u_int8_t res;
291    u_int8_t key_id[6];
292    u_int8_t sequence[8];
293    u_int8_t digest[16];
294};
295
296static const struct tok rsvp_obj_integrity_flag_values[] = {
297    { 0x80, "Handshake" },
298    { 0, NULL}
299};
300
301struct rsvp_obj_frr_t {
302    u_int8_t setup_prio;
303    u_int8_t hold_prio;
304    u_int8_t hop_limit;
305    u_int8_t flags;
306    u_int8_t bandwidth[4];
307    u_int8_t include_any[4];
308    u_int8_t exclude_any[4];
309    u_int8_t include_all[4];
310};
311
312
313#define RSVP_OBJ_XRO_MASK_SUBOBJ(x)   ((x)&0x7f)
314#define RSVP_OBJ_XRO_MASK_LOOSE(x)    ((x)&0x80)
315
316#define	RSVP_OBJ_XRO_RES       0
317#define	RSVP_OBJ_XRO_IPV4      1
318#define	RSVP_OBJ_XRO_IPV6      2
319#define	RSVP_OBJ_XRO_ASN       32
320#define	RSVP_OBJ_XRO_MPLS      64
321
322static const struct tok rsvp_obj_xro_values[] = {
323    { RSVP_OBJ_XRO_RES,	      "Reserved" },
324    { RSVP_OBJ_XRO_IPV4,      "IPv4 prefix" },
325    { RSVP_OBJ_XRO_IPV6,      "IPv6 prefix" },
326    { RSVP_OBJ_XRO_ASN,       "Autonomous system number" },
327    { RSVP_OBJ_XRO_MPLS,      "MPLS label switched path termination" },
328    { 0, NULL}
329};
330
331/* draft-ietf-mpls-rsvp-lsp-fastreroute-07.txt */
332static const struct tok rsvp_obj_rro_flag_values[] = {
333    { 0x01,	              "Local protection available" },
334    { 0x02,                   "Local protection in use" },
335    { 0x04,                   "Bandwidth protection" },
336    { 0x08,                   "Node protection" },
337    { 0, NULL}
338};
339
340static const struct tok rsvp_resstyle_values[] = {
341    { 17,	              "Wildcard Filter" },
342    { 10,                     "Fixed Filter" },
343    { 18,                     "Shared Explicit" },
344    { 0, NULL}
345};
346
347#define RSVP_OBJ_INTSERV_GUARANTEED_SERV 2
348#define RSVP_OBJ_INTSERV_CONTROLLED_LOAD 5
349
350static const struct tok rsvp_intserv_service_type_values[] = {
351    { 1,                                "Default/Global Information" },
352    { RSVP_OBJ_INTSERV_GUARANTEED_SERV, "Guaranteed Service" },
353    { RSVP_OBJ_INTSERV_CONTROLLED_LOAD,	"Controlled Load" },
354    { 0, NULL}
355};
356
357static const struct tok rsvp_intserv_parameter_id_values[] = {
358    { 4,                     "IS hop cnt" },
359    { 6,                     "Path b/w estimate" },
360    { 8,                     "Minimum path latency" },
361    { 10,                    "Composed MTU" },
362    { 127,                   "Token Bucket TSpec" },
363    { 130,                   "Guaranteed Service RSpec" },
364    { 133,                   "End-to-end composed value for C" },
365    { 134,                   "End-to-end composed value for D" },
366    { 135,                   "Since-last-reshaping point composed C" },
367    { 136,                   "Since-last-reshaping point composed D" },
368    { 0, NULL}
369};
370
371static struct tok rsvp_session_attribute_flag_values[] = {
372    { 0x01,	              "Local Protection desired" },
373    { 0x02,                   "Label Recording desired" },
374    { 0x04,                   "SE Style desired" },
375    { 0x08,                   "Bandwidth protection desired" }, /* draft-ietf-mpls-rsvp-lsp-fastreroute-02.txt */
376    { 0x10,                   "Node protection desired" },      /* draft-ietf-mpls-rsvp-lsp-fastreroute-02.txt */
377    { 0, NULL}
378};
379
380static struct tok rsvp_obj_prop_tlv_values[] = {
381    { 0x01,                   "Cos" },
382    { 0x02,                   "Metric 1" },
383    { 0x04,                   "Metric 2" },
384    { 0x08,                   "CCC Status" },
385    { 0x10,                   "Path Type" },
386    { 0, NULL}
387};
388
389#define RSVP_OBJ_ERROR_SPEC_CODE_ROUTING 24
390#define RSVP_OBJ_ERROR_SPEC_CODE_NOTIFY  25
391#define RSVP_OBJ_ERROR_SPEC_CODE_DIFFSERV_TE 28
392#define RSVP_OBJ_ERROR_SPEC_CODE_DIFFSERV_TE_OLD 125
393
394static struct tok rsvp_obj_error_code_values[] = {
395    { RSVP_OBJ_ERROR_SPEC_CODE_ROUTING, "Routing Problem" },
396    { RSVP_OBJ_ERROR_SPEC_CODE_NOTIFY,  "Notify Error" },
397    { RSVP_OBJ_ERROR_SPEC_CODE_DIFFSERV_TE, "Diffserv TE Error" },
398    { RSVP_OBJ_ERROR_SPEC_CODE_DIFFSERV_TE_OLD, "Diffserv TE Error (Old)" },
399    { 0, NULL}
400};
401
402static struct tok rsvp_obj_error_code_routing_values[] = {
403    { 1,                      "Bad EXPLICIT_ROUTE object" },
404    { 2,                      "Bad strict node" },
405    { 3,                      "Bad loose node" },
406    { 4,                      "Bad initial subobject" },
407    { 5,                      "No route available toward destination" },
408    { 6,                      "Unacceptable label value" },
409    { 7,                      "RRO indicated routing loops" },
410    { 8,                      "non-RSVP-capable router in the path" },
411    { 9,                      "MPLS label allocation failure" },
412    { 10,                     "Unsupported L3PID" },
413    { 0, NULL}
414};
415
416static struct tok rsvp_obj_error_code_diffserv_te_values[] = {
417    { 1,                      "Unexpected CT object" },
418    { 2,                      "Unsupported CT" },
419    { 3,                      "Invalid CT value" },
420    { 4,                      "CT/setup priority do not form a configured TE-Class" },
421    { 5,                      "CT/holding priority do not form a configured TE-Class" },
422    { 6,                      "CT/setup priority and CT/holding priority do not form a configured TE-Class" },
423    { 7,                      "Inconsistency between signaled PSC and signaled CT" },
424    { 8,                      "Inconsistency between signaled PHBs and signaled CT" },
425   { 0, NULL}
426};
427
428/* rfc3473 / rfc 3471 */
429static const struct tok rsvp_obj_admin_status_flag_values[] = {
430    { 0x80000000, "Reflect" },
431    { 0x00000004, "Testing" },
432    { 0x00000002, "Admin-down" },
433    { 0x00000001, "Delete-in-progress" },
434    { 0, NULL}
435};
436
437/* label set actions - rfc3471 */
438#define LABEL_SET_INCLUSIVE_LIST  0
439#define LABEL_SET_EXCLUSIVE_LIST  1
440#define LABEL_SET_INCLUSIVE_RANGE 2
441#define LABEL_SET_EXCLUSIVE_RANGE 3
442
443static const struct tok rsvp_obj_label_set_action_values[] = {
444    { LABEL_SET_INCLUSIVE_LIST, "Inclusive list" },
445    { LABEL_SET_EXCLUSIVE_LIST, "Exclusive list" },
446    { LABEL_SET_INCLUSIVE_RANGE, "Inclusive range" },
447    { LABEL_SET_EXCLUSIVE_RANGE, "Exclusive range" },
448    { 0, NULL}
449};
450
451/* OIF RSVP extensions UNI 1.0 Signaling, release 2 */
452#define RSVP_GEN_UNI_SUBOBJ_SOURCE_TNA_ADDRESS	    1
453#define RSVP_GEN_UNI_SUBOBJ_DESTINATION_TNA_ADDRESS 2
454#define RSVP_GEN_UNI_SUBOBJ_DIVERSITY		    3
455#define RSVP_GEN_UNI_SUBOBJ_EGRESS_LABEL            4
456#define RSVP_GEN_UNI_SUBOBJ_SERVICE_LEVEL           5
457
458static const struct tok rsvp_obj_generalized_uni_values[] = {
459    { RSVP_GEN_UNI_SUBOBJ_SOURCE_TNA_ADDRESS, "Source TNA address" },
460    { RSVP_GEN_UNI_SUBOBJ_DESTINATION_TNA_ADDRESS, "Destination TNA address" },
461    { RSVP_GEN_UNI_SUBOBJ_DIVERSITY, "Diversity" },
462    { RSVP_GEN_UNI_SUBOBJ_EGRESS_LABEL, "Egress label" },
463    { RSVP_GEN_UNI_SUBOBJ_SERVICE_LEVEL, "Service level" },
464    { 0, NULL}
465};
466
467static int rsvp_intserv_print(const u_char *, u_short);
468
469/*
470 * this is a dissector for all the intserv defined
471 * specs as defined per rfc2215
472 * it is called from various rsvp objects;
473 * returns the amount of bytes being processed
474 */
475static int
476rsvp_intserv_print(const u_char *tptr, u_short obj_tlen) {
477
478    int parameter_id,parameter_length;
479    union {
480	float f;
481	u_int32_t i;
482    } bw;
483
484    if (obj_tlen < 4)
485        return 0;
486    parameter_id = *(tptr);
487    parameter_length = EXTRACT_16BITS(tptr+2)<<2; /* convert wordcount to bytecount */
488
489    printf("\n\t      Parameter ID: %s (%u), length: %u, Flags: [0x%02x]",
490           tok2str(rsvp_intserv_parameter_id_values,"unknown",parameter_id),
491           parameter_id,
492           parameter_length,
493           *(tptr+1));
494
495    if (obj_tlen < parameter_length+4)
496        return 0;
497    switch(parameter_id) { /* parameter_id */
498
499    case 4:
500       /*
501        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
502        * |    4 (e)      |    (f)        |           1 (g)               |
503        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
504        * |        IS hop cnt (32-bit unsigned integer)                   |
505        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
506        */
507        if (parameter_length == 4)
508            printf("\n\t\tIS hop count: %u", EXTRACT_32BITS(tptr+4));
509        break;
510
511    case 6:
512       /*
513        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
514        * |    6 (h)      |    (i)        |           1 (j)               |
515        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
516        * |  Path b/w estimate  (32-bit IEEE floating point number)       |
517        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
518        */
519        if (parameter_length == 4) {
520            bw.i = EXTRACT_32BITS(tptr+4);
521            printf("\n\t\tPath b/w estimate: %.10g Mbps", bw.f/125000);
522        }
523        break;
524
525    case 8:
526       /*
527        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
528        * |     8 (k)     |    (l)        |           1 (m)               |
529        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
530        * |        Minimum path latency (32-bit integer)                  |
531        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
532        */
533        if (parameter_length == 4) {
534            printf("\n\t\tMinimum path latency: ");
535            if (EXTRACT_32BITS(tptr+4) == 0xffffffff)
536                printf("don't care");
537            else
538                printf("%u", EXTRACT_32BITS(tptr+4));
539        }
540        break;
541
542    case 10:
543
544       /*
545        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
546        * |     10 (n)    |      (o)      |           1 (p)               |
547        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
548        * |      Composed MTU (32-bit unsigned integer)                   |
549        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
550        */
551        if (parameter_length == 4)
552            printf("\n\t\tComposed MTU: %u bytes", EXTRACT_32BITS(tptr+4));
553        break;
554    case 127:
555       /*
556        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
557        * |   127 (e)     |    0 (f)      |             5 (g)             |
558        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
559        * |  Token Bucket Rate [r] (32-bit IEEE floating point number)    |
560        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
561        * |  Token Bucket Size [b] (32-bit IEEE floating point number)    |
562        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
563        * |  Peak Data Rate [p] (32-bit IEEE floating point number)       |
564        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
565        * |  Minimum Policed Unit [m] (32-bit integer)                    |
566        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
567        * |  Maximum Packet Size [M]  (32-bit integer)                    |
568        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
569        */
570
571        if (parameter_length == 20) {
572            bw.i = EXTRACT_32BITS(tptr+4);
573            printf("\n\t\tToken Bucket Rate: %.10g Mbps", bw.f/125000);
574            bw.i = EXTRACT_32BITS(tptr+8);
575            printf("\n\t\tToken Bucket Size: %.10g bytes", bw.f);
576            bw.i = EXTRACT_32BITS(tptr+12);
577            printf("\n\t\tPeak Data Rate: %.10g Mbps", bw.f/125000);
578            printf("\n\t\tMinimum Policed Unit: %u bytes", EXTRACT_32BITS(tptr+16));
579            printf("\n\t\tMaximum Packet Size: %u bytes", EXTRACT_32BITS(tptr+20));
580        }
581        break;
582
583    case 130:
584       /*
585        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
586        * |     130 (h)   |    0 (i)      |            2 (j)              |
587        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
588        * |  Rate [R]  (32-bit IEEE floating point number)                |
589        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
590        * |  Slack Term [S]  (32-bit integer)                             |
591        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
592        */
593
594        if (parameter_length == 8) {
595            bw.i = EXTRACT_32BITS(tptr+4);
596            printf("\n\t\tRate: %.10g Mbps", bw.f/125000);
597            printf("\n\t\tSlack Term: %u", EXTRACT_32BITS(tptr+8));
598        }
599        break;
600
601    case 133:
602    case 134:
603    case 135:
604    case 136:
605        if (parameter_length == 4)
606            printf("\n\t\tValue: %u", EXTRACT_32BITS(tptr+4));
607        break;
608
609    default:
610        if (vflag <= 1)
611            print_unknown_data(tptr+4,"\n\t\t",parameter_length);
612    }
613    return (parameter_length+4); /* header length 4 bytes */
614}
615
616static int
617rsvp_obj_print (const u_char *tptr, const char *ident, u_int tlen) {
618
619    const struct rsvp_object_header *rsvp_obj_header;
620    const u_char *obj_tptr;
621    union {
622        const struct rsvp_obj_integrity_t *rsvp_obj_integrity;
623        const struct rsvp_obj_frr_t *rsvp_obj_frr;
624    } obj_ptr;
625
626    u_short rsvp_obj_len,rsvp_obj_ctype,obj_tlen,intserv_serv_tlen;
627    int hexdump,processed,padbytes,error_code,error_value,i;
628    union {
629	float f;
630	u_int32_t i;
631    } bw;
632    u_int8_t namelen;
633
634    u_int action, subchannel;
635
636    while(tlen>=sizeof(struct rsvp_object_header)) {
637        /* did we capture enough for fully decoding the object header ? */
638        if (!TTEST2(*tptr, sizeof(struct rsvp_object_header)))
639            goto trunc;
640
641        rsvp_obj_header = (const struct rsvp_object_header *)tptr;
642        rsvp_obj_len=EXTRACT_16BITS(rsvp_obj_header->length);
643        rsvp_obj_ctype=rsvp_obj_header->ctype;
644
645        if(rsvp_obj_len % 4) {
646            printf("%sERROR: object header size %u not a multiple of 4", ident, rsvp_obj_len);
647            return -1;
648        }
649        if(rsvp_obj_len < sizeof(struct rsvp_object_header)) {
650            printf("%sERROR: object header too short %u < %lu", ident, rsvp_obj_len,
651                   (unsigned long)sizeof(const struct rsvp_object_header));
652            return -1;
653        }
654
655        printf("%s%s Object (%u) Flags: [%s",
656               ident,
657               tok2str(rsvp_obj_values,
658                       "Unknown",
659                       rsvp_obj_header->class_num),
660               rsvp_obj_header->class_num,
661               ((rsvp_obj_header->class_num)&0x80) ? "ignore" : "reject");
662
663        if (rsvp_obj_header->class_num > 128)
664            printf(" %s",
665                   ((rsvp_obj_header->class_num)&0x40) ? "and forward" : "silently");
666
667        printf(" if unknown], Class-Type: %s (%u), length: %u",
668               tok2str(rsvp_ctype_values,
669                       "Unknown",
670                       ((rsvp_obj_header->class_num)<<8)+rsvp_obj_ctype),
671               rsvp_obj_ctype,
672               rsvp_obj_len);
673
674        if(tlen < rsvp_obj_len) {
675            printf("%sERROR: object goes past end of objects TLV", ident);
676            return -1;
677        }
678
679        obj_tptr=tptr+sizeof(struct rsvp_object_header);
680        obj_tlen=rsvp_obj_len-sizeof(struct rsvp_object_header);
681
682        /* did we capture enough for fully decoding the object ? */
683        if (!TTEST2(*tptr, rsvp_obj_len))
684            return -1;
685        hexdump=FALSE;
686
687        switch(rsvp_obj_header->class_num) {
688        case RSVP_OBJ_SESSION:
689            switch(rsvp_obj_ctype) {
690            case RSVP_CTYPE_IPV4:
691                if (obj_tlen < 8)
692                    return -1;
693                printf("%s  IPv4 DestAddress: %s, Protocol ID: 0x%02x",
694                       ident,
695                       ipaddr_string(obj_tptr),
696                       *(obj_tptr+sizeof(struct in_addr)));
697                printf("%s  Flags: [0x%02x], DestPort %u",
698                       ident,
699                       *(obj_tptr+5),
700                       EXTRACT_16BITS(obj_tptr+6));
701                obj_tlen-=8;
702                obj_tptr+=8;
703                break;
704#ifdef INET6
705            case RSVP_CTYPE_IPV6:
706                if (obj_tlen < 20)
707                    return -1;
708                printf("%s  IPv6 DestAddress: %s, Protocol ID: 0x%02x",
709                       ident,
710                       ip6addr_string(obj_tptr),
711                       *(obj_tptr+sizeof(struct in6_addr)));
712                printf("%s  Flags: [0x%02x], DestPort %u",
713                       ident,
714                       *(obj_tptr+sizeof(struct in6_addr)+1),
715                       EXTRACT_16BITS(obj_tptr+sizeof(struct in6_addr)+2));
716                obj_tlen-=20;
717                obj_tptr+=20;
718                break;
719
720            case RSVP_CTYPE_TUNNEL_IPV6:
721                if (obj_tlen < 36)
722                    return -1;
723                printf("%s  IPv6 Tunnel EndPoint: %s, Tunnel ID: 0x%04x, Extended Tunnel ID: %s",
724                       ident,
725                       ip6addr_string(obj_tptr),
726                       EXTRACT_16BITS(obj_tptr+18),
727                       ip6addr_string(obj_tptr+20));
728                obj_tlen-=36;
729                obj_tptr+=36;
730                break;
731#endif
732            case RSVP_CTYPE_TUNNEL_IPV4:
733            case RSVP_CTYPE_UNI_IPV4:
734                if (obj_tlen < 12)
735                    return -1;
736                printf("%s  IPv4 Tunnel EndPoint: %s, Tunnel ID: 0x%04x, Extended Tunnel ID: %s",
737                       ident,
738                       ipaddr_string(obj_tptr),
739                       EXTRACT_16BITS(obj_tptr+6),
740                       ipaddr_string(obj_tptr+8));
741                obj_tlen-=12;
742                obj_tptr+=12;
743                break;
744            default:
745                hexdump=TRUE;
746            }
747            break;
748
749        case RSVP_OBJ_CONFIRM:
750            switch(rsvp_obj_ctype) {
751            case RSVP_CTYPE_IPV4:
752                if (obj_tlen < sizeof(struct in_addr))
753                    return -1;
754                printf("%s  IPv4 Receiver Address: %s",
755                       ident,
756                       ipaddr_string(obj_tptr));
757                obj_tlen-=sizeof(struct in_addr);
758                obj_tptr+=sizeof(struct in_addr);
759                break;
760#ifdef INET6
761            case RSVP_CTYPE_IPV6:
762                if (obj_tlen < sizeof(struct in6_addr))
763                    return -1;
764                printf("%s  IPv6 Receiver Address: %s",
765                       ident,
766                       ip6addr_string(obj_tptr));
767                obj_tlen-=sizeof(struct in6_addr);
768                obj_tptr+=sizeof(struct in6_addr);
769                break;
770#endif
771            default:
772                hexdump=TRUE;
773            }
774            break;
775
776        case RSVP_OBJ_NOTIFY_REQ:
777            switch(rsvp_obj_ctype) {
778            case RSVP_CTYPE_IPV4:
779                if (obj_tlen < sizeof(struct in_addr))
780                    return -1;
781                printf("%s  IPv4 Notify Node Address: %s",
782                       ident,
783                       ipaddr_string(obj_tptr));
784                obj_tlen-=sizeof(struct in_addr);
785                obj_tptr+=sizeof(struct in_addr);
786                break;
787#ifdef INET6
788            case RSVP_CTYPE_IPV6:
789                if (obj_tlen < sizeof(struct in6_addr))
790                    return-1;
791                printf("%s  IPv6 Notify Node Address: %s",
792                       ident,
793                       ip6addr_string(obj_tptr));
794                obj_tlen-=sizeof(struct in6_addr);
795                obj_tptr+=sizeof(struct in6_addr);
796                break;
797#endif
798            default:
799                hexdump=TRUE;
800            }
801            break;
802
803        case RSVP_OBJ_SUGGESTED_LABEL: /* fall through */
804        case RSVP_OBJ_UPSTREAM_LABEL:  /* fall through */
805        case RSVP_OBJ_RECOVERY_LABEL:  /* fall through */
806        case RSVP_OBJ_LABEL:
807            switch(rsvp_obj_ctype) {
808            case RSVP_CTYPE_1:
809                while(obj_tlen >= 4 ) {
810                    printf("%s  Label: %u", ident, EXTRACT_32BITS(obj_tptr));
811                    obj_tlen-=4;
812                    obj_tptr+=4;
813                }
814                break;
815            case RSVP_CTYPE_2:
816                if (obj_tlen < 4)
817                    return-1;
818                printf("%s  Generalized Label: %u",
819                       ident,
820                       EXTRACT_32BITS(obj_tptr));
821                obj_tlen-=4;
822                obj_tptr+=4;
823                break;
824            case RSVP_CTYPE_3:
825                if (obj_tlen < 12)
826                    return-1;
827                printf("%s  Waveband ID: %u%s  Start Label: %u, Stop Label: %u",
828                       ident,
829                       EXTRACT_32BITS(obj_tptr),
830                       ident,
831                       EXTRACT_32BITS(obj_tptr+4),
832                       EXTRACT_32BITS(obj_tptr+8));
833                obj_tlen-=12;
834                obj_tptr+=12;
835                break;
836            default:
837                hexdump=TRUE;
838            }
839            break;
840
841        case RSVP_OBJ_STYLE:
842            switch(rsvp_obj_ctype) {
843            case RSVP_CTYPE_1:
844                if (obj_tlen < 4)
845                    return-1;
846                printf("%s  Reservation Style: %s, Flags: [0x%02x]",
847                       ident,
848                       tok2str(rsvp_resstyle_values,
849                               "Unknown",
850                               EXTRACT_24BITS(obj_tptr+1)),
851                       *(obj_tptr));
852                obj_tlen-=4;
853                obj_tptr+=4;
854                break;
855            default:
856                hexdump=TRUE;
857            }
858            break;
859
860        case RSVP_OBJ_SENDER_TEMPLATE:
861            switch(rsvp_obj_ctype) {
862            case RSVP_CTYPE_IPV4:
863                if (obj_tlen < 8)
864                    return-1;
865                printf("%s  Source Address: %s, Source Port: %u",
866                       ident,
867                       ipaddr_string(obj_tptr),
868                       EXTRACT_16BITS(obj_tptr+6));
869                obj_tlen-=8;
870                obj_tptr+=8;
871                break;
872#ifdef INET6
873            case RSVP_CTYPE_IPV6:
874                if (obj_tlen < 20)
875                    return-1;
876                printf("%s  Source Address: %s, Source Port: %u",
877                       ident,
878                       ip6addr_string(obj_tptr),
879                       EXTRACT_16BITS(obj_tptr+18));
880                obj_tlen-=20;
881                obj_tptr+=20;
882                break;
883#endif
884            case RSVP_CTYPE_TUNNEL_IPV4:
885                if (obj_tlen < 8)
886                    return-1;
887                printf("%s  IPv4 Tunnel Sender Address: %s, LSP-ID: 0x%04x",
888                       ident,
889                       ipaddr_string(obj_tptr),
890                       EXTRACT_16BITS(obj_tptr+6));
891                obj_tlen-=8;
892                obj_tptr+=8;
893                break;
894            default:
895                hexdump=TRUE;
896            }
897            break;
898
899        case RSVP_OBJ_LABEL_REQ:
900            switch(rsvp_obj_ctype) {
901            case RSVP_CTYPE_1:
902                while(obj_tlen >= 4 ) {
903                    printf("%s  L3 Protocol ID: %s",
904                           ident,
905                           tok2str(ethertype_values,
906                                   "Unknown Protocol (0x%04x)",
907                                   EXTRACT_16BITS(obj_tptr+2)));
908                    obj_tlen-=4;
909                    obj_tptr+=4;
910                }
911                break;
912            case RSVP_CTYPE_2:
913                if (obj_tlen < 12)
914                    return-1;
915                printf("%s  L3 Protocol ID: %s",
916                       ident,
917                       tok2str(ethertype_values,
918                               "Unknown Protocol (0x%04x)",
919                               EXTRACT_16BITS(obj_tptr+2)));
920                printf(",%s merge capability",((*(obj_tptr+4))&0x80) ? "no" : "" );
921                printf("%s  Minimum VPI/VCI: %u/%u",
922                       ident,
923                       (EXTRACT_16BITS(obj_tptr+4))&0xfff,
924                       (EXTRACT_16BITS(obj_tptr+6))&0xfff);
925                printf("%s  Maximum VPI/VCI: %u/%u",
926                       ident,
927                       (EXTRACT_16BITS(obj_tptr+8))&0xfff,
928                       (EXTRACT_16BITS(obj_tptr+10))&0xfff);
929                obj_tlen-=12;
930                obj_tptr+=12;
931                break;
932            case RSVP_CTYPE_3:
933                if (obj_tlen < 12)
934                    return-1;
935                printf("%s  L3 Protocol ID: %s",
936                       ident,
937                       tok2str(ethertype_values,
938                               "Unknown Protocol (0x%04x)",
939                               EXTRACT_16BITS(obj_tptr+2)));
940                printf("%s  Minimum/Maximum DLCI: %u/%u, %s%s bit DLCI",
941                       ident,
942                       (EXTRACT_32BITS(obj_tptr+4))&0x7fffff,
943                       (EXTRACT_32BITS(obj_tptr+8))&0x7fffff,
944                       (((EXTRACT_16BITS(obj_tptr+4)>>7)&3) == 0 ) ? "10" : "",
945                       (((EXTRACT_16BITS(obj_tptr+4)>>7)&3) == 2 ) ? "23" : "");
946                obj_tlen-=12;
947                obj_tptr+=12;
948                break;
949            case RSVP_CTYPE_4:
950                if (obj_tlen < 4)
951                    return-1;
952                printf("%s  LSP Encoding Type: %s (%u)",
953                       ident,
954                       tok2str(gmpls_encoding_values,
955                               "Unknown",
956                               *obj_tptr),
957		       *obj_tptr);
958                printf("%s  Switching Type: %s (%u), Payload ID: %s (0x%04x)",
959                       ident,
960                       tok2str(gmpls_switch_cap_values,
961                               "Unknown",
962                               *(obj_tptr+1)),
963		       *(obj_tptr+1),
964                       tok2str(gmpls_payload_values,
965                               "Unknown",
966                               EXTRACT_16BITS(obj_tptr+2)),
967		       EXTRACT_16BITS(obj_tptr+2));
968                obj_tlen-=4;
969                obj_tptr+=4;
970                break;
971            default:
972                hexdump=TRUE;
973            }
974            break;
975
976        case RSVP_OBJ_RRO:
977        case RSVP_OBJ_ERO:
978            switch(rsvp_obj_ctype) {
979            case RSVP_CTYPE_IPV4:
980                while(obj_tlen >= 4 ) {
981                    printf("%s  Subobject Type: %s, length %u",
982                           ident,
983                           tok2str(rsvp_obj_xro_values,
984                                   "Unknown %u",
985                                   RSVP_OBJ_XRO_MASK_SUBOBJ(*obj_tptr)),
986                           *(obj_tptr+1));
987
988                    if (*(obj_tptr+1) == 0) { /* prevent infinite loops */
989                        printf("%s  ERROR: zero length ERO subtype",ident);
990                        break;
991                    }
992
993                    switch(RSVP_OBJ_XRO_MASK_SUBOBJ(*obj_tptr)) {
994                    case RSVP_OBJ_XRO_IPV4:
995                        printf(", %s, %s/%u, Flags: [%s]",
996                               RSVP_OBJ_XRO_MASK_LOOSE(*obj_tptr) ? "Loose" : "Strict",
997                               ipaddr_string(obj_tptr+2),
998                               *(obj_tptr+6),
999                               bittok2str(rsvp_obj_rro_flag_values,
1000                                   "none",
1001                                   *(obj_tptr+7))); /* rfc3209 says that this field is rsvd. */
1002                    }
1003                    obj_tlen-=*(obj_tptr+1);
1004                    obj_tptr+=*(obj_tptr+1);
1005                }
1006                break;
1007            default:
1008                hexdump=TRUE;
1009            }
1010            break;
1011
1012        case RSVP_OBJ_HELLO:
1013            switch(rsvp_obj_ctype) {
1014            case RSVP_CTYPE_1:
1015            case RSVP_CTYPE_2:
1016                if (obj_tlen < 8)
1017                    return-1;
1018                printf("%s  Source Instance: 0x%08x, Destination Instance: 0x%08x",
1019                       ident,
1020                       EXTRACT_32BITS(obj_tptr),
1021                       EXTRACT_32BITS(obj_tptr+4));
1022                obj_tlen-=8;
1023                obj_tptr+=8;
1024                break;
1025            default:
1026                hexdump=TRUE;
1027            }
1028            break;
1029
1030        case RSVP_OBJ_RESTART_CAPABILITY:
1031            switch(rsvp_obj_ctype) {
1032            case RSVP_CTYPE_1:
1033                if (obj_tlen < 8)
1034                    return-1;
1035                printf("%s  Restart  Time: %ums, Recovery Time: %ums",
1036                       ident,
1037                       EXTRACT_32BITS(obj_tptr),
1038                       EXTRACT_32BITS(obj_tptr+4));
1039                obj_tlen-=8;
1040                obj_tptr+=8;
1041                break;
1042            default:
1043                hexdump=TRUE;
1044            }
1045            break;
1046
1047        case RSVP_OBJ_SESSION_ATTRIBUTE:
1048            switch(rsvp_obj_ctype) {
1049            case RSVP_CTYPE_TUNNEL_IPV4:
1050                if (obj_tlen < 4)
1051                    return-1;
1052                namelen = *(obj_tptr+3);
1053                if (obj_tlen < 4+namelen)
1054                    return-1;
1055                printf("%s  Session Name: ", ident);
1056                for (i = 0; i < namelen; i++)
1057                    safeputchar(*(obj_tptr+4+i));
1058                printf("%s  Setup Priority: %u, Holding Priority: %u, Flags: [%s]",
1059                       ident,
1060                       (int)*obj_tptr,
1061                       (int)*(obj_tptr+1),
1062                       tok2str(rsvp_session_attribute_flag_values,
1063                                  "none",
1064                                  *(obj_tptr+2)));
1065
1066                obj_tlen-=4+*(obj_tptr+3);
1067                obj_tptr+=4+*(obj_tptr+3);
1068                break;
1069            default:
1070                hexdump=TRUE;
1071            }
1072            break;
1073
1074	case RSVP_OBJ_GENERALIZED_UNI:
1075            switch(rsvp_obj_ctype) {
1076		int subobj_type,af,subobj_len,total_subobj_len;
1077
1078            case RSVP_CTYPE_1:
1079
1080                if (obj_tlen < 4)
1081                    return-1;
1082
1083		/* read variable length subobjects */
1084		total_subobj_len = obj_tlen;
1085                while(total_subobj_len > 0) {
1086                    subobj_len  = EXTRACT_16BITS(obj_tptr);
1087                    subobj_type = (EXTRACT_16BITS(obj_tptr+2))>>8;
1088                    af = (EXTRACT_16BITS(obj_tptr+2))&0x00FF;
1089
1090                    printf("%s  Subobject Type: %s (%u), AF: %s (%u), length: %u",
1091                           ident,
1092                           tok2str(rsvp_obj_generalized_uni_values, "Unknown", subobj_type),
1093                           subobj_type,
1094                           tok2str(af_values, "Unknown", af), af,
1095                           subobj_len);
1096
1097                    switch(subobj_type) {
1098                    case RSVP_GEN_UNI_SUBOBJ_SOURCE_TNA_ADDRESS:
1099                    case RSVP_GEN_UNI_SUBOBJ_DESTINATION_TNA_ADDRESS:
1100
1101                        switch(af) {
1102                        case AFNUM_INET:
1103                            if (subobj_len < 8)
1104                                return -1;
1105                            printf("%s    UNI IPv4 TNA address: %s",
1106                                   ident, ipaddr_string(obj_tptr+4));
1107                            break;
1108#ifdef INET6
1109                        case AFNUM_INET6:
1110                            if (subobj_len < 20)
1111                                return -1;
1112                            printf("%s    UNI IPv6 TNA address: %s",
1113                                   ident, ip6addr_string(obj_tptr+4));
1114                            break;
1115#endif
1116                        case AFNUM_NSAP:
1117                            if (subobj_len) {
1118                                /* unless we have a TLV parser lets just hexdump */
1119                                hexdump=TRUE;
1120                            }
1121                            break;
1122                        }
1123                        break;
1124
1125                    case RSVP_GEN_UNI_SUBOBJ_DIVERSITY:
1126                        if (subobj_len) {
1127                            /* unless we have a TLV parser lets just hexdump */
1128                            hexdump=TRUE;
1129                        }
1130                        break;
1131
1132                    case RSVP_GEN_UNI_SUBOBJ_EGRESS_LABEL:
1133                        if (subobj_len < 16) {
1134                            return -1;
1135                        }
1136
1137                        printf("%s    U-bit: %x, Label type: %u, Logical port id: %u, Label: %u",
1138                               ident,
1139                               ((EXTRACT_32BITS(obj_tptr+4))>>31),
1140                               ((EXTRACT_32BITS(obj_tptr+4))&0xFF),
1141                               EXTRACT_32BITS(obj_tptr+8),
1142                               EXTRACT_32BITS(obj_tptr+12));
1143                        break;
1144
1145                    case RSVP_GEN_UNI_SUBOBJ_SERVICE_LEVEL:
1146                        if (subobj_len < 8) {
1147                            return -1;
1148                        }
1149
1150                        printf("%s    Service level: %u",
1151                               ident, (EXTRACT_32BITS(obj_tptr+4))>>24);
1152                        break;
1153
1154                    default:
1155                        hexdump=TRUE;
1156                        break;
1157                    }
1158                    total_subobj_len-=subobj_len;
1159                    obj_tptr+=subobj_len;
1160                    obj_tlen+=subobj_len;
1161		}
1162
1163                if (total_subobj_len) {
1164                    /* unless we have a TLV parser lets just hexdump */
1165                    hexdump=TRUE;
1166                }
1167                break;
1168
1169            default:
1170                hexdump=TRUE;
1171            }
1172            break;
1173
1174        case RSVP_OBJ_RSVP_HOP:
1175            switch(rsvp_obj_ctype) {
1176            case RSVP_CTYPE_3: /* fall through - FIXME add TLV parser */
1177            case RSVP_CTYPE_IPV4:
1178                if (obj_tlen < 8)
1179                    return-1;
1180                printf("%s  Previous/Next Interface: %s, Logical Interface Handle: 0x%08x",
1181                       ident,
1182                       ipaddr_string(obj_tptr),
1183                       EXTRACT_32BITS(obj_tptr+4));
1184                obj_tlen-=8;
1185                obj_tptr+=8;
1186                if (obj_tlen)
1187                    hexdump=TRUE; /* unless we have a TLV parser lets just hexdump */
1188                break;
1189#ifdef INET6
1190            case RSVP_CTYPE_4: /* fall through - FIXME add TLV parser */
1191            case RSVP_CTYPE_IPV6:
1192                if (obj_tlen < 20)
1193                    return-1;
1194                printf("%s  Previous/Next Interface: %s, Logical Interface Handle: 0x%08x",
1195                       ident,
1196                       ip6addr_string(obj_tptr),
1197                       EXTRACT_32BITS(obj_tptr+16));
1198                obj_tlen-=20;
1199                obj_tptr+=20;
1200                hexdump=TRUE; /* unless we have a TLV parser lets just hexdump */
1201                break;
1202#endif
1203            default:
1204                hexdump=TRUE;
1205            }
1206            break;
1207
1208        case RSVP_OBJ_TIME_VALUES:
1209            switch(rsvp_obj_ctype) {
1210            case RSVP_CTYPE_1:
1211                if (obj_tlen < 4)
1212                    return-1;
1213                printf("%s  Refresh Period: %ums",
1214                       ident,
1215                       EXTRACT_32BITS(obj_tptr));
1216                obj_tlen-=4;
1217                obj_tptr+=4;
1218                break;
1219            default:
1220                hexdump=TRUE;
1221            }
1222            break;
1223
1224        /* those three objects do share the same semantics */
1225        case RSVP_OBJ_SENDER_TSPEC:
1226        case RSVP_OBJ_ADSPEC:
1227        case RSVP_OBJ_FLOWSPEC:
1228            switch(rsvp_obj_ctype) {
1229            case RSVP_CTYPE_2:
1230                if (obj_tlen < 4)
1231                    return-1;
1232                printf("%s  Msg-Version: %u, length: %u",
1233                       ident,
1234                       (*obj_tptr & 0xf0) >> 4,
1235                       EXTRACT_16BITS(obj_tptr+2)<<2);
1236                obj_tptr+=4; /* get to the start of the service header */
1237                obj_tlen-=4;
1238
1239                while (obj_tlen >= 4) {
1240                    intserv_serv_tlen=EXTRACT_16BITS(obj_tptr+2)<<2;
1241                    printf("%s  Service Type: %s (%u), break bit %s set, Service length: %u",
1242                           ident,
1243                           tok2str(rsvp_intserv_service_type_values,"unknown",*(obj_tptr)),
1244                           *(obj_tptr),
1245                           (*(obj_tptr+1)&0x80) ? "" : "not",
1246                           intserv_serv_tlen);
1247
1248                    obj_tptr+=4; /* get to the start of the parameter list */
1249                    obj_tlen-=4;
1250
1251                    while (intserv_serv_tlen>=4) {
1252                        processed = rsvp_intserv_print(obj_tptr, obj_tlen);
1253                        if (processed == 0)
1254                            break;
1255                        obj_tlen-=processed;
1256                        intserv_serv_tlen-=processed;
1257                        obj_tptr+=processed;
1258                    }
1259                }
1260                break;
1261            default:
1262                hexdump=TRUE;
1263            }
1264            break;
1265
1266        case RSVP_OBJ_FILTERSPEC:
1267            switch(rsvp_obj_ctype) {
1268            case RSVP_CTYPE_IPV4:
1269                if (obj_tlen < 8)
1270                    return-1;
1271                printf("%s  Source Address: %s, Source Port: %u",
1272                       ident,
1273                       ipaddr_string(obj_tptr),
1274                       EXTRACT_16BITS(obj_tptr+6));
1275                obj_tlen-=8;
1276                obj_tptr+=8;
1277                break;
1278#ifdef INET6
1279            case RSVP_CTYPE_IPV6:
1280                if (obj_tlen < 20)
1281                    return-1;
1282                printf("%s  Source Address: %s, Source Port: %u",
1283                       ident,
1284                       ip6addr_string(obj_tptr),
1285                       EXTRACT_16BITS(obj_tptr+18));
1286                obj_tlen-=20;
1287                obj_tptr+=20;
1288                break;
1289            case RSVP_CTYPE_3:
1290                if (obj_tlen < 20)
1291                    return-1;
1292                printf("%s  Source Address: %s, Flow Label: %u",
1293                       ident,
1294                       ip6addr_string(obj_tptr),
1295                       EXTRACT_24BITS(obj_tptr+17));
1296                obj_tlen-=20;
1297                obj_tptr+=20;
1298                break;
1299            case RSVP_CTYPE_TUNNEL_IPV6:
1300                if (obj_tlen < 20)
1301                    return-1;
1302                printf("%s  Source Address: %s, LSP-ID: 0x%04x",
1303                       ident,
1304                       ipaddr_string(obj_tptr),
1305                       EXTRACT_16BITS(obj_tptr+18));
1306                obj_tlen-=20;
1307                obj_tptr+=20;
1308                break;
1309#endif
1310            case RSVP_CTYPE_TUNNEL_IPV4:
1311                if (obj_tlen < 8)
1312                    return-1;
1313                printf("%s  Source Address: %s, LSP-ID: 0x%04x",
1314                       ident,
1315                       ipaddr_string(obj_tptr),
1316                       EXTRACT_16BITS(obj_tptr+6));
1317                obj_tlen-=8;
1318                obj_tptr+=8;
1319                break;
1320            default:
1321                hexdump=TRUE;
1322            }
1323            break;
1324
1325        case RSVP_OBJ_FASTREROUTE:
1326            /* the differences between c-type 1 and 7 are minor */
1327            obj_ptr.rsvp_obj_frr = (const struct rsvp_obj_frr_t *)obj_tptr;
1328            bw.i = EXTRACT_32BITS(obj_ptr.rsvp_obj_frr->bandwidth);
1329
1330            switch(rsvp_obj_ctype) {
1331            case RSVP_CTYPE_1: /* new style */
1332                if (obj_tlen < sizeof(struct rsvp_obj_frr_t))
1333                    return-1;
1334                printf("%s  Setup Priority: %u, Holding Priority: %u, Hop-limit: %u, Bandwidth: %.10g Mbps",
1335                       ident,
1336                       (int)obj_ptr.rsvp_obj_frr->setup_prio,
1337                       (int)obj_ptr.rsvp_obj_frr->hold_prio,
1338                       (int)obj_ptr.rsvp_obj_frr->hop_limit,
1339                        bw.f*8/1000000);
1340                printf("%s  Include-any: 0x%08x, Exclude-any: 0x%08x, Include-all: 0x%08x",
1341                       ident,
1342                       EXTRACT_32BITS(obj_ptr.rsvp_obj_frr->include_any),
1343                       EXTRACT_32BITS(obj_ptr.rsvp_obj_frr->exclude_any),
1344                       EXTRACT_32BITS(obj_ptr.rsvp_obj_frr->include_all));
1345                obj_tlen-=sizeof(struct rsvp_obj_frr_t);
1346                obj_tptr+=sizeof(struct rsvp_obj_frr_t);
1347                break;
1348
1349            case RSVP_CTYPE_TUNNEL_IPV4: /* old style */
1350                if (obj_tlen < 16)
1351                    return-1;
1352                printf("%s  Setup Priority: %u, Holding Priority: %u, Hop-limit: %u, Bandwidth: %.10g Mbps",
1353                       ident,
1354                       (int)obj_ptr.rsvp_obj_frr->setup_prio,
1355                       (int)obj_ptr.rsvp_obj_frr->hold_prio,
1356                       (int)obj_ptr.rsvp_obj_frr->hop_limit,
1357                        bw.f*8/1000000);
1358                printf("%s  Include Colors: 0x%08x, Exclude Colors: 0x%08x",
1359                       ident,
1360                       EXTRACT_32BITS(obj_ptr.rsvp_obj_frr->include_any),
1361                       EXTRACT_32BITS(obj_ptr.rsvp_obj_frr->exclude_any));
1362                obj_tlen-=16;
1363                obj_tptr+=16;
1364                break;
1365
1366            default:
1367                hexdump=TRUE;
1368            }
1369            break;
1370
1371        case RSVP_OBJ_DETOUR:
1372            switch(rsvp_obj_ctype) {
1373            case RSVP_CTYPE_TUNNEL_IPV4:
1374                while(obj_tlen >= 8) {
1375                    printf("%s  PLR-ID: %s, Avoid-Node-ID: %s",
1376                           ident,
1377                           ipaddr_string(obj_tptr),
1378                           ipaddr_string(obj_tptr+4));
1379                    obj_tlen-=8;
1380                    obj_tptr+=8;
1381                }
1382                break;
1383            default:
1384                hexdump=TRUE;
1385            }
1386            break;
1387
1388        case RSVP_OBJ_CLASSTYPE:
1389        case RSVP_OBJ_CLASSTYPE_OLD: /* fall through */
1390            switch(rsvp_obj_ctype) {
1391            case RSVP_CTYPE_1:
1392                printf("%s  CT: %u",
1393                       ident,
1394                       EXTRACT_32BITS(obj_tptr)&0x7);
1395                obj_tlen-=4;
1396                obj_tptr+=4;
1397                break;
1398            default:
1399                hexdump=TRUE;
1400            }
1401            break;
1402
1403        case RSVP_OBJ_ERROR_SPEC:
1404            switch(rsvp_obj_ctype) {
1405            case RSVP_CTYPE_3: /* fall through - FIXME add TLV parser */
1406            case RSVP_CTYPE_IPV4:
1407                if (obj_tlen < 8)
1408                    return-1;
1409                error_code=*(obj_tptr+5);
1410                error_value=EXTRACT_16BITS(obj_tptr+6);
1411                printf("%s  Error Node Address: %s, Flags: [0x%02x]%s  Error Code: %s (%u)",
1412                       ident,
1413                       ipaddr_string(obj_tptr),
1414                       *(obj_tptr+4),
1415                       ident,
1416                       tok2str(rsvp_obj_error_code_values,"unknown",error_code),
1417                       error_code);
1418                switch (error_code) {
1419                case RSVP_OBJ_ERROR_SPEC_CODE_ROUTING:
1420                    printf(", Error Value: %s (%u)",
1421                           tok2str(rsvp_obj_error_code_routing_values,"unknown",error_value),
1422                           error_value);
1423                    break;
1424                case RSVP_OBJ_ERROR_SPEC_CODE_DIFFSERV_TE: /* fall through */
1425                case RSVP_OBJ_ERROR_SPEC_CODE_DIFFSERV_TE_OLD:
1426                    printf(", Error Value: %s (%u)",
1427                           tok2str(rsvp_obj_error_code_diffserv_te_values,"unknown",error_value),
1428                           error_value);
1429                    break;
1430                default:
1431                    printf(", Unknown Error Value (%u)", error_value);
1432                    break;
1433                }
1434                obj_tlen-=8;
1435                obj_tptr+=8;
1436                break;
1437#ifdef INET6
1438            case RSVP_CTYPE_4: /* fall through - FIXME add TLV parser */
1439            case RSVP_CTYPE_IPV6:
1440                if (obj_tlen < 20)
1441                    return-1;
1442                error_code=*(obj_tptr+17);
1443                error_value=EXTRACT_16BITS(obj_tptr+18);
1444                printf("%s  Error Node Address: %s, Flags: [0x%02x]%s  Error Code: %s (%u)",
1445                       ident,
1446                       ip6addr_string(obj_tptr),
1447                       *(obj_tptr+16),
1448                       ident,
1449                       tok2str(rsvp_obj_error_code_values,"unknown",error_code),
1450                       error_code);
1451
1452                switch (error_code) {
1453                case RSVP_OBJ_ERROR_SPEC_CODE_ROUTING:
1454                    printf(", Error Value: %s (%u)",
1455                           tok2str(rsvp_obj_error_code_routing_values,"unknown",error_value),
1456			   error_value);
1457                    break;
1458                default:
1459                    break;
1460                }
1461                obj_tlen-=20;
1462                obj_tptr+=20;
1463                break;
1464#endif
1465            default:
1466                hexdump=TRUE;
1467            }
1468            break;
1469
1470        case RSVP_OBJ_PROPERTIES:
1471            switch(rsvp_obj_ctype) {
1472            case RSVP_CTYPE_1:
1473                if (obj_tlen < 4)
1474                    return-1;
1475                padbytes = EXTRACT_16BITS(obj_tptr+2);
1476                printf("%s  TLV count: %u, padding bytes: %u",
1477                       ident,
1478                       EXTRACT_16BITS(obj_tptr),
1479                       padbytes);
1480                obj_tlen-=4;
1481                obj_tptr+=4;
1482                /* loop through as long there is anything longer than the TLV header (2) */
1483                while(obj_tlen >= 2 + padbytes) {
1484                    printf("%s    %s TLV (0x%02x), length: %u", /* length includes header */
1485                           ident,
1486                           tok2str(rsvp_obj_prop_tlv_values,"unknown",*obj_tptr),
1487                           *obj_tptr,
1488                           *(obj_tptr+1));
1489                    if (obj_tlen < *(obj_tptr+1))
1490                        return-1;
1491                    if (*(obj_tptr+1) < 2)
1492                        return -1;
1493                    print_unknown_data(obj_tptr+2,"\n\t\t",*(obj_tptr+1)-2);
1494                    obj_tlen-=*(obj_tptr+1);
1495                    obj_tptr+=*(obj_tptr+1);
1496                }
1497                break;
1498            default:
1499                hexdump=TRUE;
1500            }
1501            break;
1502
1503        case RSVP_OBJ_MESSAGE_ID:     /* fall through */
1504        case RSVP_OBJ_MESSAGE_ID_ACK: /* fall through */
1505        case RSVP_OBJ_MESSAGE_ID_LIST:
1506            switch(rsvp_obj_ctype) {
1507            case RSVP_CTYPE_1:
1508            case RSVP_CTYPE_2:
1509                if (obj_tlen < 8)
1510                    return-1;
1511                printf("%s  Flags [0x%02x], epoch: %u",
1512                       ident,
1513                       *obj_tptr,
1514                       EXTRACT_24BITS(obj_tptr+1));
1515                obj_tlen-=4;
1516                obj_tptr+=4;
1517                /* loop through as long there are no messages left */
1518                while(obj_tlen >= 4) {
1519                    printf("%s    Message-ID 0x%08x (%u)",
1520                           ident,
1521                           EXTRACT_32BITS(obj_tptr),
1522                           EXTRACT_32BITS(obj_tptr));
1523                    obj_tlen-=4;
1524                    obj_tptr+=4;
1525                }
1526                break;
1527            default:
1528                hexdump=TRUE;
1529            }
1530            break;
1531
1532        case RSVP_OBJ_INTEGRITY:
1533            switch(rsvp_obj_ctype) {
1534            case RSVP_CTYPE_1:
1535                if (obj_tlen < sizeof(struct rsvp_obj_integrity_t))
1536                    return-1;
1537                obj_ptr.rsvp_obj_integrity = (const struct rsvp_obj_integrity_t *)obj_tptr;
1538                printf("%s  Key-ID 0x%04x%08x, Sequence 0x%08x%08x, Flags [%s]",
1539                       ident,
1540                       EXTRACT_16BITS(obj_ptr.rsvp_obj_integrity->key_id),
1541                       EXTRACT_32BITS(obj_ptr.rsvp_obj_integrity->key_id+2),
1542                       EXTRACT_32BITS(obj_ptr.rsvp_obj_integrity->sequence),
1543                       EXTRACT_32BITS(obj_ptr.rsvp_obj_integrity->sequence+4),
1544                       bittok2str(rsvp_obj_integrity_flag_values,
1545                                  "none",
1546                                  obj_ptr.rsvp_obj_integrity->flags));
1547                printf("%s  MD5-sum 0x%08x%08x%08x%08x (unverified)",
1548                       ident,
1549                       EXTRACT_32BITS(obj_ptr.rsvp_obj_integrity->digest),
1550                       EXTRACT_32BITS(obj_ptr.rsvp_obj_integrity->digest+4),
1551                       EXTRACT_32BITS(obj_ptr.rsvp_obj_integrity->digest+8),
1552                       EXTRACT_32BITS(obj_ptr.rsvp_obj_integrity->digest+12));
1553                obj_tlen+=sizeof(struct rsvp_obj_integrity_t);
1554                obj_tptr+=sizeof(struct rsvp_obj_integrity_t);
1555                break;
1556            default:
1557                hexdump=TRUE;
1558            }
1559            break;
1560
1561        case RSVP_OBJ_ADMIN_STATUS:
1562            switch(rsvp_obj_ctype) {
1563            case RSVP_CTYPE_1:
1564                if (obj_tlen < 4)
1565                    return-1;
1566                printf("%s  Flags [%s]", ident,
1567                       bittok2str(rsvp_obj_admin_status_flag_values, "none",
1568                                  EXTRACT_32BITS(obj_tptr)));
1569                obj_tlen-=4;
1570                obj_tptr+=4;
1571                break;
1572            default:
1573                hexdump=TRUE;
1574            }
1575            break;
1576
1577        case RSVP_OBJ_LABEL_SET:
1578            switch(rsvp_obj_ctype) {
1579            case RSVP_CTYPE_1:
1580                if (obj_tlen < 4)
1581                    return-1;
1582                action = (EXTRACT_16BITS(obj_tptr)>>8);
1583
1584                printf("%s  Action: %s (%u), Label type: %u", ident,
1585                       tok2str(rsvp_obj_label_set_action_values, "Unknown", action),
1586                       action, ((EXTRACT_32BITS(obj_tptr) & 0x7F)));
1587
1588                switch (action) {
1589                case LABEL_SET_INCLUSIVE_RANGE:
1590                case LABEL_SET_EXCLUSIVE_RANGE: /* fall through */
1591
1592		    /* only a couple of subchannels are expected */
1593		    if (obj_tlen < 12)
1594			return -1;
1595		    printf("%s  Start range: %u, End range: %u", ident,
1596                           EXTRACT_32BITS(obj_tptr+4),
1597                           EXTRACT_32BITS(obj_tptr+8));
1598		    obj_tlen-=12;
1599		    obj_tptr+=12;
1600                    break;
1601
1602                default:
1603                    obj_tlen-=4;
1604                    obj_tptr+=4;
1605                    subchannel = 1;
1606                    while(obj_tlen >= 4 ) {
1607                        printf("%s  Subchannel #%u: %u", ident, subchannel,
1608                               EXTRACT_32BITS(obj_tptr));
1609                        obj_tptr+=4;
1610                        obj_tlen-=4;
1611                        subchannel++;
1612                    }
1613                    break;
1614                }
1615                break;
1616
1617            default:
1618                hexdump=TRUE;
1619            }
1620
1621        /*
1622         *  FIXME those are the defined objects that lack a decoder
1623         *  you are welcome to contribute code ;-)
1624         */
1625
1626        case RSVP_OBJ_SCOPE:
1627        case RSVP_OBJ_POLICY_DATA:
1628        case RSVP_OBJ_ACCEPT_LABEL_SET:
1629        case RSVP_OBJ_PROTECTION:
1630        default:
1631            if (vflag <= 1)
1632                print_unknown_data(obj_tptr,"\n\t    ",obj_tlen); /* FIXME indentation */
1633            break;
1634        }
1635        /* do we also want to see a hex dump ? */
1636        if (vflag > 1 || hexdump==TRUE)
1637            print_unknown_data(tptr+sizeof(sizeof(struct rsvp_object_header)),"\n\t    ", /* FIXME indentation */
1638                               rsvp_obj_len-sizeof(struct rsvp_object_header));
1639
1640        tptr+=rsvp_obj_len;
1641        tlen-=rsvp_obj_len;
1642    }
1643    return 0;
1644trunc:
1645    printf("\n\t\t packet exceeded snapshot");
1646    return -1;
1647}
1648
1649
1650void
1651rsvp_print(register const u_char *pptr, register u_int len) {
1652
1653    const struct rsvp_common_header *rsvp_com_header;
1654    const u_char *tptr,*subtptr;
1655    u_short tlen,subtlen;
1656
1657    tptr=pptr;
1658
1659    rsvp_com_header = (const struct rsvp_common_header *)pptr;
1660    TCHECK(*rsvp_com_header);
1661
1662    /*
1663     * Sanity checking of the header.
1664     */
1665    if (RSVP_EXTRACT_VERSION(rsvp_com_header->version_flags) != RSVP_VERSION) {
1666	printf("ERROR: RSVP version %u packet not supported",
1667               RSVP_EXTRACT_VERSION(rsvp_com_header->version_flags));
1668	return;
1669    }
1670
1671    /* in non-verbose mode just lets print the basic Message Type*/
1672    if (vflag < 1) {
1673        printf("RSVPv%u %s Message, length: %u",
1674               RSVP_EXTRACT_VERSION(rsvp_com_header->version_flags),
1675               tok2str(rsvp_msg_type_values, "unknown (%u)",rsvp_com_header->msg_type),
1676               len);
1677        return;
1678    }
1679
1680    /* ok they seem to want to know everything - lets fully decode it */
1681
1682    tlen=EXTRACT_16BITS(rsvp_com_header->length);
1683
1684    printf("\n\tRSVPv%u %s Message (%u), Flags: [%s], length: %u, ttl: %u, checksum: 0x%04x",
1685           RSVP_EXTRACT_VERSION(rsvp_com_header->version_flags),
1686           tok2str(rsvp_msg_type_values, "unknown, type: %u",rsvp_com_header->msg_type),
1687           rsvp_com_header->msg_type,
1688           bittok2str(rsvp_header_flag_values,"none",RSVP_EXTRACT_FLAGS(rsvp_com_header->version_flags)),
1689           tlen,
1690           rsvp_com_header->ttl,
1691           EXTRACT_16BITS(rsvp_com_header->checksum));
1692
1693    if (tlen < sizeof(const struct rsvp_common_header)) {
1694        printf("ERROR: common header too short %u < %lu", tlen,
1695               (unsigned long)sizeof(const struct rsvp_common_header));
1696        return;
1697    }
1698
1699    tptr+=sizeof(const struct rsvp_common_header);
1700    tlen-=sizeof(const struct rsvp_common_header);
1701
1702    switch(rsvp_com_header->msg_type) {
1703
1704    case RSVP_MSGTYPE_AGGREGATE:
1705        while(tlen > 0) {
1706            subtptr=tptr;
1707            rsvp_com_header = (const struct rsvp_common_header *)subtptr;
1708            TCHECK(*rsvp_com_header);
1709
1710            /*
1711             * Sanity checking of the header.
1712             */
1713            if (RSVP_EXTRACT_VERSION(rsvp_com_header->version_flags) != RSVP_VERSION) {
1714                printf("ERROR: RSVP version %u packet not supported",
1715                       RSVP_EXTRACT_VERSION(rsvp_com_header->version_flags));
1716                return;
1717            }
1718            subtlen=EXTRACT_16BITS(rsvp_com_header->length);
1719
1720            printf("\n\t  RSVPv%u %s Message (%u), Flags: [%s], length: %u, ttl: %u, checksum: 0x%04x",
1721                   RSVP_EXTRACT_VERSION(rsvp_com_header->version_flags),
1722                   tok2str(rsvp_msg_type_values, "unknown, type: %u",rsvp_com_header->msg_type),
1723                   rsvp_com_header->msg_type,
1724                   bittok2str(rsvp_header_flag_values,"none",RSVP_EXTRACT_FLAGS(rsvp_com_header->version_flags)),
1725                   subtlen,
1726                   rsvp_com_header->ttl,
1727                   EXTRACT_16BITS(rsvp_com_header->checksum));
1728
1729            if (subtlen < sizeof(const struct rsvp_common_header)) {
1730                printf("ERROR: common header too short %u < %lu", subtlen,
1731                       (unsigned long)sizeof(const struct rsvp_common_header));
1732                return;
1733            }
1734
1735            if (tlen < subtlen) {
1736                printf("ERROR: common header too large %u > %u", subtlen,
1737                       tlen);
1738                return;
1739            }
1740
1741            subtptr+=sizeof(const struct rsvp_common_header);
1742            subtlen-=sizeof(const struct rsvp_common_header);
1743
1744            if (rsvp_obj_print(subtptr,"\n\t    ", subtlen) == -1)
1745                return;
1746
1747            tptr+=subtlen+sizeof(const struct rsvp_common_header);
1748            tlen-=subtlen+sizeof(const struct rsvp_common_header);
1749        }
1750
1751        break;
1752
1753    case RSVP_MSGTYPE_PATH:
1754    case RSVP_MSGTYPE_RESV:
1755    case RSVP_MSGTYPE_PATHERR:
1756    case RSVP_MSGTYPE_RESVERR:
1757    case RSVP_MSGTYPE_PATHTEAR:
1758    case RSVP_MSGTYPE_RESVTEAR:
1759    case RSVP_MSGTYPE_RESVCONF:
1760    case RSVP_MSGTYPE_HELLO_OLD:
1761    case RSVP_MSGTYPE_HELLO:
1762    case RSVP_MSGTYPE_ACK:
1763    case RSVP_MSGTYPE_SREFRESH:
1764        if (rsvp_obj_print(tptr,"\n\t  ", tlen) == -1)
1765            return;
1766        break;
1767
1768    default:
1769        print_unknown_data(tptr,"\n\t    ",tlen);
1770        break;
1771    }
1772
1773    return;
1774trunc:
1775    printf("\n\t\t packet exceeded snapshot");
1776}
1777