mirror of
https://github.com/the-tcpdump-group/tcpdump.git
synced 2024-12-01 05:53:38 +08:00
26687fd6b9
Make sure we don't run past the end of a BGP attribute or LDP TLV when dissecting the attribute/TLV. Make some of the code do a bit more of a "step the pointer through the data"-style dissection; that was done while debugging the changes in question. It also fixes up some code to not check for more data than should actually be there. Update references to RFC 4906 from the draft, and note that RFC 4447 replaces it.
677 lines
22 KiB
C
677 lines
22 KiB
C
/*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that: (1) source code
|
|
* distributions retain the above copyright notice and this paragraph
|
|
* in its entirety, and (2) distributions including binary code include
|
|
* the above copyright notice and this paragraph in its entirety in
|
|
* the documentation or other materials provided with the distribution.
|
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND
|
|
* WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
|
|
* LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
* FOR A PARTICULAR PURPOSE.
|
|
*
|
|
* Original code by Hannes Gredler (hannes@juniper.net)
|
|
* and Steinar Haug (sthaug@nethelp.no)
|
|
*/
|
|
|
|
#ifndef lint
|
|
static const char rcsid[] _U_ =
|
|
"@(#) $Header: /tcpdump/master/tcpdump/print-ldp.c,v 1.20 2006-06-23 02:03:09 hannes Exp $";
|
|
#endif
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <tcpdump-stdinc.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "interface.h"
|
|
#include "decode_prefix.h"
|
|
#include "extract.h"
|
|
#include "addrtoname.h"
|
|
|
|
#include "l2vpn.h"
|
|
#include "af.h"
|
|
|
|
/*
|
|
* ldp common header
|
|
*
|
|
* 0 1 2 3
|
|
* 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
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
* | Version | PDU Length |
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
* | LDP Identifier |
|
|
* + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
* | |
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
*
|
|
*/
|
|
|
|
struct ldp_common_header {
|
|
u_int8_t version[2];
|
|
u_int8_t pdu_length[2];
|
|
u_int8_t lsr_id[4];
|
|
u_int8_t label_space[2];
|
|
};
|
|
|
|
#define LDP_VERSION 1
|
|
|
|
/*
|
|
* ldp message header
|
|
*
|
|
* 0 1 2 3
|
|
* 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
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
* |U| Message Type | Message Length |
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
* | Message ID |
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
* | |
|
|
* + +
|
|
* | Mandatory Parameters |
|
|
* + +
|
|
* | |
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
* | |
|
|
* + +
|
|
* | Optional Parameters |
|
|
* + +
|
|
* | |
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
*/
|
|
|
|
struct ldp_msg_header {
|
|
u_int8_t type[2];
|
|
u_int8_t length[2];
|
|
u_int8_t id[4];
|
|
};
|
|
|
|
#define LDP_MASK_MSG_TYPE(x) ((x)&0x7fff)
|
|
#define LDP_MASK_U_BIT(x) ((x)&0x8000)
|
|
|
|
#define LDP_MSG_NOTIF 0x0001
|
|
#define LDP_MSG_HELLO 0x0100
|
|
#define LDP_MSG_INIT 0x0200
|
|
#define LDP_MSG_KEEPALIVE 0x0201
|
|
#define LDP_MSG_ADDRESS 0x0300
|
|
#define LDP_MSG_ADDRESS_WITHDRAW 0x0301
|
|
#define LDP_MSG_LABEL_MAPPING 0x0400
|
|
#define LDP_MSG_LABEL_REQUEST 0x0401
|
|
#define LDP_MSG_LABEL_WITHDRAW 0x0402
|
|
#define LDP_MSG_LABEL_RELEASE 0x0403
|
|
#define LDP_MSG_LABEL_ABORT_REQUEST 0x0404
|
|
|
|
#define LDP_VENDOR_PRIVATE_MIN 0x3e00
|
|
#define LDP_VENDOR_PRIVATE_MAX 0x3eff
|
|
#define LDP_EXPERIMENTAL_MIN 0x3f00
|
|
#define LDP_EXPERIMENTAL_MAX 0x3fff
|
|
|
|
static const struct tok ldp_msg_values[] = {
|
|
{ LDP_MSG_NOTIF, "Notification" },
|
|
{ LDP_MSG_HELLO, "Hello" },
|
|
{ LDP_MSG_INIT, "Initialization" },
|
|
{ LDP_MSG_KEEPALIVE, "Keepalive" },
|
|
{ LDP_MSG_ADDRESS, "Address" },
|
|
{ LDP_MSG_ADDRESS_WITHDRAW, "Address Withdraw" },
|
|
{ LDP_MSG_LABEL_MAPPING, "Label Mapping" },
|
|
{ LDP_MSG_LABEL_REQUEST, "Label Request" },
|
|
{ LDP_MSG_LABEL_WITHDRAW, "Label Withdraw" },
|
|
{ LDP_MSG_LABEL_RELEASE, "Label Release" },
|
|
{ LDP_MSG_LABEL_ABORT_REQUEST, "Label Abort Request" },
|
|
{ 0, NULL}
|
|
};
|
|
|
|
#define LDP_MASK_TLV_TYPE(x) ((x)&0x3fff)
|
|
#define LDP_MASK_F_BIT(x) ((x)&0x4000)
|
|
|
|
#define LDP_TLV_FEC 0x0100
|
|
#define LDP_TLV_ADDRESS_LIST 0x0101
|
|
#define LDP_TLV_ADDRESS_LIST_AFNUM_LEN 2
|
|
#define LDP_TLV_HOP_COUNT 0x0103
|
|
#define LDP_TLV_PATH_VECTOR 0x0104
|
|
#define LDP_TLV_GENERIC_LABEL 0x0200
|
|
#define LDP_TLV_ATM_LABEL 0x0201
|
|
#define LDP_TLV_FR_LABEL 0x0202
|
|
#define LDP_TLV_STATUS 0x0300
|
|
#define LDP_TLV_EXTD_STATUS 0x0301
|
|
#define LDP_TLV_RETURNED_PDU 0x0302
|
|
#define LDP_TLV_RETURNED_MSG 0x0303
|
|
#define LDP_TLV_COMMON_HELLO 0x0400
|
|
#define LDP_TLV_IPV4_TRANSPORT_ADDR 0x0401
|
|
#define LDP_TLV_CONFIG_SEQ_NUMBER 0x0402
|
|
#define LDP_TLV_IPV6_TRANSPORT_ADDR 0x0403
|
|
#define LDP_TLV_COMMON_SESSION 0x0500
|
|
#define LDP_TLV_ATM_SESSION_PARM 0x0501
|
|
#define LDP_TLV_FR_SESSION_PARM 0x0502
|
|
#define LDP_TLV_FT_SESSION 0x0503
|
|
#define LDP_TLV_LABEL_REQUEST_MSG_ID 0x0600
|
|
#define LDP_TLV_MTU 0x0601 /* rfc 3988 */
|
|
|
|
static const struct tok ldp_tlv_values[] = {
|
|
{ LDP_TLV_FEC, "FEC" },
|
|
{ LDP_TLV_ADDRESS_LIST, "Address List" },
|
|
{ LDP_TLV_HOP_COUNT, "Hop Count" },
|
|
{ LDP_TLV_PATH_VECTOR, "Path Vector" },
|
|
{ LDP_TLV_GENERIC_LABEL, "Generic Label" },
|
|
{ LDP_TLV_ATM_LABEL, "ATM Label" },
|
|
{ LDP_TLV_FR_LABEL, "Frame-Relay Label" },
|
|
{ LDP_TLV_STATUS, "Status" },
|
|
{ LDP_TLV_EXTD_STATUS, "Extended Status" },
|
|
{ LDP_TLV_RETURNED_PDU, "Returned PDU" },
|
|
{ LDP_TLV_RETURNED_MSG, "Returned Message" },
|
|
{ LDP_TLV_COMMON_HELLO, "Common Hello Parameters" },
|
|
{ LDP_TLV_IPV4_TRANSPORT_ADDR, "IPv4 Transport Address" },
|
|
{ LDP_TLV_CONFIG_SEQ_NUMBER, "Configuration Sequence Number" },
|
|
{ LDP_TLV_IPV6_TRANSPORT_ADDR, "IPv6 Transport Address" },
|
|
{ LDP_TLV_COMMON_SESSION, "Common Session Parameters" },
|
|
{ LDP_TLV_ATM_SESSION_PARM, "ATM Session Parameters" },
|
|
{ LDP_TLV_FR_SESSION_PARM, "Frame-Relay Session Parameters" },
|
|
{ LDP_TLV_FT_SESSION, "Fault-Tolerant Session Parameters" },
|
|
{ LDP_TLV_LABEL_REQUEST_MSG_ID, "Label Request Message ID" },
|
|
{ LDP_TLV_MTU, "MTU" },
|
|
{ 0, NULL}
|
|
};
|
|
|
|
#define LDP_FEC_WILDCARD 0x01
|
|
#define LDP_FEC_PREFIX 0x02
|
|
#define LDP_FEC_HOSTADDRESS 0x03
|
|
/* From RFC 4906; should probably be updated to RFC 4447 (e.g., VC -> PW) */
|
|
#define LDP_FEC_MARTINI_VC 0x80
|
|
|
|
static const struct tok ldp_fec_values[] = {
|
|
{ LDP_FEC_WILDCARD, "Wildcard" },
|
|
{ LDP_FEC_PREFIX, "Prefix" },
|
|
{ LDP_FEC_HOSTADDRESS, "Host address" },
|
|
{ LDP_FEC_MARTINI_VC, "Martini VC" },
|
|
{ 0, NULL}
|
|
};
|
|
|
|
#define LDP_FEC_MARTINI_IFPARM_MTU 0x01
|
|
#define LDP_FEC_MARTINI_IFPARM_DESC 0x03
|
|
#define LDP_FEC_MARTINI_IFPARM_VCCV 0x0c
|
|
|
|
static const struct tok ldp_fec_martini_ifparm_values[] = {
|
|
{ LDP_FEC_MARTINI_IFPARM_MTU, "MTU" },
|
|
{ LDP_FEC_MARTINI_IFPARM_DESC, "Description" },
|
|
{ LDP_FEC_MARTINI_IFPARM_VCCV, "VCCV" },
|
|
{ 0, NULL}
|
|
};
|
|
|
|
/* draft-ietf-pwe3-vccv-04.txt */
|
|
static const struct tok ldp_fec_martini_ifparm_vccv_cc_values[] = {
|
|
{ 0x01, "PWE3 control word" },
|
|
{ 0x02, "MPLS Router Alert Label" },
|
|
{ 0x04, "MPLS inner label TTL = 1" },
|
|
{ 0, NULL}
|
|
};
|
|
|
|
/* draft-ietf-pwe3-vccv-04.txt */
|
|
static const struct tok ldp_fec_martini_ifparm_vccv_cv_values[] = {
|
|
{ 0x01, "ICMP Ping" },
|
|
{ 0x02, "LSP Ping" },
|
|
{ 0x04, "BFD" },
|
|
{ 0, NULL}
|
|
};
|
|
|
|
int ldp_msg_print(register const u_char *);
|
|
int ldp_tlv_print(register const u_char *);
|
|
|
|
/*
|
|
* ldp tlv header
|
|
*
|
|
* 0 1 2 3
|
|
* 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
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
* |U|F| Type | Length |
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
* | |
|
|
* | Value |
|
|
* ~ ~
|
|
* | |
|
|
* | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
* | |
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
*/
|
|
|
|
#define TLV_TCHECK(minlen) \
|
|
TCHECK2(*tptr, minlen); if (tlv_tlen < minlen) goto badtlv;
|
|
|
|
int
|
|
ldp_tlv_print(register const u_char *tptr) {
|
|
|
|
struct ldp_tlv_header {
|
|
u_int8_t type[2];
|
|
u_int8_t length[2];
|
|
};
|
|
|
|
const struct ldp_tlv_header *ldp_tlv_header;
|
|
u_short tlv_type,tlv_len,tlv_tlen,af,ft_flags;
|
|
u_char fec_type;
|
|
u_int ui,vc_info_len, vc_info_tlv_type, vc_info_tlv_len,idx;
|
|
char buf[100];
|
|
int i;
|
|
|
|
ldp_tlv_header = (const struct ldp_tlv_header *)tptr;
|
|
tlv_len=EXTRACT_16BITS(ldp_tlv_header->length);
|
|
tlv_tlen=tlv_len;
|
|
tlv_type=LDP_MASK_TLV_TYPE(EXTRACT_16BITS(ldp_tlv_header->type));
|
|
|
|
/* FIXME vendor private / experimental check */
|
|
printf("\n\t %s TLV (0x%04x), length: %u, Flags: [%s and %s forward if unknown]",
|
|
tok2str(ldp_tlv_values,
|
|
"Unknown",
|
|
tlv_type),
|
|
tlv_type,
|
|
tlv_len,
|
|
LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "continue processing" : "ignore",
|
|
LDP_MASK_F_BIT(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "do" : "don't");
|
|
|
|
tptr+=sizeof(struct ldp_tlv_header);
|
|
|
|
switch(tlv_type) {
|
|
|
|
case LDP_TLV_COMMON_HELLO:
|
|
TLV_TCHECK(4);
|
|
printf("\n\t Hold Time: %us, Flags: [%s Hello%s]",
|
|
EXTRACT_16BITS(tptr),
|
|
(EXTRACT_16BITS(tptr+2)&0x8000) ? "Targeted" : "Link",
|
|
(EXTRACT_16BITS(tptr+2)&0x4000) ? ", Request for targeted Hellos" : "");
|
|
break;
|
|
|
|
case LDP_TLV_IPV4_TRANSPORT_ADDR:
|
|
TLV_TCHECK(4);
|
|
printf("\n\t IPv4 Transport Address: %s", ipaddr_string(tptr));
|
|
break;
|
|
#ifdef INET6
|
|
case LDP_TLV_IPV6_TRANSPORT_ADDR:
|
|
TLV_TCHECK(16);
|
|
printf("\n\t IPv6 Transport Address: %s", ip6addr_string(tptr));
|
|
break;
|
|
#endif
|
|
case LDP_TLV_CONFIG_SEQ_NUMBER:
|
|
TLV_TCHECK(4);
|
|
printf("\n\t Sequence Number: %u", EXTRACT_32BITS(tptr));
|
|
break;
|
|
|
|
case LDP_TLV_ADDRESS_LIST:
|
|
TLV_TCHECK(LDP_TLV_ADDRESS_LIST_AFNUM_LEN);
|
|
af = EXTRACT_16BITS(tptr);
|
|
tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
|
|
tlv_tlen -= LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
|
|
printf("\n\t Address Family: %s, addresses",
|
|
tok2str(af_values, "Unknown (%u)", af));
|
|
switch (af) {
|
|
case AFNUM_INET:
|
|
while(tlv_tlen >= sizeof(struct in_addr)) {
|
|
TCHECK2(*tptr, sizeof(struct in_addr));
|
|
printf(" %s",ipaddr_string(tptr));
|
|
tlv_tlen-=sizeof(struct in_addr);
|
|
tptr+=sizeof(struct in_addr);
|
|
}
|
|
break;
|
|
#ifdef INET6
|
|
case AFNUM_INET6:
|
|
while(tlv_tlen >= sizeof(struct in6_addr)) {
|
|
TCHECK2(*tptr, sizeof(struct in6_addr));
|
|
printf(" %s",ip6addr_string(tptr));
|
|
tlv_tlen-=sizeof(struct in6_addr);
|
|
tptr+=sizeof(struct in6_addr);
|
|
}
|
|
break;
|
|
#endif
|
|
default:
|
|
/* unknown AF */
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case LDP_TLV_COMMON_SESSION:
|
|
TLV_TCHECK(8);
|
|
printf("\n\t Version: %u, Keepalive: %us, Flags: [Downstream %s, Loop Detection %s]",
|
|
EXTRACT_16BITS(tptr), EXTRACT_16BITS(tptr+2),
|
|
(EXTRACT_16BITS(tptr+6)&0x8000) ? "On Demand" : "Unsolicited",
|
|
(EXTRACT_16BITS(tptr+6)&0x4000) ? "Enabled" : "Disabled"
|
|
);
|
|
break;
|
|
|
|
case LDP_TLV_FEC:
|
|
TLV_TCHECK(1);
|
|
fec_type = *tptr;
|
|
printf("\n\t %s FEC (0x%02x)",
|
|
tok2str(ldp_fec_values, "Unknown", fec_type),
|
|
fec_type);
|
|
|
|
tptr+=1;
|
|
tlv_tlen-=1;
|
|
switch(fec_type) {
|
|
|
|
case LDP_FEC_WILDCARD:
|
|
break;
|
|
case LDP_FEC_PREFIX:
|
|
TLV_TCHECK(2);
|
|
af = EXTRACT_16BITS(tptr);
|
|
tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
|
|
tlv_tlen-=LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
|
|
if (af == AFNUM_INET) {
|
|
i=decode_prefix4(tptr,tlv_tlen,buf,sizeof(buf));
|
|
if (i == -2)
|
|
goto trunc;
|
|
if (i == -3)
|
|
printf(": IPv4 prefix (goes past end of TLV)");
|
|
else if (i == -1)
|
|
printf(": IPv4 prefix (invalid length)");
|
|
else
|
|
printf(": IPv4 prefix %s",buf);
|
|
}
|
|
#ifdef INET6
|
|
else if (af == AFNUM_INET6) {
|
|
i=decode_prefix6(tptr,tlv_tlen,buf,sizeof(buf));
|
|
if (i == -2)
|
|
goto trunc;
|
|
if (i == -3)
|
|
printf(": IPv4 prefix (goes past end of TLV)");
|
|
else if (i == -1)
|
|
printf(": IPv6 prefix (invalid length)");
|
|
else
|
|
printf(": IPv6 prefix %s",buf);
|
|
}
|
|
#endif
|
|
else
|
|
printf(": Address family %u prefix", af);
|
|
break;
|
|
case LDP_FEC_HOSTADDRESS:
|
|
break;
|
|
case LDP_FEC_MARTINI_VC:
|
|
/*
|
|
* According to RFC 4908, the VC info Length field can be zero,
|
|
* in which case not only are there no interface parameters,
|
|
* there's no VC ID.
|
|
*/
|
|
TLV_TCHECK(7);
|
|
vc_info_len = *(tptr+2);
|
|
|
|
if (vc_info_len == 0) {
|
|
printf(": %s, %scontrol word, group-ID %u, VC-info-length: %u",
|
|
tok2str(l2vpn_encaps_values, "Unknown", EXTRACT_16BITS(tptr)&0x7fff),
|
|
EXTRACT_16BITS(tptr)&0x8000 ? "" : "no ",
|
|
EXTRACT_32BITS(tptr+3),
|
|
vc_info_len);
|
|
break;
|
|
}
|
|
|
|
/* Make sure we have the VC ID as well */
|
|
TLV_TCHECK(11);
|
|
printf(": %s, %scontrol word, group-ID %u, VC-ID %u, VC-info-length: %u",
|
|
tok2str(l2vpn_encaps_values, "Unknown", EXTRACT_16BITS(tptr)&0x7fff),
|
|
EXTRACT_16BITS(tptr)&0x8000 ? "" : "no ",
|
|
EXTRACT_32BITS(tptr+3),
|
|
EXTRACT_32BITS(tptr+7),
|
|
vc_info_len);
|
|
if (vc_info_len < 4)
|
|
goto trunc; /* minimum 4, for the VC ID */
|
|
vc_info_len -= 4; /* subtract out the VC ID, giving the length of the interface parameters */
|
|
|
|
/* Skip past the fixed information and the VC ID */
|
|
tptr+=11;
|
|
tlv_tlen-=11;
|
|
TLV_TCHECK(vc_info_len);
|
|
|
|
while (vc_info_len > 2) {
|
|
vc_info_tlv_type = *tptr;
|
|
vc_info_tlv_len = *(tptr+1);
|
|
if (vc_info_tlv_len < 2)
|
|
break;
|
|
if (vc_info_len < vc_info_tlv_len)
|
|
break;
|
|
|
|
printf("\n\t\tInterface Parameter: %s (0x%02x), len %u",
|
|
tok2str(ldp_fec_martini_ifparm_values,"Unknown",vc_info_tlv_type),
|
|
vc_info_tlv_type,
|
|
vc_info_tlv_len);
|
|
|
|
switch(vc_info_tlv_type) {
|
|
case LDP_FEC_MARTINI_IFPARM_MTU:
|
|
printf(": %u",EXTRACT_16BITS(tptr+2));
|
|
break;
|
|
|
|
case LDP_FEC_MARTINI_IFPARM_DESC:
|
|
printf(": ");
|
|
for (idx = 2; idx < vc_info_tlv_len; idx++)
|
|
safeputchar(*(tptr+idx));
|
|
break;
|
|
|
|
case LDP_FEC_MARTINI_IFPARM_VCCV:
|
|
printf("\n\t\t Control Channels (0x%02x) = [%s]",
|
|
*(tptr+2),
|
|
bittok2str(ldp_fec_martini_ifparm_vccv_cc_values,"none",*(tptr+2)));
|
|
printf("\n\t\t CV Types (0x%02x) = [%s]",
|
|
*(tptr+3),
|
|
bittok2str(ldp_fec_martini_ifparm_vccv_cv_values,"none",*(tptr+3)));
|
|
break;
|
|
|
|
default:
|
|
print_unknown_data(tptr+2,"\n\t\t ",vc_info_tlv_len-2);
|
|
break;
|
|
}
|
|
|
|
vc_info_len -= vc_info_tlv_len;
|
|
tptr += vc_info_tlv_len;
|
|
}
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
case LDP_TLV_GENERIC_LABEL:
|
|
TLV_TCHECK(4);
|
|
printf("\n\t Label: %u", EXTRACT_32BITS(tptr) & 0xfffff);
|
|
break;
|
|
|
|
case LDP_TLV_STATUS:
|
|
TLV_TCHECK(8);
|
|
ui = EXTRACT_32BITS(tptr);
|
|
tptr+=4;
|
|
printf("\n\t Status: 0x%02x, Flags: [%s and %s forward]",
|
|
ui&0x3fffffff,
|
|
ui&0x80000000 ? "Fatal error" : "Advisory Notification",
|
|
ui&0x40000000 ? "do" : "don't");
|
|
ui = EXTRACT_32BITS(tptr);
|
|
tptr+=4;
|
|
if (ui)
|
|
printf(", causing Message ID: 0x%08x", ui);
|
|
break;
|
|
|
|
case LDP_TLV_FT_SESSION:
|
|
TLV_TCHECK(8);
|
|
ft_flags = EXTRACT_16BITS(tptr);
|
|
printf("\n\t Flags: [%sReconnect, %sSave State, %sAll-Label Protection, %s Checkpoint, %sRe-Learn State]",
|
|
ft_flags&0x8000 ? "" : "No ",
|
|
ft_flags&0x8 ? "" : "Don't ",
|
|
ft_flags&0x4 ? "" : "No ",
|
|
ft_flags&0x2 ? "Sequence Numbered Label" : "All Labels",
|
|
ft_flags&0x1 ? "" : "Don't ");
|
|
tptr+=4;
|
|
ui = EXTRACT_32BITS(tptr);
|
|
if (ui)
|
|
printf(", Reconnect Timeout: %ums", ui);
|
|
tptr+=4;
|
|
ui = EXTRACT_32BITS(tptr);
|
|
if (ui)
|
|
printf(", Recovery Time: %ums", ui);
|
|
break;
|
|
|
|
case LDP_TLV_MTU:
|
|
TLV_TCHECK(2);
|
|
printf("\n\t MTU: %u", EXTRACT_16BITS(tptr));
|
|
break;
|
|
|
|
|
|
/*
|
|
* FIXME those are the defined TLVs that lack a decoder
|
|
* you are welcome to contribute code ;-)
|
|
*/
|
|
|
|
case LDP_TLV_HOP_COUNT:
|
|
case LDP_TLV_PATH_VECTOR:
|
|
case LDP_TLV_ATM_LABEL:
|
|
case LDP_TLV_FR_LABEL:
|
|
case LDP_TLV_EXTD_STATUS:
|
|
case LDP_TLV_RETURNED_PDU:
|
|
case LDP_TLV_RETURNED_MSG:
|
|
case LDP_TLV_ATM_SESSION_PARM:
|
|
case LDP_TLV_FR_SESSION_PARM:
|
|
case LDP_TLV_LABEL_REQUEST_MSG_ID:
|
|
|
|
default:
|
|
if (vflag <= 1)
|
|
print_unknown_data(tptr,"\n\t ",tlv_tlen);
|
|
break;
|
|
}
|
|
return(tlv_len+4); /* Type & Length fields not included */
|
|
|
|
trunc:
|
|
printf("\n\t\t packet exceeded snapshot");
|
|
return 0;
|
|
|
|
badtlv:
|
|
printf("\n\t\t TLV contents go past end of TLV");
|
|
return(tlv_len+4); /* Type & Length fields not included */
|
|
}
|
|
|
|
void
|
|
ldp_print(register const u_char *pptr, register u_int len) {
|
|
|
|
int processed;
|
|
while (len > (sizeof(struct ldp_common_header) + sizeof(struct ldp_msg_header))) {
|
|
processed = ldp_msg_print(pptr);
|
|
if (processed == 0)
|
|
return;
|
|
len -= processed;
|
|
pptr += processed;
|
|
}
|
|
}
|
|
|
|
|
|
int
|
|
ldp_msg_print(register const u_char *pptr) {
|
|
|
|
const struct ldp_common_header *ldp_com_header;
|
|
const struct ldp_msg_header *ldp_msg_header;
|
|
const u_char *tptr,*msg_tptr;
|
|
u_short tlen;
|
|
u_short pdu_len,msg_len,msg_type,msg_tlen;
|
|
int hexdump,processed;
|
|
|
|
tptr=pptr;
|
|
ldp_com_header = (const struct ldp_common_header *)pptr;
|
|
TCHECK(*ldp_com_header);
|
|
|
|
/*
|
|
* Sanity checking of the header.
|
|
*/
|
|
if (EXTRACT_16BITS(&ldp_com_header->version) != LDP_VERSION) {
|
|
printf("%sLDP version %u packet not supported",
|
|
(vflag < 1) ? "" : "\n\t",
|
|
EXTRACT_16BITS(&ldp_com_header->version));
|
|
return 0;
|
|
}
|
|
|
|
/* print the LSR-ID, label-space & length */
|
|
pdu_len = EXTRACT_16BITS(&ldp_com_header->pdu_length);
|
|
printf("%sLDP, Label-Space-ID: %s:%u, pdu-length: %u",
|
|
(vflag < 1) ? "" : "\n\t",
|
|
ipaddr_string(&ldp_com_header->lsr_id),
|
|
EXTRACT_16BITS(&ldp_com_header->label_space),
|
|
pdu_len);
|
|
|
|
/* bail out if non-verbose */
|
|
if (vflag < 1)
|
|
return 0;
|
|
|
|
/* ok they seem to want to know everything - lets fully decode it */
|
|
tlen=pdu_len;
|
|
|
|
tptr += sizeof(const struct ldp_common_header);
|
|
tlen -= sizeof(const struct ldp_common_header)-4; /* Type & Length fields not included */
|
|
|
|
while(tlen>0) {
|
|
/* did we capture enough for fully decoding the msg header ? */
|
|
TCHECK2(*tptr, sizeof(struct ldp_msg_header));
|
|
|
|
ldp_msg_header = (const struct ldp_msg_header *)tptr;
|
|
msg_len=EXTRACT_16BITS(ldp_msg_header->length);
|
|
msg_type=LDP_MASK_MSG_TYPE(EXTRACT_16BITS(ldp_msg_header->type));
|
|
|
|
/* FIXME vendor private / experimental check */
|
|
printf("\n\t %s Message (0x%04x), length: %u, Message ID: 0x%08x, Flags: [%s if unknown]",
|
|
tok2str(ldp_msg_values,
|
|
"Unknown",
|
|
msg_type),
|
|
msg_type,
|
|
msg_len,
|
|
EXTRACT_32BITS(&ldp_msg_header->id),
|
|
LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_msg_header->type)) ? "continue processing" : "ignore");
|
|
|
|
if (msg_len == 0) /* infinite loop protection */
|
|
return 0;
|
|
|
|
msg_tptr=tptr+sizeof(struct ldp_msg_header);
|
|
msg_tlen=msg_len-sizeof(struct ldp_msg_header)+4; /* Type & Length fields not included */
|
|
|
|
/* did we capture enough for fully decoding the message ? */
|
|
TCHECK2(*tptr, msg_len);
|
|
hexdump=FALSE;
|
|
|
|
switch(msg_type) {
|
|
|
|
case LDP_MSG_NOTIF:
|
|
case LDP_MSG_HELLO:
|
|
case LDP_MSG_INIT:
|
|
case LDP_MSG_KEEPALIVE:
|
|
case LDP_MSG_ADDRESS:
|
|
case LDP_MSG_LABEL_MAPPING:
|
|
case LDP_MSG_ADDRESS_WITHDRAW:
|
|
case LDP_MSG_LABEL_WITHDRAW:
|
|
while(msg_tlen >= 4) {
|
|
processed = ldp_tlv_print(msg_tptr);
|
|
if (processed == 0)
|
|
break;
|
|
msg_tlen-=processed;
|
|
msg_tptr+=processed;
|
|
}
|
|
break;
|
|
|
|
/*
|
|
* FIXME those are the defined messages that lack a decoder
|
|
* you are welcome to contribute code ;-)
|
|
*/
|
|
|
|
case LDP_MSG_LABEL_REQUEST:
|
|
case LDP_MSG_LABEL_RELEASE:
|
|
case LDP_MSG_LABEL_ABORT_REQUEST:
|
|
|
|
default:
|
|
if (vflag <= 1)
|
|
print_unknown_data(msg_tptr,"\n\t ",msg_tlen);
|
|
break;
|
|
}
|
|
/* do we want to see an additionally hexdump ? */
|
|
if (vflag > 1 || hexdump==TRUE)
|
|
print_unknown_data(tptr+sizeof(struct ldp_msg_header),"\n\t ",
|
|
msg_len);
|
|
|
|
tptr += msg_len+4;
|
|
tlen -= msg_len+4;
|
|
}
|
|
return pdu_len+4;
|
|
trunc:
|
|
printf("\n\t\t packet exceeded snapshot");
|
|
return 0;
|
|
}
|
|
|