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