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