print-lspping.c revision 313537
1/*
2 * Redistribution and use in source and binary forms, with or without
3 * modification, are permitted provided that: (1) source code
4 * distributions retain the above copyright notice and this paragraph
5 * in its entirety, and (2) distributions including binary code include
6 * the above copyright notice and this paragraph in its entirety in
7 * the documentation or other materials provided with the distribution.
8 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
9 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
10 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
11 * FOR A PARTICULAR PURPOSE.
12 *
13 * Original code by Hannes Gredler (hannes@juniper.net)
14 */
15
16/* \summary: MPLS LSP PING printer */
17
18#ifdef HAVE_CONFIG_H
19#include "config.h"
20#endif
21
22#include <netdissect-stdinc.h>
23
24#include "netdissect.h"
25#include "extract.h"
26#include "addrtoname.h"
27
28#include "l2vpn.h"
29#include "oui.h"
30
31/* RFC 4349 */
32
33/*
34 * LSPPING common header
35 *
36 *  0                   1                   2                   3
37 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
38 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39 * |         Version Number        |         Must Be Zero          |
40 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41 * |  Message Type |   Reply mode  |  Return Code  | Return Subcode|
42 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43 * |                        Sender's Handle                        |
44 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45 * |                        Sequence Number                        |
46 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47 * |                    TimeStamp Sent (seconds)                   |
48 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49 * |                  TimeStamp Sent (microseconds)                |
50 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51 * |                  TimeStamp Received (seconds)                 |
52 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53 * |                TimeStamp Received (microseconds)              |
54 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55 * |                            TLVs ...                           |
56 * .                                                               .
57 * .                                                               .
58 * .                                                               .
59 */
60
61struct lspping_common_header {
62    uint8_t version[2];
63    uint8_t global_flags[2];
64    uint8_t msg_type;
65    uint8_t reply_mode;
66    uint8_t return_code;
67    uint8_t return_subcode;
68    uint8_t sender_handle[4];
69    uint8_t seq_number[4];
70    uint8_t ts_sent_sec[4];
71    uint8_t ts_sent_usec[4];
72    uint8_t ts_rcvd_sec[4];
73    uint8_t ts_rcvd_usec[4];
74};
75
76#define LSPPING_VERSION            1
77
78static const struct tok lspping_msg_type_values[] = {
79    { 1, "MPLS Echo Request"},
80    { 2, "MPLS Echo Reply"},
81    { 0, NULL}
82};
83
84static const struct tok lspping_reply_mode_values[] = {
85    { 1, "Do not reply"},
86    { 2, "Reply via an IPv4/IPv6 UDP packet"},
87    { 3, "Reply via an IPv4/IPv6 UDP packet with Router Alert"},
88    { 4, "Reply via application level control channel"},
89    { 0, NULL}
90};
91
92static const struct tok lspping_return_code_values[] = {
93    {  0, "No return code or return code contained in the Error Code TLV"},
94    {  1, "Malformed echo request received"},
95    {  2, "One or more of the TLVs was not understood"},
96    {  3, "Replying router is an egress for the FEC at stack depth"},
97    {  4, "Replying router has no mapping for the FEC at stack depth"},
98    {  5, "Reserved"},
99    {  6, "Reserved"},
100    {  7, "Reserved"},
101    {  8, "Label switched at stack-depth"},
102    {  9, "Label switched but no MPLS forwarding at stack-depth"},
103    { 10, "Mapping for this FEC is not the given label at stack depth"},
104    { 11, "No label entry at stack-depth"},
105    { 12, "Protocol not associated with interface at FEC stack depth"},
106    { 13, "Premature termination of ping due to label stack shrinking to a single label"},
107};
108
109
110/*
111 * LSPPING TLV header
112 *  0                   1                   2                   3
113 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
114 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
115 * |             Type              |            Length             |
116 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
117 * |                             Value                             |
118 * .                                                               .
119 * .                                                               .
120 * .                                                               .
121 * |                                                               |
122 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
123 */
124
125struct lspping_tlv_header {
126    uint8_t type[2];
127    uint8_t length[2];
128};
129
130#define	LSPPING_TLV_TARGET_FEC_STACK      1
131#define	LSPPING_TLV_DOWNSTREAM_MAPPING    2
132#define	LSPPING_TLV_PAD                   3
133/* not assigned                           4 */
134#define LSPPING_TLV_VENDOR_ENTERPRISE     5
135#define LSPPING_TLV_VENDOR_ENTERPRISE_LEN 4
136/* not assigned                           6 */
137#define LSPPING_TLV_INTERFACE_LABEL_STACK 7
138/* not assigned                           8 */
139#define	LSPPING_TLV_ERROR_CODE            9
140#define LSPPING_TLV_REPLY_TOS_BYTE        10
141#define	LSPPING_TLV_BFD_DISCRIMINATOR     15 /* draft-ietf-bfd-mpls-02 */
142#define LSPPING_TLV_BFD_DISCRIMINATOR_LEN 4
143#define	LSPPING_TLV_VENDOR_PRIVATE        0xfc00
144
145static const struct tok lspping_tlv_values[] = {
146    { LSPPING_TLV_TARGET_FEC_STACK, "Target FEC Stack" },
147    { LSPPING_TLV_DOWNSTREAM_MAPPING, "Downstream Mapping" },
148    { LSPPING_TLV_PAD, "Pad" },
149    { LSPPING_TLV_ERROR_CODE, "Error Code" },
150    { LSPPING_TLV_VENDOR_ENTERPRISE, "Vendor Enterprise Code" },
151    { LSPPING_TLV_INTERFACE_LABEL_STACK, "Interface Label Stack" },
152    { LSPPING_TLV_REPLY_TOS_BYTE, "Reply TOS Byte" },
153    { LSPPING_TLV_BFD_DISCRIMINATOR, "BFD Discriminator" },
154    { LSPPING_TLV_VENDOR_PRIVATE, "Vendor Private Code" },
155    { 0, NULL}
156};
157
158#define	LSPPING_TLV_TARGETFEC_SUBTLV_LDP_IPV4       1
159#define	LSPPING_TLV_TARGETFEC_SUBTLV_LDP_IPV6       2
160#define	LSPPING_TLV_TARGETFEC_SUBTLV_RSVP_IPV4      3
161#define	LSPPING_TLV_TARGETFEC_SUBTLV_RSVP_IPV6      4
162/* not assigned                                     5 */
163#define	LSPPING_TLV_TARGETFEC_SUBTLV_L3VPN_IPV4     6
164#define	LSPPING_TLV_TARGETFEC_SUBTLV_L3VPN_IPV6     7
165#define	LSPPING_TLV_TARGETFEC_SUBTLV_L2VPN_ENDPT    8
166#define	LSPPING_TLV_TARGETFEC_SUBTLV_FEC_128_PW_OLD 9
167#define	LSPPING_TLV_TARGETFEC_SUBTLV_FEC_128_PW     10
168#define	LSPPING_TLV_TARGETFEC_SUBTLV_FEC_129_PW     11
169#define	LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV4       12
170#define	LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV6       13
171#define	LSPPING_TLV_TARGETFEC_SUBTLV_GENERIC_IPV4   14
172#define	LSPPING_TLV_TARGETFEC_SUBTLV_GENERIC_IPV6   15
173#define	LSPPING_TLV_TARGETFEC_SUBTLV_NIL_FEC        16
174
175static const struct tok lspping_tlvtargetfec_subtlv_values[] = {
176    { LSPPING_TLV_TARGETFEC_SUBTLV_LDP_IPV4, "LDP IPv4 prefix"},
177    { LSPPING_TLV_TARGETFEC_SUBTLV_LDP_IPV6, "LDP IPv6 prefix"},
178    { LSPPING_TLV_TARGETFEC_SUBTLV_RSVP_IPV4, "RSVP IPv4 Session Query"},
179    { LSPPING_TLV_TARGETFEC_SUBTLV_RSVP_IPV6, "RSVP IPv6 Session Query"},
180    { 5, "Reserved"},
181    { LSPPING_TLV_TARGETFEC_SUBTLV_L3VPN_IPV4, "VPN IPv4 prefix"},
182    { LSPPING_TLV_TARGETFEC_SUBTLV_L3VPN_IPV6, "VPN IPv6 prefix"},
183    { LSPPING_TLV_TARGETFEC_SUBTLV_L2VPN_ENDPT, "L2 VPN endpoint"},
184    { LSPPING_TLV_TARGETFEC_SUBTLV_FEC_128_PW_OLD, "FEC 128 pseudowire (old)"},
185    { LSPPING_TLV_TARGETFEC_SUBTLV_FEC_128_PW, "FEC 128 pseudowire"},
186    { LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV4, "BGP labeled IPv4 prefix"},
187    { LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV6, "BGP labeled IPv6 prefix"},
188    { 0, NULL}
189};
190
191/*
192 *  0                   1                   2                   3
193 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
194 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
195 * |                          IPv4 prefix                          |
196 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
197 * | Prefix Length |         Must Be Zero                          |
198 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
199 */
200struct lspping_tlv_targetfec_subtlv_ldp_ipv4_t {
201    uint8_t prefix [4];
202    uint8_t prefix_len;
203};
204
205/*
206 *  0                   1                   2                   3
207 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
208 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
209 * |                          IPv6 prefix                          |
210 * |                          (16 octets)                          |
211 * |                                                               |
212 * |                                                               |
213 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
214 * | Prefix Length |         Must Be Zero                          |
215 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
216 */
217struct lspping_tlv_targetfec_subtlv_ldp_ipv6_t {
218    uint8_t prefix [16];
219    uint8_t prefix_len;
220};
221
222/*
223 *  0                   1                   2                   3
224 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
225 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
226 * |                 IPv4 tunnel end point address                 |
227 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
228 * |          Must Be Zero         |     Tunnel ID                 |
229 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
230 * |                       Extended Tunnel ID                      |
231 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
232 * |                   IPv4 tunnel sender address                  |
233 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
234 * |          Must Be Zero         |            LSP ID             |
235 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
236 */
237struct lspping_tlv_targetfec_subtlv_rsvp_ipv4_t {
238    uint8_t tunnel_endpoint [4];
239    uint8_t res[2];
240    uint8_t tunnel_id[2];
241    uint8_t extended_tunnel_id[4];
242    uint8_t tunnel_sender [4];
243    uint8_t res2[2];
244    uint8_t lsp_id [2];
245};
246
247/*
248 *  0                   1                   2                   3
249 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
250 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
251 * |                 IPv6 tunnel end point address                 |
252 * |                                                               |
253 * |                                                               |
254 * |                                                               |
255 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
256 * |          Must Be Zero         |          Tunnel ID            |
257 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
258 * |                       Extended Tunnel ID                      |
259 * |                                                               |
260 * |                                                               |
261 * |                                                               |
262 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
263 * |                   IPv6 tunnel sender address                  |
264 * |                                                               |
265 * |                                                               |
266 * |                                                               |
267 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
268 * |          Must Be Zero         |            LSP ID             |
269 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
270 */
271struct lspping_tlv_targetfec_subtlv_rsvp_ipv6_t {
272    uint8_t tunnel_endpoint [16];
273    uint8_t res[2];
274    uint8_t tunnel_id[2];
275    uint8_t extended_tunnel_id[16];
276    uint8_t tunnel_sender [16];
277    uint8_t res2[2];
278    uint8_t lsp_id [2];
279};
280
281/*
282 *  0                   1                   2                   3
283 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
284 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
285 * |                      Route Distinguisher                      |
286 * |                          (8 octets)                           |
287 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
288 * |                         IPv4 prefix                           |
289 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
290 * | Prefix Length |                 Must Be Zero                  |
291 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
292 */
293struct lspping_tlv_targetfec_subtlv_l3vpn_ipv4_t {
294    uint8_t rd [8];
295    uint8_t prefix [4];
296    uint8_t prefix_len;
297};
298
299/*
300 *  0                   1                   2                   3
301 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
302 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
303 * |                      Route Distinguisher                      |
304 * |                          (8 octets)                           |
305 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
306 * |                          IPv6 prefix                          |
307 * |                          (16 octets)                          |
308 * |                                                               |
309 * |                                                               |
310 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
311 * | Prefix Length |                 Must Be Zero                  |
312 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
313 */
314struct lspping_tlv_targetfec_subtlv_l3vpn_ipv6_t {
315    uint8_t rd [8];
316    uint8_t prefix [16];
317    uint8_t prefix_len;
318};
319
320/*
321 *  0                   1                   2                   3
322 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
323 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
324 * |                      Route Distinguisher                      |
325 * |                          (8 octets)                           |
326 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
327 * |         Sender's VE ID        |       Receiver's VE ID        |
328 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
329 * |      Encapsulation Type       |         Must Be Zero          |
330 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
331 *  0                   1                   2                   3
332 */
333struct lspping_tlv_targetfec_subtlv_l2vpn_endpt_t {
334    uint8_t rd [8];
335    uint8_t sender_ve_id [2];
336    uint8_t receiver_ve_id [2];
337    uint8_t encapsulation[2];
338};
339
340/*
341 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
342 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
343 * |                      Remote PE Address                        |
344 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
345 * |                             PW ID                             |
346 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
347 * |            PW Type            |          Must Be Zero         |
348 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
349 */
350struct lspping_tlv_targetfec_subtlv_fec_128_pw_old {
351    uint8_t remote_pe_address [4];
352    uint8_t pw_id [4];
353    uint8_t pw_type[2];
354};
355
356/*
357 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
358 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
359 * |                     Sender's PE Address                       |
360 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
361 * |                      Remote PE Address                        |
362 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
363 * |                             PW ID                             |
364 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
365 * |            PW Type            |          Must Be Zero         |
366 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
367 */
368struct lspping_tlv_targetfec_subtlv_fec_128_pw {
369    uint8_t sender_pe_address [4];
370    uint8_t remote_pe_address [4];
371    uint8_t pw_id [4];
372    uint8_t pw_type[2];
373};
374
375/*
376 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
377 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
378 * |                         IPv4 prefix                           |
379 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
380 * | Prefix Length |                 Must Be Zero                  |
381 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
382 */
383struct lspping_tlv_targetfec_subtlv_bgp_ipv4_t {
384    uint8_t prefix [4];
385    uint8_t prefix_len;
386};
387
388/*
389 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
390 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
391 * |                          IPv6 prefix                          |
392 * |                          (16 octets)                          |
393 * |                                                               |
394 * |                                                               |
395 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
396 * | Prefix Length |                 Must Be Zero                  |
397 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
398 */
399struct lspping_tlv_targetfec_subtlv_bgp_ipv6_t {
400    uint8_t prefix [16];
401    uint8_t prefix_len;
402};
403
404/*
405 *  0                   1                   2                   3
406 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
407 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
408 * |               MTU             | Address Type  |  Resvd (SBZ)  |
409 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
410 * |             Downstream IP Address (4 or 16 octets)            |
411 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
412 * |         Downstream Interface Address (4 or 16 octets)         |
413 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
414 * | Multipath Type| Depth Limit   |        Multipath Length       |
415 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
416 * .                                                               .
417 * .                     (Multipath Information)                   .
418 * .                                                               .
419 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
420 * |               Downstream Label                |    Protocol   |
421 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
422 * .                                                               .
423 * .                                                               .
424 * .                                                               .
425 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
426 * |               Downstream Label                |    Protocol   |
427 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
428 */
429/* Enough to get the address type */
430struct lspping_tlv_downstream_map_t {
431    uint8_t mtu [2];
432    uint8_t address_type;
433    uint8_t ds_flags;
434};
435
436struct lspping_tlv_downstream_map_ipv4_t {
437    uint8_t mtu [2];
438    uint8_t address_type;
439    uint8_t ds_flags;
440    uint8_t downstream_ip[4];
441    uint8_t downstream_interface[4];
442};
443
444struct lspping_tlv_downstream_map_ipv4_unmb_t {
445    uint8_t mtu [2];
446    uint8_t address_type;
447    uint8_t ds_flags;
448    uint8_t downstream_ip[4];
449    uint8_t downstream_interface[4];
450};
451
452struct lspping_tlv_downstream_map_ipv6_t {
453    uint8_t mtu [2];
454    uint8_t address_type;
455    uint8_t ds_flags;
456    uint8_t downstream_ip[16];
457    uint8_t downstream_interface[16];
458};
459
460struct lspping_tlv_downstream_map_ipv6_unmb_t {
461    uint8_t mtu [2];
462    uint8_t address_type;
463    uint8_t ds_flags;
464    uint8_t downstream_ip[16];
465    uint8_t downstream_interface[4];
466};
467
468struct lspping_tlv_downstream_map_info_t {
469    uint8_t multipath_type;
470    uint8_t depth_limit;
471    uint8_t multipath_length [2];
472};
473
474#define LSPPING_AFI_IPV4      1
475#define LSPPING_AFI_IPV4_UNMB 2
476#define LSPPING_AFI_IPV6      3
477#define LSPPING_AFI_IPV6_UNMB 4
478
479static const struct tok lspping_tlv_downstream_addr_values[] = {
480    { LSPPING_AFI_IPV4,      "IPv4"},
481    { LSPPING_AFI_IPV4_UNMB, "Unnumbered IPv4"},
482    { LSPPING_AFI_IPV6,      "IPv6"},
483    { LSPPING_AFI_IPV6_UNMB, "IPv6"},
484    { 0, NULL}
485};
486
487void
488lspping_print(netdissect_options *ndo,
489              register const u_char *pptr, register u_int len)
490{
491    const struct lspping_common_header *lspping_com_header;
492    const struct lspping_tlv_header *lspping_tlv_header;
493    const struct lspping_tlv_header *lspping_subtlv_header;
494    const u_char *tptr,*tlv_tptr,*subtlv_tptr;
495    u_int tlen,lspping_tlv_len,lspping_tlv_type,tlv_tlen;
496    int tlv_hexdump,subtlv_hexdump;
497    u_int lspping_subtlv_len,lspping_subtlv_type;
498    struct timeval timestamp;
499
500    union {
501        const struct lspping_tlv_downstream_map_t *lspping_tlv_downstream_map;
502        const struct lspping_tlv_downstream_map_ipv4_t *lspping_tlv_downstream_map_ipv4;
503        const struct lspping_tlv_downstream_map_ipv4_unmb_t *lspping_tlv_downstream_map_ipv4_unmb;
504        const struct lspping_tlv_downstream_map_ipv6_t *lspping_tlv_downstream_map_ipv6;
505        const struct lspping_tlv_downstream_map_ipv6_unmb_t *lspping_tlv_downstream_map_ipv6_unmb;
506        const struct lspping_tlv_downstream_map_info_t  *lspping_tlv_downstream_map_info;
507    } tlv_ptr;
508
509    union {
510        const struct lspping_tlv_targetfec_subtlv_ldp_ipv4_t *lspping_tlv_targetfec_subtlv_ldp_ipv4;
511        const struct lspping_tlv_targetfec_subtlv_ldp_ipv6_t *lspping_tlv_targetfec_subtlv_ldp_ipv6;
512        const struct lspping_tlv_targetfec_subtlv_rsvp_ipv4_t *lspping_tlv_targetfec_subtlv_rsvp_ipv4;
513        const struct lspping_tlv_targetfec_subtlv_rsvp_ipv6_t *lspping_tlv_targetfec_subtlv_rsvp_ipv6;
514        const struct lspping_tlv_targetfec_subtlv_l3vpn_ipv4_t *lspping_tlv_targetfec_subtlv_l3vpn_ipv4;
515        const struct lspping_tlv_targetfec_subtlv_l3vpn_ipv6_t *lspping_tlv_targetfec_subtlv_l3vpn_ipv6;
516        const struct lspping_tlv_targetfec_subtlv_l2vpn_endpt_t *lspping_tlv_targetfec_subtlv_l2vpn_endpt;
517        const struct lspping_tlv_targetfec_subtlv_fec_128_pw_old *lspping_tlv_targetfec_subtlv_l2vpn_vcid_old;
518        const struct lspping_tlv_targetfec_subtlv_fec_128_pw *lspping_tlv_targetfec_subtlv_l2vpn_vcid;
519        const struct lspping_tlv_targetfec_subtlv_bgp_ipv4_t *lspping_tlv_targetfec_subtlv_bgp_ipv4;
520        const struct lspping_tlv_targetfec_subtlv_bgp_ipv6_t *lspping_tlv_targetfec_subtlv_bgp_ipv6;
521    } subtlv_ptr;
522
523    tptr=pptr;
524    lspping_com_header = (const struct lspping_common_header *)pptr;
525    if (len < sizeof(const struct lspping_common_header))
526        goto tooshort;
527    ND_TCHECK(*lspping_com_header);
528
529    /*
530     * Sanity checking of the header.
531     */
532    if (EXTRACT_16BITS(&lspping_com_header->version[0]) != LSPPING_VERSION) {
533	ND_PRINT((ndo, "LSP-PING version %u packet not supported",
534               EXTRACT_16BITS(&lspping_com_header->version[0])));
535	return;
536    }
537
538    /* in non-verbose mode just lets print the basic Message Type*/
539    if (ndo->ndo_vflag < 1) {
540        ND_PRINT((ndo, "LSP-PINGv%u, %s, seq %u, length: %u",
541               EXTRACT_16BITS(&lspping_com_header->version[0]),
542               tok2str(lspping_msg_type_values, "unknown (%u)",lspping_com_header->msg_type),
543               EXTRACT_32BITS(lspping_com_header->seq_number),
544               len));
545        return;
546    }
547
548    /* ok they seem to want to know everything - lets fully decode it */
549
550    tlen=len;
551
552    ND_PRINT((ndo, "\n\tLSP-PINGv%u, msg-type: %s (%u), length: %u\n\t  reply-mode: %s (%u)",
553           EXTRACT_16BITS(&lspping_com_header->version[0]),
554           tok2str(lspping_msg_type_values, "unknown",lspping_com_header->msg_type),
555           lspping_com_header->msg_type,
556           len,
557           tok2str(lspping_reply_mode_values, "unknown",lspping_com_header->reply_mode),
558           lspping_com_header->reply_mode));
559
560    /*
561     *  the following return codes require that the subcode is attached
562     *  at the end of the translated token output
563     */
564    if (lspping_com_header->return_code == 3 ||
565        lspping_com_header->return_code == 4 ||
566        lspping_com_header->return_code == 8 ||
567        lspping_com_header->return_code == 10 ||
568        lspping_com_header->return_code == 11 ||
569        lspping_com_header->return_code == 12 )
570        ND_PRINT((ndo, "\n\t  Return Code: %s %u (%u)\n\t  Return Subcode: (%u)",
571               tok2str(lspping_return_code_values, "unknown",lspping_com_header->return_code),
572               lspping_com_header->return_subcode,
573               lspping_com_header->return_code,
574               lspping_com_header->return_subcode));
575    else
576        ND_PRINT((ndo, "\n\t  Return Code: %s (%u)\n\t  Return Subcode: (%u)",
577               tok2str(lspping_return_code_values, "unknown",lspping_com_header->return_code),
578               lspping_com_header->return_code,
579               lspping_com_header->return_subcode));
580
581    ND_PRINT((ndo, "\n\t  Sender Handle: 0x%08x, Sequence: %u",
582           EXTRACT_32BITS(lspping_com_header->sender_handle),
583           EXTRACT_32BITS(lspping_com_header->seq_number)));
584
585    timestamp.tv_sec=EXTRACT_32BITS(lspping_com_header->ts_sent_sec);
586    timestamp.tv_usec=EXTRACT_32BITS(lspping_com_header->ts_sent_usec);
587    ND_PRINT((ndo, "\n\t  Sender Timestamp: "));
588    ts_print(ndo, &timestamp);
589
590    timestamp.tv_sec=EXTRACT_32BITS(lspping_com_header->ts_rcvd_sec);
591    timestamp.tv_usec=EXTRACT_32BITS(lspping_com_header->ts_rcvd_usec);
592    ND_PRINT((ndo, "Receiver Timestamp: "));
593    if ((timestamp.tv_sec != 0) && (timestamp.tv_usec != 0))
594        ts_print(ndo, &timestamp);
595    else
596        ND_PRINT((ndo, "no timestamp"));
597
598    tptr+=sizeof(const struct lspping_common_header);
599    tlen-=sizeof(const struct lspping_common_header);
600
601    while (tlen != 0) {
602        /* Does the TLV go past the end of the packet? */
603        if (tlen < sizeof(struct lspping_tlv_header))
604            goto tooshort;
605
606        /* did we capture enough for fully decoding the tlv header ? */
607        ND_TCHECK2(*tptr, sizeof(struct lspping_tlv_header));
608
609        lspping_tlv_header = (const struct lspping_tlv_header *)tptr;
610        lspping_tlv_type=EXTRACT_16BITS(lspping_tlv_header->type);
611        lspping_tlv_len=EXTRACT_16BITS(lspping_tlv_header->length);
612
613        ND_PRINT((ndo, "\n\t  %s TLV (%u), length: %u",
614               tok2str(lspping_tlv_values,
615                       "Unknown",
616                       lspping_tlv_type),
617               lspping_tlv_type,
618               lspping_tlv_len));
619
620        /* some little sanity checking */
621        if (lspping_tlv_len == 0) {
622            tptr+=sizeof(struct lspping_tlv_header);
623            tlen-=sizeof(struct lspping_tlv_header);
624            continue;    /* no value to dissect */
625        }
626
627        tlv_tptr=tptr+sizeof(struct lspping_tlv_header);
628        tlv_tlen=lspping_tlv_len; /* header not included -> no adjustment */
629
630        /* Does the TLV go past the end of the packet? */
631        if (tlen < lspping_tlv_len+sizeof(struct lspping_tlv_header))
632            goto tooshort;
633        /* did we capture enough for fully decoding the tlv ? */
634        ND_TCHECK2(*tlv_tptr, lspping_tlv_len);
635        tlv_hexdump=FALSE;
636
637        switch(lspping_tlv_type) {
638        case LSPPING_TLV_TARGET_FEC_STACK:
639            while (tlv_tlen != 0) {
640                /* Does the subTLV header go past the end of the TLV? */
641                if (tlv_tlen < sizeof(struct lspping_tlv_header)) {
642                    ND_PRINT((ndo, "\n\t      TLV is too short"));
643                    tlv_hexdump = TRUE;
644                    goto tlv_tooshort;
645                }
646                /* did we capture enough for fully decoding the subtlv header ? */
647                ND_TCHECK2(*tlv_tptr, sizeof(struct lspping_tlv_header));
648                subtlv_hexdump=FALSE;
649
650                lspping_subtlv_header = (const struct lspping_tlv_header *)tlv_tptr;
651                lspping_subtlv_type=EXTRACT_16BITS(lspping_subtlv_header->type);
652                lspping_subtlv_len=EXTRACT_16BITS(lspping_subtlv_header->length);
653                subtlv_tptr=tlv_tptr+sizeof(struct lspping_tlv_header);
654
655                /* Does the subTLV go past the end of the TLV? */
656                if (tlv_tlen < lspping_subtlv_len+sizeof(struct lspping_tlv_header)) {
657                    ND_PRINT((ndo, "\n\t      TLV is too short"));
658                    tlv_hexdump = TRUE;
659                    goto tlv_tooshort;
660                }
661
662                /* Did we capture enough for fully decoding the subTLV? */
663                ND_TCHECK2(*subtlv_tptr, lspping_subtlv_len);
664
665                ND_PRINT((ndo, "\n\t    %s subTLV (%u), length: %u",
666                       tok2str(lspping_tlvtargetfec_subtlv_values,
667                               "Unknown",
668                               lspping_subtlv_type),
669                       lspping_subtlv_type,
670                       lspping_subtlv_len));
671
672                switch(lspping_subtlv_type) {
673
674                case LSPPING_TLV_TARGETFEC_SUBTLV_LDP_IPV4:
675                    /* Is the subTLV length correct? */
676                    if (lspping_subtlv_len != 5) {
677                        ND_PRINT((ndo, "\n\t      invalid subTLV length, should be 5"));
678                        subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
679                    } else {
680                        subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv4 = \
681                            (const struct lspping_tlv_targetfec_subtlv_ldp_ipv4_t *)subtlv_tptr;
682                        ND_PRINT((ndo, "\n\t      %s/%u",
683                               ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv4->prefix),
684                               subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv4->prefix_len));
685                    }
686                    break;
687
688                case LSPPING_TLV_TARGETFEC_SUBTLV_LDP_IPV6:
689                    /* Is the subTLV length correct? */
690                    if (lspping_subtlv_len != 17) {
691                        ND_PRINT((ndo, "\n\t      invalid subTLV length, should be 17"));
692                        subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
693                    } else {
694                        subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv6 = \
695                            (const struct lspping_tlv_targetfec_subtlv_ldp_ipv6_t *)subtlv_tptr;
696                        ND_PRINT((ndo, "\n\t      %s/%u",
697                               ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv6->prefix),
698                               subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv6->prefix_len));
699                    }
700                    break;
701
702                case LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV4:
703                    /* Is the subTLV length correct? */
704                    if (lspping_subtlv_len != 5) {
705                        ND_PRINT((ndo, "\n\t      invalid subTLV length, should be 5"));
706                        subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
707                    } else {
708                        subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv4 = \
709                            (const struct lspping_tlv_targetfec_subtlv_bgp_ipv4_t *)subtlv_tptr;
710                        ND_PRINT((ndo, "\n\t      %s/%u",
711                               ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv4->prefix),
712                               subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv4->prefix_len));
713                    }
714                    break;
715
716                case LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV6:
717                    /* Is the subTLV length correct? */
718                    if (lspping_subtlv_len != 17) {
719                        ND_PRINT((ndo, "\n\t      invalid subTLV length, should be 17"));
720                        subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
721                    } else {
722                        subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv6 = \
723                            (const struct lspping_tlv_targetfec_subtlv_bgp_ipv6_t *)subtlv_tptr;
724                        ND_PRINT((ndo, "\n\t      %s/%u",
725                               ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv6->prefix),
726                               subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv6->prefix_len));
727                    }
728                    break;
729
730                case LSPPING_TLV_TARGETFEC_SUBTLV_RSVP_IPV4:
731                    /* Is the subTLV length correct? */
732                    if (lspping_subtlv_len != 20) {
733                        ND_PRINT((ndo, "\n\t      invalid subTLV length, should be 20"));
734                        subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
735                    } else {
736                        subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4 = \
737                            (const struct lspping_tlv_targetfec_subtlv_rsvp_ipv4_t *)subtlv_tptr;
738                        ND_PRINT((ndo, "\n\t      tunnel end-point %s, tunnel sender %s, lsp-id 0x%04x" \
739                               "\n\t      tunnel-id 0x%04x, extended tunnel-id %s",
740                               ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->tunnel_endpoint),
741                               ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->tunnel_sender),
742                               EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->lsp_id),
743                               EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->tunnel_id),
744                               ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->extended_tunnel_id)));
745                    }
746                    break;
747
748                case LSPPING_TLV_TARGETFEC_SUBTLV_RSVP_IPV6:
749                    /* Is the subTLV length correct? */
750                    if (lspping_subtlv_len != 56) {
751                        ND_PRINT((ndo, "\n\t      invalid subTLV length, should be 56"));
752                        subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
753                    } else {
754                        subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6 = \
755                            (const struct lspping_tlv_targetfec_subtlv_rsvp_ipv6_t *)subtlv_tptr;
756                        ND_PRINT((ndo, "\n\t      tunnel end-point %s, tunnel sender %s, lsp-id 0x%04x" \
757                               "\n\t      tunnel-id 0x%04x, extended tunnel-id %s",
758                               ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->tunnel_endpoint),
759                               ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->tunnel_sender),
760                               EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->lsp_id),
761                               EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->tunnel_id),
762                               ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->extended_tunnel_id)));
763                    }
764                    break;
765
766                case LSPPING_TLV_TARGETFEC_SUBTLV_L3VPN_IPV4:
767                    /* Is the subTLV length correct? */
768                    if (lspping_subtlv_len != 13) {
769                        ND_PRINT((ndo, "\n\t      invalid subTLV length, should be 13"));
770                        subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
771                    } else {
772                        subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv4 = \
773                            (const struct lspping_tlv_targetfec_subtlv_l3vpn_ipv4_t *)subtlv_tptr;
774                        ND_PRINT((ndo, "\n\t      RD: %s, %s/%u",
775                               bgp_vpn_rd_print(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv4->rd),
776                               ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv4->prefix),
777                               subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv4->prefix_len));
778                    }
779                    break;
780
781                case LSPPING_TLV_TARGETFEC_SUBTLV_L3VPN_IPV6:
782                    /* Is the subTLV length correct? */
783                    if (lspping_subtlv_len != 25) {
784                        ND_PRINT((ndo, "\n\t      invalid subTLV length, should be 25"));
785                        subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
786                    } else {
787                        subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv6 = \
788                            (const struct lspping_tlv_targetfec_subtlv_l3vpn_ipv6_t *)subtlv_tptr;
789                        ND_PRINT((ndo, "\n\t      RD: %s, %s/%u",
790                               bgp_vpn_rd_print(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv6->rd),
791                               ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv6->prefix),
792                               subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv6->prefix_len));
793                    }
794                    break;
795
796                case LSPPING_TLV_TARGETFEC_SUBTLV_L2VPN_ENDPT:
797                    /* Is the subTLV length correct? */
798                    if (lspping_subtlv_len != 14) {
799                        ND_PRINT((ndo, "\n\t      invalid subTLV length, should be 14"));
800                        subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
801                    } else {
802                        subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt = \
803                            (const struct lspping_tlv_targetfec_subtlv_l2vpn_endpt_t *)subtlv_tptr;
804                        ND_PRINT((ndo, "\n\t      RD: %s, Sender VE ID: %u, Receiver VE ID: %u" \
805                               "\n\t      Encapsulation Type: %s (%u)",
806                               bgp_vpn_rd_print(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->rd),
807                               EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->sender_ve_id),
808                               EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->receiver_ve_id),
809                               tok2str(mpls_pw_types_values,
810                                       "unknown",
811                                       EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->encapsulation)),
812                               EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->encapsulation)));
813                    }
814                    break;
815
816                    /* the old L2VPN VCID subTLV does not have support for the sender field */
817                case LSPPING_TLV_TARGETFEC_SUBTLV_FEC_128_PW_OLD:
818                    /* Is the subTLV length correct? */
819                    if (lspping_subtlv_len != 10) {
820                        ND_PRINT((ndo, "\n\t      invalid subTLV length, should be 10"));
821                        subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
822                    } else {
823                        subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old = \
824                            (const struct lspping_tlv_targetfec_subtlv_fec_128_pw_old *)subtlv_tptr;
825                        ND_PRINT((ndo, "\n\t      Remote PE: %s" \
826                               "\n\t      PW ID: 0x%08x, PW Type: %s (%u)",
827                               ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old->remote_pe_address),
828                               EXTRACT_32BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old->pw_id),
829                               tok2str(mpls_pw_types_values,
830                                       "unknown",
831                                       EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old->pw_type)),
832                               EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old->pw_type)));
833                    }
834                    break;
835
836                case LSPPING_TLV_TARGETFEC_SUBTLV_FEC_128_PW:
837                    /* Is the subTLV length correct? */
838                    if (lspping_subtlv_len != 14) {
839                        ND_PRINT((ndo, "\n\t      invalid subTLV length, should be 14"));
840                        subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
841                    } else {
842                        subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid = \
843                            (const struct lspping_tlv_targetfec_subtlv_fec_128_pw *)subtlv_tptr;
844                        ND_PRINT((ndo, "\n\t      Sender PE: %s, Remote PE: %s" \
845                               "\n\t      PW ID: 0x%08x, PW Type: %s (%u)",
846                               ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->sender_pe_address),
847                               ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->remote_pe_address),
848                               EXTRACT_32BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->pw_id),
849                               tok2str(mpls_pw_types_values,
850                                       "unknown",
851                                       EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->pw_type)),
852                               EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->pw_type)));
853                    }
854                    break;
855
856                default:
857                    subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
858                    break;
859                }
860                /* do we want to see an additionally subtlv hexdump ? */
861                if (ndo->ndo_vflag > 1 || subtlv_hexdump==TRUE)
862                    print_unknown_data(ndo, tlv_tptr+sizeof(struct lspping_tlv_header), \
863                                       "\n\t      ",
864                                       lspping_subtlv_len);
865
866                /* All subTLVs are aligned to four octet boundary */
867                if (lspping_subtlv_len % 4) {
868                    lspping_subtlv_len += 4 - (lspping_subtlv_len % 4);
869                    /* Does the subTLV, including padding, go past the end of the TLV? */
870                    if (tlv_tlen < lspping_subtlv_len+sizeof(struct lspping_tlv_header)) {
871                        ND_PRINT((ndo, "\n\t\t TLV is too short"));
872                        return;
873                    }
874                }
875                tlv_tptr+=lspping_subtlv_len;
876                tlv_tlen-=lspping_subtlv_len+sizeof(struct lspping_tlv_header);
877            }
878            break;
879
880        case LSPPING_TLV_DOWNSTREAM_MAPPING:
881            /* Does the header go past the end of the TLV? */
882            if (tlv_tlen < sizeof(struct lspping_tlv_downstream_map_t)) {
883                ND_PRINT((ndo, "\n\t      TLV is too short"));
884                tlv_hexdump = TRUE;
885                goto tlv_tooshort;
886            }
887            /* Did we capture enough to get the address family? */
888            ND_TCHECK2(*tlv_tptr, sizeof(struct lspping_tlv_downstream_map_t));
889
890            tlv_ptr.lspping_tlv_downstream_map= \
891                (const struct lspping_tlv_downstream_map_t *)tlv_tptr;
892
893            /* that strange thing with the downstream map TLV is that until now
894             * we do not know if its IPv4 or IPv6 or is unnumbered; after
895             * we find the address-type, we recast the tlv_tptr and move on. */
896
897            ND_PRINT((ndo, "\n\t    MTU: %u, Address-Type: %s (%u)",
898                   EXTRACT_16BITS(tlv_ptr.lspping_tlv_downstream_map->mtu),
899                   tok2str(lspping_tlv_downstream_addr_values,
900                           "unknown",
901                           tlv_ptr.lspping_tlv_downstream_map->address_type),
902                   tlv_ptr.lspping_tlv_downstream_map->address_type));
903
904            switch(tlv_ptr.lspping_tlv_downstream_map->address_type) {
905
906            case LSPPING_AFI_IPV4:
907                /* Does the data go past the end of the TLV? */
908                if (tlv_tlen < sizeof(struct lspping_tlv_downstream_map_ipv4_t)) {
909                    ND_PRINT((ndo, "\n\t      TLV is too short"));
910                    tlv_hexdump = TRUE;
911                    goto tlv_tooshort;
912                }
913                /* Did we capture enough for this part of the TLV? */
914                ND_TCHECK2(*tlv_tptr, sizeof(struct lspping_tlv_downstream_map_ipv4_t));
915
916                tlv_ptr.lspping_tlv_downstream_map_ipv4= \
917                    (const struct lspping_tlv_downstream_map_ipv4_t *)tlv_tptr;
918                ND_PRINT((ndo, "\n\t    Downstream IP: %s" \
919                       "\n\t    Downstream Interface IP: %s",
920                       ipaddr_string(ndo, tlv_ptr.lspping_tlv_downstream_map_ipv4->downstream_ip),
921                       ipaddr_string(ndo, tlv_ptr.lspping_tlv_downstream_map_ipv4->downstream_interface)));
922                tlv_tptr+=sizeof(struct lspping_tlv_downstream_map_ipv4_t);
923                tlv_tlen-=sizeof(struct lspping_tlv_downstream_map_ipv4_t);
924                break;
925            case LSPPING_AFI_IPV4_UNMB:
926                /* Does the data go past the end of the TLV? */
927                if (tlv_tlen < sizeof(struct lspping_tlv_downstream_map_ipv4_unmb_t)) {
928                    ND_PRINT((ndo, "\n\t      TLV is too short"));
929                    tlv_hexdump = TRUE;
930                    goto tlv_tooshort;
931                }
932                /* Did we capture enough for this part of the TLV? */
933                ND_TCHECK2(*tlv_tptr, sizeof(struct lspping_tlv_downstream_map_ipv4_unmb_t));
934
935                tlv_ptr.lspping_tlv_downstream_map_ipv4_unmb= \
936                    (const struct lspping_tlv_downstream_map_ipv4_unmb_t *)tlv_tptr;
937                ND_PRINT((ndo, "\n\t    Downstream IP: %s" \
938                       "\n\t    Downstream Interface Index: 0x%08x",
939                       ipaddr_string(ndo, tlv_ptr.lspping_tlv_downstream_map_ipv4_unmb->downstream_ip),
940                       EXTRACT_32BITS(tlv_ptr.lspping_tlv_downstream_map_ipv4_unmb->downstream_interface)));
941                tlv_tptr+=sizeof(struct lspping_tlv_downstream_map_ipv4_unmb_t);
942                tlv_tlen-=sizeof(struct lspping_tlv_downstream_map_ipv4_unmb_t);
943                break;
944            case LSPPING_AFI_IPV6:
945                /* Does the data go past the end of the TLV? */
946                if (tlv_tlen < sizeof(struct lspping_tlv_downstream_map_ipv6_t)) {
947                    ND_PRINT((ndo, "\n\t      TLV is too short"));
948                    tlv_hexdump = TRUE;
949                    goto tlv_tooshort;
950                }
951                /* Did we capture enough for this part of the TLV? */
952                ND_TCHECK2(*tlv_tptr, sizeof(struct lspping_tlv_downstream_map_ipv6_t));
953
954                tlv_ptr.lspping_tlv_downstream_map_ipv6= \
955                    (const struct lspping_tlv_downstream_map_ipv6_t *)tlv_tptr;
956                ND_PRINT((ndo, "\n\t    Downstream IP: %s" \
957                       "\n\t    Downstream Interface IP: %s",
958                       ip6addr_string(ndo, tlv_ptr.lspping_tlv_downstream_map_ipv6->downstream_ip),
959                       ip6addr_string(ndo, tlv_ptr.lspping_tlv_downstream_map_ipv6->downstream_interface)));
960                tlv_tptr+=sizeof(struct lspping_tlv_downstream_map_ipv6_t);
961                tlv_tlen-=sizeof(struct lspping_tlv_downstream_map_ipv6_t);
962                break;
963             case LSPPING_AFI_IPV6_UNMB:
964                /* Does the data go past the end of the TLV? */
965                if (tlv_tlen < sizeof(struct lspping_tlv_downstream_map_ipv6_unmb_t)) {
966                    ND_PRINT((ndo, "\n\t      TLV is too short"));
967                    tlv_hexdump = TRUE;
968                    goto tlv_tooshort;
969                }
970                /* Did we capture enough for this part of the TLV? */
971                ND_TCHECK2(*tlv_tptr, sizeof(struct lspping_tlv_downstream_map_ipv6_unmb_t));
972
973                tlv_ptr.lspping_tlv_downstream_map_ipv6_unmb= \
974                   (const struct lspping_tlv_downstream_map_ipv6_unmb_t *)tlv_tptr;
975                ND_PRINT((ndo, "\n\t    Downstream IP: %s" \
976                       "\n\t    Downstream Interface Index: 0x%08x",
977                       ip6addr_string(ndo, tlv_ptr.lspping_tlv_downstream_map_ipv6_unmb->downstream_ip),
978                       EXTRACT_32BITS(tlv_ptr.lspping_tlv_downstream_map_ipv6_unmb->downstream_interface)));
979                tlv_tptr+=sizeof(struct lspping_tlv_downstream_map_ipv6_unmb_t);
980                tlv_tlen-=sizeof(struct lspping_tlv_downstream_map_ipv6_unmb_t);
981                break;
982
983            default:
984                /* should not happen ! - no error message - tok2str() has barked already */
985                break;
986            }
987
988            /* Does the data go past the end of the TLV? */
989            if (tlv_tlen < sizeof(struct lspping_tlv_downstream_map_info_t)) {
990                ND_PRINT((ndo, "\n\t      TLV is too short"));
991                tlv_hexdump = TRUE;
992                goto tlv_tooshort;
993            }
994            /* Did we capture enough for this part of the TLV? */
995            ND_TCHECK2(*tlv_tptr, sizeof(struct lspping_tlv_downstream_map_info_t));
996
997            tlv_ptr.lspping_tlv_downstream_map_info= \
998                (const struct lspping_tlv_downstream_map_info_t *)tlv_tptr;
999
1000            /* FIXME add hash-key type, depth limit, multipath processing */
1001
1002            tlv_tptr+=sizeof(struct lspping_tlv_downstream_map_info_t);
1003            tlv_tlen-=sizeof(struct lspping_tlv_downstream_map_info_t);
1004
1005            /* FIXME print downstream labels */
1006
1007            tlv_hexdump=TRUE; /* dump the TLV until code complete */
1008
1009            break;
1010
1011        case LSPPING_TLV_BFD_DISCRIMINATOR:
1012            if (tlv_tlen < LSPPING_TLV_BFD_DISCRIMINATOR_LEN) {
1013                ND_PRINT((ndo, "\n\t      TLV is too short"));
1014                tlv_hexdump = TRUE;
1015                goto tlv_tooshort;
1016            } else {
1017                ND_TCHECK2(*tptr, LSPPING_TLV_BFD_DISCRIMINATOR_LEN);
1018                ND_PRINT((ndo, "\n\t    BFD Discriminator 0x%08x", EXTRACT_32BITS(tptr)));
1019            }
1020            break;
1021
1022        case  LSPPING_TLV_VENDOR_ENTERPRISE:
1023        {
1024            uint32_t vendor_id;
1025
1026            if (tlv_tlen < LSPPING_TLV_VENDOR_ENTERPRISE_LEN) {
1027                ND_PRINT((ndo, "\n\t      TLV is too short"));
1028                tlv_hexdump = TRUE;
1029                goto tlv_tooshort;
1030            } else {
1031                ND_TCHECK2(*tptr, LSPPING_TLV_VENDOR_ENTERPRISE_LEN);
1032                vendor_id = EXTRACT_32BITS(tlv_tptr);
1033                ND_PRINT((ndo, "\n\t    Vendor: %s (0x%04x)",
1034                       tok2str(smi_values, "Unknown", vendor_id),
1035                       vendor_id));
1036            }
1037        }
1038            break;
1039
1040            /*
1041             *  FIXME those are the defined TLVs that lack a decoder
1042             *  you are welcome to contribute code ;-)
1043             */
1044        case LSPPING_TLV_PAD:
1045        case LSPPING_TLV_ERROR_CODE:
1046        case LSPPING_TLV_VENDOR_PRIVATE:
1047
1048        default:
1049            if (ndo->ndo_vflag <= 1)
1050                print_unknown_data(ndo, tlv_tptr, "\n\t    ", tlv_tlen);
1051            break;
1052        }
1053        /* do we want to see an additionally tlv hexdump ? */
1054    tlv_tooshort:
1055        if (ndo->ndo_vflag > 1 || tlv_hexdump==TRUE)
1056            print_unknown_data(ndo, tptr+sizeof(struct lspping_tlv_header), "\n\t    ",
1057                               lspping_tlv_len);
1058
1059
1060        /* All TLVs are aligned to four octet boundary */
1061        if (lspping_tlv_len % 4) {
1062            lspping_tlv_len += (4 - lspping_tlv_len % 4);
1063            /* Does the TLV, including padding, go past the end of the packet? */
1064            if (tlen < lspping_tlv_len+sizeof(struct lspping_tlv_header))
1065                goto tooshort;
1066        }
1067
1068        tptr+=lspping_tlv_len+sizeof(struct lspping_tlv_header);
1069        tlen-=lspping_tlv_len+sizeof(struct lspping_tlv_header);
1070    }
1071    return;
1072tooshort:
1073    ND_PRINT((ndo, "\n\t\t packet is too short"));
1074    return;
1075trunc:
1076    ND_PRINT((ndo, "\n\t\t packet exceeded snapshot"));
1077    return;
1078}
1079/*
1080 * Local Variables:
1081 * c-style: whitesmith
1082 * c-basic-offset: 8
1083 * End:
1084 */
1085