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