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