xref: /netbsd-src/external/bsd/tcpdump/dist/print-ldp.c (revision a536ee5124e62c9a0051a252f7833dc8f50f44c9)
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  *  and Steinar Haug (sthaug@nethelp.no)
15  */
16 
17 #include <sys/cdefs.h>
18 #ifndef lint
19 #if 0
20 static const char rcsid[] _U_ =
21     "@(#) Header: /tcpdump/master/tcpdump/print-ldp.c,v 1.20 2006-06-23 02:03:09 hannes Exp";
22 #else
23 __RCSID("$NetBSD: print-ldp.c,v 1.3 2012/01/16 17:34:18 christos Exp $");
24 #endif
25 #endif
26 
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30 
31 #include <tcpdump-stdinc.h>
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 
37 #include "interface.h"
38 #include "decode_prefix.h"
39 #include "extract.h"
40 #include "addrtoname.h"
41 
42 #include "l2vpn.h"
43 #include "af.h"
44 
45 /*
46  * ldp common header
47  *
48  *  0                   1                   2                   3
49  *  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
50  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51  * |  Version                      |         PDU Length            |
52  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53  * |                         LDP Identifier                        |
54  * +                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55  * |                               |
56  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57  *
58  */
59 
60 struct ldp_common_header {
61     u_int8_t version[2];
62     u_int8_t pdu_length[2];
63     u_int8_t lsr_id[4];
64     u_int8_t label_space[2];
65 };
66 
67 #define LDP_VERSION 1
68 
69 /*
70  * ldp message header
71  *
72  *  0                   1                   2                   3
73  *  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
74  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
75  * |U|   Message Type              |      Message Length           |
76  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
77  * |                     Message ID                                |
78  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
79  * |                                                               |
80  * +                                                               +
81  * |                     Mandatory Parameters                      |
82  * +                                                               +
83  * |                                                               |
84  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
85  * |                                                               |
86  * +                                                               +
87  * |                     Optional Parameters                       |
88  * +                                                               +
89  * |                                                               |
90  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
91  */
92 
93 struct ldp_msg_header {
94     u_int8_t type[2];
95     u_int8_t length[2];
96     u_int8_t id[4];
97 };
98 
99 #define	LDP_MASK_MSG_TYPE(x)  ((x)&0x7fff)
100 #define	LDP_MASK_U_BIT(x)     ((x)&0x8000)
101 
102 #define	LDP_MSG_NOTIF                0x0001
103 #define	LDP_MSG_HELLO                0x0100
104 #define	LDP_MSG_INIT                 0x0200
105 #define	LDP_MSG_KEEPALIVE            0x0201
106 #define	LDP_MSG_ADDRESS              0x0300
107 #define	LDP_MSG_ADDRESS_WITHDRAW     0x0301
108 #define	LDP_MSG_LABEL_MAPPING        0x0400
109 #define	LDP_MSG_LABEL_REQUEST        0x0401
110 #define	LDP_MSG_LABEL_WITHDRAW       0x0402
111 #define	LDP_MSG_LABEL_RELEASE        0x0403
112 #define	LDP_MSG_LABEL_ABORT_REQUEST  0x0404
113 
114 #define	LDP_VENDOR_PRIVATE_MIN       0x3e00
115 #define	LDP_VENDOR_PRIVATE_MAX       0x3eff
116 #define	LDP_EXPERIMENTAL_MIN         0x3f00
117 #define	LDP_EXPERIMENTAL_MAX         0x3fff
118 
119 static const struct tok ldp_msg_values[] = {
120     { LDP_MSG_NOTIF,	             "Notification" },
121     { LDP_MSG_HELLO,	             "Hello" },
122     { LDP_MSG_INIT,	             "Initialization" },
123     { LDP_MSG_KEEPALIVE,             "Keepalive" },
124     { LDP_MSG_ADDRESS,	             "Address" },
125     { LDP_MSG_ADDRESS_WITHDRAW,	     "Address Withdraw" },
126     { LDP_MSG_LABEL_MAPPING,	     "Label Mapping" },
127     { LDP_MSG_LABEL_REQUEST,	     "Label Request" },
128     { LDP_MSG_LABEL_WITHDRAW,	     "Label Withdraw" },
129     { LDP_MSG_LABEL_RELEASE,	     "Label Release" },
130     { LDP_MSG_LABEL_ABORT_REQUEST,   "Label Abort Request" },
131     { 0, NULL}
132 };
133 
134 #define	LDP_MASK_TLV_TYPE(x)  ((x)&0x3fff)
135 #define	LDP_MASK_F_BIT(x) ((x)&0x4000)
136 
137 #define	LDP_TLV_FEC                  0x0100
138 #define	LDP_TLV_ADDRESS_LIST         0x0101
139 #define LDP_TLV_ADDRESS_LIST_AFNUM_LEN 2
140 #define	LDP_TLV_HOP_COUNT            0x0103
141 #define	LDP_TLV_PATH_VECTOR          0x0104
142 #define	LDP_TLV_GENERIC_LABEL        0x0200
143 #define	LDP_TLV_ATM_LABEL            0x0201
144 #define	LDP_TLV_FR_LABEL             0x0202
145 #define	LDP_TLV_STATUS               0x0300
146 #define	LDP_TLV_EXTD_STATUS          0x0301
147 #define	LDP_TLV_RETURNED_PDU         0x0302
148 #define	LDP_TLV_RETURNED_MSG         0x0303
149 #define	LDP_TLV_COMMON_HELLO         0x0400
150 #define	LDP_TLV_IPV4_TRANSPORT_ADDR  0x0401
151 #define	LDP_TLV_CONFIG_SEQ_NUMBER    0x0402
152 #define	LDP_TLV_IPV6_TRANSPORT_ADDR  0x0403
153 #define	LDP_TLV_COMMON_SESSION       0x0500
154 #define	LDP_TLV_ATM_SESSION_PARM     0x0501
155 #define	LDP_TLV_FR_SESSION_PARM      0x0502
156 #define LDP_TLV_FT_SESSION	     0x0503
157 #define	LDP_TLV_LABEL_REQUEST_MSG_ID 0x0600
158 #define LDP_TLV_MTU                  0x0601 /* rfc 3988 */
159 
160 static const struct tok ldp_tlv_values[] = {
161     { LDP_TLV_FEC,	             "FEC" },
162     { LDP_TLV_ADDRESS_LIST,          "Address List" },
163     { LDP_TLV_HOP_COUNT,             "Hop Count" },
164     { LDP_TLV_PATH_VECTOR,           "Path Vector" },
165     { LDP_TLV_GENERIC_LABEL,         "Generic Label" },
166     { LDP_TLV_ATM_LABEL,             "ATM Label" },
167     { LDP_TLV_FR_LABEL,              "Frame-Relay Label" },
168     { LDP_TLV_STATUS,                "Status" },
169     { LDP_TLV_EXTD_STATUS,           "Extended Status" },
170     { LDP_TLV_RETURNED_PDU,          "Returned PDU" },
171     { LDP_TLV_RETURNED_MSG,          "Returned Message" },
172     { LDP_TLV_COMMON_HELLO,          "Common Hello Parameters" },
173     { LDP_TLV_IPV4_TRANSPORT_ADDR,   "IPv4 Transport Address" },
174     { LDP_TLV_CONFIG_SEQ_NUMBER,     "Configuration Sequence Number" },
175     { LDP_TLV_IPV6_TRANSPORT_ADDR,   "IPv6 Transport Address" },
176     { LDP_TLV_COMMON_SESSION,        "Common Session Parameters" },
177     { LDP_TLV_ATM_SESSION_PARM,      "ATM Session Parameters" },
178     { LDP_TLV_FR_SESSION_PARM,       "Frame-Relay Session Parameters" },
179     { LDP_TLV_FT_SESSION,            "Fault-Tolerant Session Parameters" },
180     { LDP_TLV_LABEL_REQUEST_MSG_ID,  "Label Request Message ID" },
181     { LDP_TLV_MTU,                   "MTU" },
182     { 0, NULL}
183 };
184 
185 #define LDP_FEC_WILDCARD	0x01
186 #define LDP_FEC_PREFIX		0x02
187 #define LDP_FEC_HOSTADDRESS	0x03
188 /* From draft-martini-l2circuit-trans-mpls-13.txt */
189 #define LDP_FEC_MARTINI_VC	0x80
190 
191 static const struct tok ldp_fec_values[] = {
192     { LDP_FEC_WILDCARD,		"Wildcard" },
193     { LDP_FEC_PREFIX,		"Prefix" },
194     { LDP_FEC_HOSTADDRESS,	"Host address" },
195     { LDP_FEC_MARTINI_VC,	"Martini VC" },
196     { 0, NULL}
197 };
198 
199 #define LDP_FEC_MARTINI_IFPARM_MTU  0x01
200 #define LDP_FEC_MARTINI_IFPARM_DESC 0x03
201 #define LDP_FEC_MARTINI_IFPARM_VCCV 0x0c
202 
203 static const struct tok ldp_fec_martini_ifparm_values[] = {
204     { LDP_FEC_MARTINI_IFPARM_MTU, "MTU" },
205     { LDP_FEC_MARTINI_IFPARM_DESC, "Description" },
206     { LDP_FEC_MARTINI_IFPARM_VCCV, "VCCV" },
207     { 0, NULL}
208 };
209 
210 /* draft-ietf-pwe3-vccv-04.txt */
211 static const struct tok ldp_fec_martini_ifparm_vccv_cc_values[] = {
212     { 0x01, "PWE3 control word" },
213     { 0x02, "MPLS Router Alert Label" },
214     { 0x04, "MPLS inner label TTL = 1" },
215     { 0, NULL}
216 };
217 
218 /* draft-ietf-pwe3-vccv-04.txt */
219 static const struct tok ldp_fec_martini_ifparm_vccv_cv_values[] = {
220     { 0x01, "ICMP Ping" },
221     { 0x02, "LSP Ping" },
222     { 0x04, "BFD" },
223     { 0, NULL}
224 };
225 
226 int ldp_msg_print(register const u_char *);
227 int ldp_tlv_print(register const u_char *);
228 
229 /*
230  * ldp tlv header
231  *
232  *  0                   1                   2                   3
233  *  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
234  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
235  * |U|F|        Type               |            Length             |
236  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
237  * |                                                               |
238  * |                             Value                             |
239  * ~                                                               ~
240  * |                                                               |
241  * |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
242  * |                               |
243  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
244  */
245 
246 int
247 ldp_tlv_print(register const u_char *tptr) {
248 
249     struct ldp_tlv_header {
250         u_int8_t type[2];
251         u_int8_t length[2];
252     };
253 
254     const struct ldp_tlv_header *ldp_tlv_header;
255     u_short tlv_type,tlv_len,tlv_tlen,af,ft_flags;
256     u_char fec_type;
257     u_int ui,vc_info_len, vc_info_tlv_type, vc_info_tlv_len,idx;
258     char buf[100];
259     int i;
260 
261     ldp_tlv_header = (const struct ldp_tlv_header *)tptr;
262     tlv_len=EXTRACT_16BITS(ldp_tlv_header->length);
263     tlv_tlen=tlv_len;
264     tlv_type=LDP_MASK_TLV_TYPE(EXTRACT_16BITS(ldp_tlv_header->type));
265 
266     /* FIXME vendor private / experimental check */
267     printf("\n\t    %s TLV (0x%04x), length: %u, Flags: [%s and %s forward if unknown]",
268            tok2str(ldp_tlv_values,
269                    "Unknown",
270                    tlv_type),
271            tlv_type,
272            tlv_len,
273            LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "continue processing" : "ignore",
274            LDP_MASK_F_BIT(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "do" : "don't");
275 
276     tptr+=sizeof(struct ldp_tlv_header);
277 
278     switch(tlv_type) {
279 
280     case LDP_TLV_COMMON_HELLO:
281         printf("\n\t      Hold Time: %us, Flags: [%s Hello%s]",
282                EXTRACT_16BITS(tptr),
283                (EXTRACT_16BITS(tptr+2)&0x8000) ? "Targeted" : "Link",
284                (EXTRACT_16BITS(tptr+2)&0x4000) ? ", Request for targeted Hellos" : "");
285         break;
286 
287     case LDP_TLV_IPV4_TRANSPORT_ADDR:
288         printf("\n\t      IPv4 Transport Address: %s", ipaddr_string(tptr));
289         break;
290 #ifdef INET6
291     case LDP_TLV_IPV6_TRANSPORT_ADDR:
292         printf("\n\t      IPv6 Transport Address: %s", ip6addr_string(tptr));
293         break;
294 #endif
295     case LDP_TLV_CONFIG_SEQ_NUMBER:
296         printf("\n\t      Sequence Number: %u", EXTRACT_32BITS(tptr));
297         break;
298 
299     case LDP_TLV_ADDRESS_LIST:
300 	af = EXTRACT_16BITS(tptr);
301 	tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
302         tlv_tlen -= LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
303 	printf("\n\t      Address Family: %s, addresses",
304                tok2str(af_values, "Unknown (%u)", af));
305         switch (af) {
306         case AFNUM_INET:
307 	    while(tlv_tlen >= sizeof(struct in_addr)) {
308 		printf(" %s",ipaddr_string(tptr));
309 		tlv_tlen-=sizeof(struct in_addr);
310 		tptr+=sizeof(struct in_addr);
311 	    }
312             break;
313 #ifdef INET6
314         case AFNUM_INET6:
315 	    while(tlv_tlen >= sizeof(struct in6_addr)) {
316 		printf(" %s",ip6addr_string(tptr));
317 		tlv_tlen-=sizeof(struct in6_addr);
318 		tptr+=sizeof(struct in6_addr);
319 	    }
320             break;
321 #endif
322         default:
323             /* unknown AF */
324             break;
325         }
326 	break;
327 
328     case LDP_TLV_COMMON_SESSION:
329 	printf("\n\t      Version: %u, Keepalive: %us, Flags: [Downstream %s, Loop Detection %s]",
330 	       EXTRACT_16BITS(tptr), EXTRACT_16BITS(tptr+2),
331 	       (EXTRACT_16BITS(tptr+6)&0x8000) ? "On Demand" : "Unsolicited",
332 	       (EXTRACT_16BITS(tptr+6)&0x4000) ? "Enabled" : "Disabled"
333 	       );
334 	break;
335 
336     case LDP_TLV_FEC:
337         fec_type = *tptr;
338 	printf("\n\t      %s FEC (0x%02x)",
339 	       tok2str(ldp_fec_values, "Unknown", fec_type),
340 	       fec_type);
341 
342 	tptr+=1;
343 	switch(fec_type) {
344 
345 	case LDP_FEC_WILDCARD:
346 	    break;
347 	case LDP_FEC_PREFIX:
348 	    af = EXTRACT_16BITS(tptr);
349 	    tptr+=2;
350 	    if (af == AFNUM_INET) {
351 		i=decode_prefix4(tptr,buf,sizeof(buf));
352 		printf(": IPv4 prefix %s",buf);
353 	    }
354 #ifdef INET6
355 	    else if (af == AFNUM_INET6) {
356 		i=decode_prefix6(tptr,buf,sizeof(buf));
357 		printf(": IPv6 prefix %s",buf);
358 	    }
359 #endif
360 	    break;
361 	case LDP_FEC_HOSTADDRESS:
362 	    break;
363 	case LDP_FEC_MARTINI_VC:
364             if (!TTEST2(*tptr, 11))
365                 goto trunc;
366             vc_info_len = *(tptr+2);
367 
368 	    printf(": %s, %scontrol word, group-ID %u, VC-ID %u, VC-info-length: %u",
369 		   tok2str(l2vpn_encaps_values, "Unknown", EXTRACT_16BITS(tptr)&0x7fff),
370 		   EXTRACT_16BITS(tptr)&0x8000 ? "" : "no ",
371                    EXTRACT_32BITS(tptr+3),
372 		   EXTRACT_32BITS(tptr+7),
373                    vc_info_len);
374 
375             if (vc_info_len == 0) /* infinite loop protection */
376                 break;
377 
378             tptr+=11;
379             if (!TTEST2(*tptr, vc_info_len))
380                 goto trunc;
381 
382             while (vc_info_len > 2) {
383                 vc_info_tlv_type = *tptr;
384                 vc_info_tlv_len = *(tptr+1);
385                 if (vc_info_tlv_len < 2)
386                     break;
387                 if (vc_info_len < vc_info_tlv_len)
388                     break;
389 
390                 printf("\n\t\tInterface Parameter: %s (0x%02x), len %u",
391                        tok2str(ldp_fec_martini_ifparm_values,"Unknown",vc_info_tlv_type),
392                        vc_info_tlv_type,
393                        vc_info_tlv_len);
394 
395                 switch(vc_info_tlv_type) {
396                 case LDP_FEC_MARTINI_IFPARM_MTU:
397                     printf(": %u",EXTRACT_16BITS(tptr+2));
398                     break;
399 
400                 case LDP_FEC_MARTINI_IFPARM_DESC:
401                     printf(": ");
402                     for (idx = 2; idx < vc_info_tlv_len; idx++)
403                         safeputchar(*(tptr+idx));
404                     break;
405 
406                 case LDP_FEC_MARTINI_IFPARM_VCCV:
407                     printf("\n\t\t  Control Channels (0x%02x) = [%s]",
408                            *(tptr+2),
409                            bittok2str(ldp_fec_martini_ifparm_vccv_cc_values,"none",*(tptr+2)));
410                     printf("\n\t\t  CV Types (0x%02x) = [%s]",
411                            *(tptr+3),
412                            bittok2str(ldp_fec_martini_ifparm_vccv_cv_values,"none",*(tptr+3)));
413                     break;
414 
415                 default:
416                     print_unknown_data(tptr+2,"\n\t\t  ",vc_info_tlv_len-2);
417                     break;
418                 }
419 
420                 vc_info_len -= vc_info_tlv_len;
421                 tptr += vc_info_tlv_len;
422             }
423 	    break;
424 	}
425 
426 	break;
427 
428     case LDP_TLV_GENERIC_LABEL:
429 	printf("\n\t      Label: %u", EXTRACT_32BITS(tptr) & 0xfffff);
430 	break;
431 
432     case LDP_TLV_STATUS:
433 	ui = EXTRACT_32BITS(tptr);
434 	tptr+=4;
435 	printf("\n\t      Status: 0x%02x, Flags: [%s and %s forward]",
436 	       ui&0x3fffffff,
437 	       ui&0x80000000 ? "Fatal error" : "Advisory Notification",
438 	       ui&0x40000000 ? "do" : "don't");
439 	ui = EXTRACT_32BITS(tptr);
440 	tptr+=4;
441 	if (ui)
442 	    printf(", causing Message ID: 0x%08x", ui);
443 	break;
444 
445     case LDP_TLV_FT_SESSION:
446 	ft_flags = EXTRACT_16BITS(tptr);
447 	printf("\n\t      Flags: [%sReconnect, %sSave State, %sAll-Label Protection, %s Checkpoint, %sRe-Learn State]",
448 	       ft_flags&0x8000 ? "" : "No ",
449 	       ft_flags&0x8 ? "" : "Don't ",
450 	       ft_flags&0x4 ? "" : "No ",
451 	       ft_flags&0x2 ? "Sequence Numbered Label" : "All Labels",
452 	       ft_flags&0x1 ? "" : "Don't ");
453 	tptr+=4;
454 	ui = EXTRACT_32BITS(tptr);
455 	if (ui)
456 	    printf(", Reconnect Timeout: %ums", ui);
457 	tptr+=4;
458 	ui = EXTRACT_32BITS(tptr);
459 	if (ui)
460 	    printf(", Recovery Time: %ums", ui);
461 	break;
462 
463     case LDP_TLV_MTU:
464 	printf("\n\t      MTU: %u", EXTRACT_16BITS(tptr));
465 	break;
466 
467 
468     /*
469      *  FIXME those are the defined TLVs that lack a decoder
470      *  you are welcome to contribute code ;-)
471      */
472 
473     case LDP_TLV_HOP_COUNT:
474     case LDP_TLV_PATH_VECTOR:
475     case LDP_TLV_ATM_LABEL:
476     case LDP_TLV_FR_LABEL:
477     case LDP_TLV_EXTD_STATUS:
478     case LDP_TLV_RETURNED_PDU:
479     case LDP_TLV_RETURNED_MSG:
480     case LDP_TLV_ATM_SESSION_PARM:
481     case LDP_TLV_FR_SESSION_PARM:
482     case LDP_TLV_LABEL_REQUEST_MSG_ID:
483 
484     default:
485         if (vflag <= 1)
486             print_unknown_data(tptr,"\n\t      ",tlv_tlen);
487         break;
488     }
489     return(tlv_len+4); /* Type & Length fields not included */
490 
491 trunc:
492     printf("\n\t\t packet exceeded snapshot");
493     return 0;
494 }
495 
496 void
497 ldp_print(register const u_char *pptr, register u_int len) {
498 
499     int processed;
500     while (len > (sizeof(struct ldp_common_header) + sizeof(struct ldp_msg_header))) {
501         processed = ldp_msg_print(pptr);
502         if (processed == 0)
503             return;
504         len -= processed;
505         pptr += processed;
506     }
507 }
508 
509 
510 int
511 ldp_msg_print(register const u_char *pptr) {
512 
513     const struct ldp_common_header *ldp_com_header;
514     const struct ldp_msg_header *ldp_msg_header;
515     const u_char *tptr,*msg_tptr;
516     u_short tlen;
517     u_short pdu_len,msg_len,msg_type,msg_tlen;
518     int hexdump,processed;
519 
520     tptr=pptr;
521     ldp_com_header = (const struct ldp_common_header *)pptr;
522     TCHECK(*ldp_com_header);
523 
524     /*
525      * Sanity checking of the header.
526      */
527     if (EXTRACT_16BITS(&ldp_com_header->version) != LDP_VERSION) {
528 	printf("%sLDP version %u packet not supported",
529                (vflag < 1) ? "" : "\n\t",
530                EXTRACT_16BITS(&ldp_com_header->version));
531 	return 0;
532     }
533 
534     /* print the LSR-ID, label-space & length */
535     pdu_len = EXTRACT_16BITS(&ldp_com_header->pdu_length);
536     printf("%sLDP, Label-Space-ID: %s:%u, pdu-length: %u",
537            (vflag < 1) ? "" : "\n\t",
538            ipaddr_string(&ldp_com_header->lsr_id),
539            EXTRACT_16BITS(&ldp_com_header->label_space),
540            pdu_len);
541 
542     /* bail out if non-verbose */
543     if (vflag < 1)
544         return 0;
545 
546     /* ok they seem to want to know everything - lets fully decode it */
547     tlen=pdu_len;
548 
549     tptr += sizeof(const struct ldp_common_header);
550     tlen -= sizeof(const struct ldp_common_header)-4;	/* Type & Length fields not included */
551 
552     while(tlen>0) {
553         /* did we capture enough for fully decoding the msg header ? */
554         if (!TTEST2(*tptr, sizeof(struct ldp_msg_header)))
555             goto trunc;
556 
557         ldp_msg_header = (const struct ldp_msg_header *)tptr;
558         msg_len=EXTRACT_16BITS(ldp_msg_header->length);
559         msg_type=LDP_MASK_MSG_TYPE(EXTRACT_16BITS(ldp_msg_header->type));
560 
561         /* FIXME vendor private / experimental check */
562         printf("\n\t  %s Message (0x%04x), length: %u, Message ID: 0x%08x, Flags: [%s if unknown]",
563                tok2str(ldp_msg_values,
564                        "Unknown",
565                        msg_type),
566                msg_type,
567                msg_len,
568                EXTRACT_32BITS(&ldp_msg_header->id),
569                LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_msg_header->type)) ? "continue processing" : "ignore");
570 
571         if (msg_len == 0) /* infinite loop protection */
572             return 0;
573 
574         msg_tptr=tptr+sizeof(struct ldp_msg_header);
575         msg_tlen=msg_len-sizeof(struct ldp_msg_header)+4; /* Type & Length fields not included */
576 
577         /* did we capture enough for fully decoding the message ? */
578         if (!TTEST2(*tptr, msg_len))
579             goto trunc;
580         hexdump=FALSE;
581 
582         switch(msg_type) {
583 
584         case LDP_MSG_NOTIF:
585         case LDP_MSG_HELLO:
586         case LDP_MSG_INIT:
587         case LDP_MSG_KEEPALIVE:
588         case LDP_MSG_ADDRESS:
589         case LDP_MSG_LABEL_MAPPING:
590         case LDP_MSG_ADDRESS_WITHDRAW:
591         case LDP_MSG_LABEL_WITHDRAW:
592             while(msg_tlen >= 4) {
593                 processed = ldp_tlv_print(msg_tptr);
594                 if (processed == 0)
595                     break;
596                 msg_tlen-=processed;
597                 msg_tptr+=processed;
598             }
599             break;
600 
601         /*
602          *  FIXME those are the defined messages that lack a decoder
603          *  you are welcome to contribute code ;-)
604          */
605 
606         case LDP_MSG_LABEL_REQUEST:
607         case LDP_MSG_LABEL_RELEASE:
608         case LDP_MSG_LABEL_ABORT_REQUEST:
609 
610         default:
611             if (vflag <= 1)
612                 print_unknown_data(msg_tptr,"\n\t  ",msg_tlen);
613             break;
614         }
615         /* do we want to see an additionally hexdump ? */
616         if (vflag > 1 || hexdump==TRUE)
617             print_unknown_data(tptr+sizeof(struct ldp_msg_header),"\n\t  ",
618                                msg_len);
619 
620         tptr += msg_len+4;
621         tlen -= msg_len+4;
622     }
623     return pdu_len+4;
624 trunc:
625     printf("\n\t\t packet exceeded snapshot");
626     return 0;
627 }
628 
629