1127668Sbms/* 2127668Sbms * Redistribution and use in source and binary forms, with or without 3127668Sbms * modification, are permitted provided that: (1) source code 4127668Sbms * distributions retain the above copyright notice and this paragraph 5127668Sbms * in its entirety, and (2) distributions including binary code include 6127668Sbms * the above copyright notice and this paragraph in its entirety in 7127668Sbms * the documentation or other materials provided with the distribution. 8127668Sbms * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 9127668Sbms * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT 10127668Sbms * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 11127668Sbms * FOR A PARTICULAR PURPOSE. 12127668Sbms * 13127668Sbms * Original code by Hannes Gredler (hannes@juniper.net) 14146773Ssam * and Steinar Haug (sthaug@nethelp.no) 15127668Sbms */ 16127668Sbms 17127668Sbms#ifndef lint 18127668Sbmsstatic const char rcsid[] _U_ = 19190207Srpaulo "@(#) $Header: /tcpdump/master/tcpdump/print-ldp.c,v 1.20 2006-06-23 02:03:09 hannes Exp $"; 20127668Sbms#endif 21127668Sbms 22127668Sbms#ifdef HAVE_CONFIG_H 23127668Sbms#include "config.h" 24127668Sbms#endif 25127668Sbms 26127668Sbms#include <tcpdump-stdinc.h> 27127668Sbms 28127668Sbms#include <stdio.h> 29127668Sbms#include <stdlib.h> 30127668Sbms#include <string.h> 31127668Sbms 32127668Sbms#include "interface.h" 33146773Ssam#include "decode_prefix.h" 34127668Sbms#include "extract.h" 35127668Sbms#include "addrtoname.h" 36127668Sbms 37146773Ssam#include "l2vpn.h" 38190207Srpaulo#include "af.h" 39146773Ssam 40127668Sbms/* 41127668Sbms * ldp common header 42127668Sbms * 43127668Sbms * 0 1 2 3 44127668Sbms * 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 45127668Sbms * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 46127668Sbms * | Version | PDU Length | 47127668Sbms * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 48127668Sbms * | LDP Identifier | 49127668Sbms * + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 50127668Sbms * | | 51127668Sbms * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 52127668Sbms * 53127668Sbms */ 54127668Sbms 55127668Sbmsstruct ldp_common_header { 56127668Sbms u_int8_t version[2]; 57127668Sbms u_int8_t pdu_length[2]; 58127668Sbms u_int8_t lsr_id[4]; 59127668Sbms u_int8_t label_space[2]; 60127668Sbms}; 61127668Sbms 62127668Sbms#define LDP_VERSION 1 63127668Sbms 64127668Sbms/* 65127668Sbms * ldp message header 66127668Sbms * 67127668Sbms * 0 1 2 3 68127668Sbms * 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 69127668Sbms * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 70127668Sbms * |U| Message Type | Message Length | 71127668Sbms * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 72127668Sbms * | Message ID | 73127668Sbms * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 74127668Sbms * | | 75127668Sbms * + + 76127668Sbms * | Mandatory Parameters | 77127668Sbms * + + 78127668Sbms * | | 79127668Sbms * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 80127668Sbms * | | 81127668Sbms * + + 82127668Sbms * | Optional Parameters | 83127668Sbms * + + 84127668Sbms * | | 85127668Sbms * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 86127668Sbms */ 87127668Sbms 88127668Sbmsstruct ldp_msg_header { 89127668Sbms u_int8_t type[2]; 90127668Sbms u_int8_t length[2]; 91127668Sbms u_int8_t id[4]; 92127668Sbms}; 93127668Sbms 94127668Sbms#define LDP_MASK_MSG_TYPE(x) ((x)&0x7fff) 95127668Sbms#define LDP_MASK_U_BIT(x) ((x)&0x8000) 96127668Sbms 97127668Sbms#define LDP_MSG_NOTIF 0x0001 98127668Sbms#define LDP_MSG_HELLO 0x0100 99127668Sbms#define LDP_MSG_INIT 0x0200 100127668Sbms#define LDP_MSG_KEEPALIVE 0x0201 101127668Sbms#define LDP_MSG_ADDRESS 0x0300 102127668Sbms#define LDP_MSG_ADDRESS_WITHDRAW 0x0301 103127668Sbms#define LDP_MSG_LABEL_MAPPING 0x0400 104127668Sbms#define LDP_MSG_LABEL_REQUEST 0x0401 105127668Sbms#define LDP_MSG_LABEL_WITHDRAW 0x0402 106127668Sbms#define LDP_MSG_LABEL_RELEASE 0x0403 107127668Sbms#define LDP_MSG_LABEL_ABORT_REQUEST 0x0404 108127668Sbms 109127668Sbms#define LDP_VENDOR_PRIVATE_MIN 0x3e00 110127668Sbms#define LDP_VENDOR_PRIVATE_MAX 0x3eff 111127668Sbms#define LDP_EXPERIMENTAL_MIN 0x3f00 112127668Sbms#define LDP_EXPERIMENTAL_MAX 0x3fff 113127668Sbms 114127668Sbmsstatic const struct tok ldp_msg_values[] = { 115127668Sbms { LDP_MSG_NOTIF, "Notification" }, 116127668Sbms { LDP_MSG_HELLO, "Hello" }, 117127668Sbms { LDP_MSG_INIT, "Initialization" }, 118127668Sbms { LDP_MSG_KEEPALIVE, "Keepalive" }, 119127668Sbms { LDP_MSG_ADDRESS, "Address" }, 120172683Smlaier { LDP_MSG_ADDRESS_WITHDRAW, "Address Withdraw" }, 121127668Sbms { LDP_MSG_LABEL_MAPPING, "Label Mapping" }, 122127668Sbms { LDP_MSG_LABEL_REQUEST, "Label Request" }, 123127668Sbms { LDP_MSG_LABEL_WITHDRAW, "Label Withdraw" }, 124127668Sbms { LDP_MSG_LABEL_RELEASE, "Label Release" }, 125127668Sbms { LDP_MSG_LABEL_ABORT_REQUEST, "Label Abort Request" }, 126127668Sbms { 0, NULL} 127127668Sbms}; 128127668Sbms 129127668Sbms#define LDP_MASK_TLV_TYPE(x) ((x)&0x3fff) 130127668Sbms#define LDP_MASK_F_BIT(x) ((x)&0x4000) 131127668Sbms 132127668Sbms#define LDP_TLV_FEC 0x0100 133127668Sbms#define LDP_TLV_ADDRESS_LIST 0x0101 134190207Srpaulo#define LDP_TLV_ADDRESS_LIST_AFNUM_LEN 2 135127668Sbms#define LDP_TLV_HOP_COUNT 0x0103 136127668Sbms#define LDP_TLV_PATH_VECTOR 0x0104 137127668Sbms#define LDP_TLV_GENERIC_LABEL 0x0200 138127668Sbms#define LDP_TLV_ATM_LABEL 0x0201 139127668Sbms#define LDP_TLV_FR_LABEL 0x0202 140127668Sbms#define LDP_TLV_STATUS 0x0300 141127668Sbms#define LDP_TLV_EXTD_STATUS 0x0301 142127668Sbms#define LDP_TLV_RETURNED_PDU 0x0302 143127668Sbms#define LDP_TLV_RETURNED_MSG 0x0303 144127668Sbms#define LDP_TLV_COMMON_HELLO 0x0400 145127668Sbms#define LDP_TLV_IPV4_TRANSPORT_ADDR 0x0401 146127668Sbms#define LDP_TLV_CONFIG_SEQ_NUMBER 0x0402 147127668Sbms#define LDP_TLV_IPV6_TRANSPORT_ADDR 0x0403 148127668Sbms#define LDP_TLV_COMMON_SESSION 0x0500 149127668Sbms#define LDP_TLV_ATM_SESSION_PARM 0x0501 150127668Sbms#define LDP_TLV_FR_SESSION_PARM 0x0502 151146773Ssam#define LDP_TLV_FT_SESSION 0x0503 152127668Sbms#define LDP_TLV_LABEL_REQUEST_MSG_ID 0x0600 153190207Srpaulo#define LDP_TLV_MTU 0x0601 /* rfc 3988 */ 154127668Sbms 155127668Sbmsstatic const struct tok ldp_tlv_values[] = { 156127668Sbms { LDP_TLV_FEC, "FEC" }, 157127668Sbms { LDP_TLV_ADDRESS_LIST, "Address List" }, 158127668Sbms { LDP_TLV_HOP_COUNT, "Hop Count" }, 159127668Sbms { LDP_TLV_PATH_VECTOR, "Path Vector" }, 160127668Sbms { LDP_TLV_GENERIC_LABEL, "Generic Label" }, 161127668Sbms { LDP_TLV_ATM_LABEL, "ATM Label" }, 162127668Sbms { LDP_TLV_FR_LABEL, "Frame-Relay Label" }, 163127668Sbms { LDP_TLV_STATUS, "Status" }, 164127668Sbms { LDP_TLV_EXTD_STATUS, "Extended Status" }, 165127668Sbms { LDP_TLV_RETURNED_PDU, "Returned PDU" }, 166127668Sbms { LDP_TLV_RETURNED_MSG, "Returned Message" }, 167127668Sbms { LDP_TLV_COMMON_HELLO, "Common Hello Parameters" }, 168127668Sbms { LDP_TLV_IPV4_TRANSPORT_ADDR, "IPv4 Transport Address" }, 169127668Sbms { LDP_TLV_CONFIG_SEQ_NUMBER, "Configuration Sequence Number" }, 170127668Sbms { LDP_TLV_IPV6_TRANSPORT_ADDR, "IPv6 Transport Address" }, 171127668Sbms { LDP_TLV_COMMON_SESSION, "Common Session Parameters" }, 172127668Sbms { LDP_TLV_ATM_SESSION_PARM, "ATM Session Parameters" }, 173127668Sbms { LDP_TLV_FR_SESSION_PARM, "Frame-Relay Session Parameters" }, 174146773Ssam { LDP_TLV_FT_SESSION, "Fault-Tolerant Session Parameters" }, 175127668Sbms { LDP_TLV_LABEL_REQUEST_MSG_ID, "Label Request Message ID" }, 176190207Srpaulo { LDP_TLV_MTU, "MTU" }, 177127668Sbms { 0, NULL} 178127668Sbms}; 179127668Sbms 180146773Ssam#define LDP_FEC_WILDCARD 0x01 181146773Ssam#define LDP_FEC_PREFIX 0x02 182146773Ssam#define LDP_FEC_HOSTADDRESS 0x03 183241235Sdelphij/* From RFC 4906; should probably be updated to RFC 4447 (e.g., VC -> PW) */ 184146773Ssam#define LDP_FEC_MARTINI_VC 0x80 185146773Ssam 186146773Ssamstatic const struct tok ldp_fec_values[] = { 187146773Ssam { LDP_FEC_WILDCARD, "Wildcard" }, 188146773Ssam { LDP_FEC_PREFIX, "Prefix" }, 189146773Ssam { LDP_FEC_HOSTADDRESS, "Host address" }, 190146773Ssam { LDP_FEC_MARTINI_VC, "Martini VC" }, 191146773Ssam { 0, NULL} 192146773Ssam}; 193146773Ssam 194147899Ssam#define LDP_FEC_MARTINI_IFPARM_MTU 0x01 195147899Ssam#define LDP_FEC_MARTINI_IFPARM_DESC 0x03 196147899Ssam#define LDP_FEC_MARTINI_IFPARM_VCCV 0x0c 197147899Ssam 198147899Ssamstatic const struct tok ldp_fec_martini_ifparm_values[] = { 199147899Ssam { LDP_FEC_MARTINI_IFPARM_MTU, "MTU" }, 200147899Ssam { LDP_FEC_MARTINI_IFPARM_DESC, "Description" }, 201147899Ssam { LDP_FEC_MARTINI_IFPARM_VCCV, "VCCV" }, 202147899Ssam { 0, NULL} 203147899Ssam}; 204147899Ssam 205147899Ssam/* draft-ietf-pwe3-vccv-04.txt */ 206147899Ssamstatic const struct tok ldp_fec_martini_ifparm_vccv_cc_values[] = { 207147899Ssam { 0x01, "PWE3 control word" }, 208147899Ssam { 0x02, "MPLS Router Alert Label" }, 209147899Ssam { 0x04, "MPLS inner label TTL = 1" }, 210147899Ssam { 0, NULL} 211147899Ssam}; 212147899Ssam 213147899Ssam/* draft-ietf-pwe3-vccv-04.txt */ 214147899Ssamstatic const struct tok ldp_fec_martini_ifparm_vccv_cv_values[] = { 215147899Ssam { 0x01, "ICMP Ping" }, 216147899Ssam { 0x02, "LSP Ping" }, 217147899Ssam { 0x04, "BFD" }, 218147899Ssam { 0, NULL} 219147899Ssam}; 220147899Ssam 221147899Ssamint ldp_msg_print(register const u_char *); 222127668Sbmsint ldp_tlv_print(register const u_char *); 223127668Sbms 224127668Sbms/* 225127668Sbms * ldp tlv header 226127668Sbms * 227127668Sbms * 0 1 2 3 228127668Sbms * 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 229127668Sbms * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 230127668Sbms * |U|F| Type | Length | 231127668Sbms * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 232127668Sbms * | | 233127668Sbms * | Value | 234127668Sbms * ~ ~ 235127668Sbms * | | 236127668Sbms * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 237127668Sbms * | | 238127668Sbms * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 239127668Sbms */ 240127668Sbms 241241235Sdelphij#define TLV_TCHECK(minlen) \ 242241235Sdelphij TCHECK2(*tptr, minlen); if (tlv_tlen < minlen) goto badtlv; 243241235Sdelphij 244127668Sbmsint 245127668Sbmsldp_tlv_print(register const u_char *tptr) { 246127668Sbms 247127668Sbms struct ldp_tlv_header { 248127668Sbms u_int8_t type[2]; 249127668Sbms u_int8_t length[2]; 250127668Sbms }; 251127668Sbms 252127668Sbms const struct ldp_tlv_header *ldp_tlv_header; 253146773Ssam u_short tlv_type,tlv_len,tlv_tlen,af,ft_flags; 254146773Ssam u_char fec_type; 255147899Ssam u_int ui,vc_info_len, vc_info_tlv_type, vc_info_tlv_len,idx; 256146773Ssam char buf[100]; 257146773Ssam int i; 258127668Sbms 259127668Sbms ldp_tlv_header = (const struct ldp_tlv_header *)tptr; 260127668Sbms tlv_len=EXTRACT_16BITS(ldp_tlv_header->length); 261127668Sbms tlv_tlen=tlv_len; 262127668Sbms tlv_type=LDP_MASK_TLV_TYPE(EXTRACT_16BITS(ldp_tlv_header->type)); 263127668Sbms 264127668Sbms /* FIXME vendor private / experimental check */ 265127668Sbms printf("\n\t %s TLV (0x%04x), length: %u, Flags: [%s and %s forward if unknown]", 266127668Sbms tok2str(ldp_tlv_values, 267127668Sbms "Unknown", 268127668Sbms tlv_type), 269127668Sbms tlv_type, 270127668Sbms tlv_len, 271127668Sbms LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "continue processing" : "ignore", 272127668Sbms LDP_MASK_F_BIT(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "do" : "don't"); 273127668Sbms 274127668Sbms tptr+=sizeof(struct ldp_tlv_header); 275127668Sbms 276127668Sbms switch(tlv_type) { 277127668Sbms 278127668Sbms case LDP_TLV_COMMON_HELLO: 279241235Sdelphij TLV_TCHECK(4); 280127668Sbms printf("\n\t Hold Time: %us, Flags: [%s Hello%s]", 281127668Sbms EXTRACT_16BITS(tptr), 282127668Sbms (EXTRACT_16BITS(tptr+2)&0x8000) ? "Targeted" : "Link", 283127668Sbms (EXTRACT_16BITS(tptr+2)&0x4000) ? ", Request for targeted Hellos" : ""); 284127668Sbms break; 285127668Sbms 286127668Sbms case LDP_TLV_IPV4_TRANSPORT_ADDR: 287241235Sdelphij TLV_TCHECK(4); 288127668Sbms printf("\n\t IPv4 Transport Address: %s", ipaddr_string(tptr)); 289127668Sbms break; 290127668Sbms#ifdef INET6 291127668Sbms case LDP_TLV_IPV6_TRANSPORT_ADDR: 292241235Sdelphij TLV_TCHECK(16); 293127668Sbms printf("\n\t IPv6 Transport Address: %s", ip6addr_string(tptr)); 294127668Sbms break; 295127668Sbms#endif 296127668Sbms case LDP_TLV_CONFIG_SEQ_NUMBER: 297241235Sdelphij TLV_TCHECK(4); 298127668Sbms printf("\n\t Sequence Number: %u", EXTRACT_32BITS(tptr)); 299127668Sbms break; 300127668Sbms 301146773Ssam case LDP_TLV_ADDRESS_LIST: 302241235Sdelphij TLV_TCHECK(LDP_TLV_ADDRESS_LIST_AFNUM_LEN); 303146773Ssam af = EXTRACT_16BITS(tptr); 304190207Srpaulo tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; 305190207Srpaulo tlv_tlen -= LDP_TLV_ADDRESS_LIST_AFNUM_LEN; 306190207Srpaulo printf("\n\t Address Family: %s, addresses", 307190207Srpaulo tok2str(af_values, "Unknown (%u)", af)); 308190207Srpaulo switch (af) { 309190207Srpaulo case AFNUM_INET: 310172683Smlaier while(tlv_tlen >= sizeof(struct in_addr)) { 311241235Sdelphij TCHECK2(*tptr, sizeof(struct in_addr)); 312146773Ssam printf(" %s",ipaddr_string(tptr)); 313172683Smlaier tlv_tlen-=sizeof(struct in_addr); 314172683Smlaier tptr+=sizeof(struct in_addr); 315146773Ssam } 316190207Srpaulo break; 317146773Ssam#ifdef INET6 318190207Srpaulo case AFNUM_INET6: 319172683Smlaier while(tlv_tlen >= sizeof(struct in6_addr)) { 320241235Sdelphij TCHECK2(*tptr, sizeof(struct in6_addr)); 321146773Ssam printf(" %s",ip6addr_string(tptr)); 322172683Smlaier tlv_tlen-=sizeof(struct in6_addr); 323172683Smlaier tptr+=sizeof(struct in6_addr); 324146773Ssam } 325190207Srpaulo break; 326146773Ssam#endif 327190207Srpaulo default: 328190207Srpaulo /* unknown AF */ 329190207Srpaulo break; 330190207Srpaulo } 331146773Ssam break; 332146773Ssam 333146773Ssam case LDP_TLV_COMMON_SESSION: 334241235Sdelphij TLV_TCHECK(8); 335146773Ssam printf("\n\t Version: %u, Keepalive: %us, Flags: [Downstream %s, Loop Detection %s]", 336146773Ssam EXTRACT_16BITS(tptr), EXTRACT_16BITS(tptr+2), 337146773Ssam (EXTRACT_16BITS(tptr+6)&0x8000) ? "On Demand" : "Unsolicited", 338146773Ssam (EXTRACT_16BITS(tptr+6)&0x4000) ? "Enabled" : "Disabled" 339146773Ssam ); 340146773Ssam break; 341146773Ssam 342146773Ssam case LDP_TLV_FEC: 343241235Sdelphij TLV_TCHECK(1); 344146773Ssam fec_type = *tptr; 345146773Ssam printf("\n\t %s FEC (0x%02x)", 346146773Ssam tok2str(ldp_fec_values, "Unknown", fec_type), 347146773Ssam fec_type); 348146773Ssam 349146773Ssam tptr+=1; 350241235Sdelphij tlv_tlen-=1; 351146773Ssam switch(fec_type) { 352146773Ssam 353146773Ssam case LDP_FEC_WILDCARD: 354146773Ssam break; 355146773Ssam case LDP_FEC_PREFIX: 356241235Sdelphij TLV_TCHECK(2); 357146773Ssam af = EXTRACT_16BITS(tptr); 358241235Sdelphij tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; 359241235Sdelphij tlv_tlen-=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; 360146773Ssam if (af == AFNUM_INET) { 361241235Sdelphij i=decode_prefix4(tptr,tlv_tlen,buf,sizeof(buf)); 362241235Sdelphij if (i == -2) 363241235Sdelphij goto trunc; 364241235Sdelphij if (i == -3) 365241235Sdelphij printf(": IPv4 prefix (goes past end of TLV)"); 366241235Sdelphij else if (i == -1) 367241235Sdelphij printf(": IPv4 prefix (invalid length)"); 368241235Sdelphij else 369241235Sdelphij printf(": IPv4 prefix %s",buf); 370146773Ssam } 371146773Ssam#ifdef INET6 372146773Ssam else if (af == AFNUM_INET6) { 373241235Sdelphij i=decode_prefix6(tptr,tlv_tlen,buf,sizeof(buf)); 374241235Sdelphij if (i == -2) 375241235Sdelphij goto trunc; 376241235Sdelphij if (i == -3) 377241235Sdelphij printf(": IPv4 prefix (goes past end of TLV)"); 378241235Sdelphij else if (i == -1) 379241235Sdelphij printf(": IPv6 prefix (invalid length)"); 380241235Sdelphij else 381241235Sdelphij printf(": IPv6 prefix %s",buf); 382146773Ssam } 383146773Ssam#endif 384241235Sdelphij else 385241235Sdelphij printf(": Address family %u prefix", af); 386146773Ssam break; 387146773Ssam case LDP_FEC_HOSTADDRESS: 388146773Ssam break; 389146773Ssam case LDP_FEC_MARTINI_VC: 390241235Sdelphij /* 391241235Sdelphij * According to RFC 4908, the VC info Length field can be zero, 392241235Sdelphij * in which case not only are there no interface parameters, 393241235Sdelphij * there's no VC ID. 394241235Sdelphij */ 395241235Sdelphij TLV_TCHECK(7); 396147899Ssam vc_info_len = *(tptr+2); 397147899Ssam 398241235Sdelphij if (vc_info_len == 0) { 399241235Sdelphij printf(": %s, %scontrol word, group-ID %u, VC-info-length: %u", 400241235Sdelphij tok2str(l2vpn_encaps_values, "Unknown", EXTRACT_16BITS(tptr)&0x7fff), 401241235Sdelphij EXTRACT_16BITS(tptr)&0x8000 ? "" : "no ", 402241235Sdelphij EXTRACT_32BITS(tptr+3), 403241235Sdelphij vc_info_len); 404241235Sdelphij break; 405241235Sdelphij } 406241235Sdelphij 407241235Sdelphij /* Make sure we have the VC ID as well */ 408241235Sdelphij TLV_TCHECK(11); 409147899Ssam printf(": %s, %scontrol word, group-ID %u, VC-ID %u, VC-info-length: %u", 410146773Ssam tok2str(l2vpn_encaps_values, "Unknown", EXTRACT_16BITS(tptr)&0x7fff), 411146773Ssam EXTRACT_16BITS(tptr)&0x8000 ? "" : "no ", 412147899Ssam EXTRACT_32BITS(tptr+3), 413147899Ssam EXTRACT_32BITS(tptr+7), 414147899Ssam vc_info_len); 415241235Sdelphij if (vc_info_len < 4) 416241235Sdelphij goto trunc; /* minimum 4, for the VC ID */ 417241235Sdelphij vc_info_len -= 4; /* subtract out the VC ID, giving the length of the interface parameters */ 418147899Ssam 419241235Sdelphij /* Skip past the fixed information and the VC ID */ 420147899Ssam tptr+=11; 421241235Sdelphij tlv_tlen-=11; 422241235Sdelphij TLV_TCHECK(vc_info_len); 423147899Ssam 424147899Ssam while (vc_info_len > 2) { 425147899Ssam vc_info_tlv_type = *tptr; 426147899Ssam vc_info_tlv_len = *(tptr+1); 427147899Ssam if (vc_info_tlv_len < 2) 428147899Ssam break; 429147899Ssam if (vc_info_len < vc_info_tlv_len) 430147899Ssam break; 431147899Ssam 432147899Ssam printf("\n\t\tInterface Parameter: %s (0x%02x), len %u", 433147899Ssam tok2str(ldp_fec_martini_ifparm_values,"Unknown",vc_info_tlv_type), 434147899Ssam vc_info_tlv_type, 435147899Ssam vc_info_tlv_len); 436147899Ssam 437147899Ssam switch(vc_info_tlv_type) { 438147899Ssam case LDP_FEC_MARTINI_IFPARM_MTU: 439147899Ssam printf(": %u",EXTRACT_16BITS(tptr+2)); 440147899Ssam break; 441147899Ssam 442147899Ssam case LDP_FEC_MARTINI_IFPARM_DESC: 443147899Ssam printf(": "); 444147899Ssam for (idx = 2; idx < vc_info_tlv_len; idx++) 445147899Ssam safeputchar(*(tptr+idx)); 446147899Ssam break; 447147899Ssam 448147899Ssam case LDP_FEC_MARTINI_IFPARM_VCCV: 449147899Ssam printf("\n\t\t Control Channels (0x%02x) = [%s]", 450147899Ssam *(tptr+2), 451147899Ssam bittok2str(ldp_fec_martini_ifparm_vccv_cc_values,"none",*(tptr+2))); 452147899Ssam printf("\n\t\t CV Types (0x%02x) = [%s]", 453147899Ssam *(tptr+3), 454147899Ssam bittok2str(ldp_fec_martini_ifparm_vccv_cv_values,"none",*(tptr+3))); 455147899Ssam break; 456147899Ssam 457147899Ssam default: 458147899Ssam print_unknown_data(tptr+2,"\n\t\t ",vc_info_tlv_len-2); 459147899Ssam break; 460147899Ssam } 461147899Ssam 462147899Ssam vc_info_len -= vc_info_tlv_len; 463147899Ssam tptr += vc_info_tlv_len; 464147899Ssam } 465146773Ssam break; 466146773Ssam } 467146773Ssam 468146773Ssam break; 469146773Ssam 470146773Ssam case LDP_TLV_GENERIC_LABEL: 471241235Sdelphij TLV_TCHECK(4); 472146773Ssam printf("\n\t Label: %u", EXTRACT_32BITS(tptr) & 0xfffff); 473146773Ssam break; 474146773Ssam 475146773Ssam case LDP_TLV_STATUS: 476241235Sdelphij TLV_TCHECK(8); 477146773Ssam ui = EXTRACT_32BITS(tptr); 478146773Ssam tptr+=4; 479146773Ssam printf("\n\t Status: 0x%02x, Flags: [%s and %s forward]", 480146773Ssam ui&0x3fffffff, 481146773Ssam ui&0x80000000 ? "Fatal error" : "Advisory Notification", 482146773Ssam ui&0x40000000 ? "do" : "don't"); 483146773Ssam ui = EXTRACT_32BITS(tptr); 484146773Ssam tptr+=4; 485146773Ssam if (ui) 486146773Ssam printf(", causing Message ID: 0x%08x", ui); 487146773Ssam break; 488146773Ssam 489146773Ssam case LDP_TLV_FT_SESSION: 490241235Sdelphij TLV_TCHECK(8); 491146773Ssam ft_flags = EXTRACT_16BITS(tptr); 492146773Ssam printf("\n\t Flags: [%sReconnect, %sSave State, %sAll-Label Protection, %s Checkpoint, %sRe-Learn State]", 493146773Ssam ft_flags&0x8000 ? "" : "No ", 494146773Ssam ft_flags&0x8 ? "" : "Don't ", 495146773Ssam ft_flags&0x4 ? "" : "No ", 496146773Ssam ft_flags&0x2 ? "Sequence Numbered Label" : "All Labels", 497146773Ssam ft_flags&0x1 ? "" : "Don't "); 498146773Ssam tptr+=4; 499146773Ssam ui = EXTRACT_32BITS(tptr); 500146773Ssam if (ui) 501146773Ssam printf(", Reconnect Timeout: %ums", ui); 502146773Ssam tptr+=4; 503146773Ssam ui = EXTRACT_32BITS(tptr); 504146773Ssam if (ui) 505146773Ssam printf(", Recovery Time: %ums", ui); 506146773Ssam break; 507146773Ssam 508190207Srpaulo case LDP_TLV_MTU: 509241235Sdelphij TLV_TCHECK(2); 510190207Srpaulo printf("\n\t MTU: %u", EXTRACT_16BITS(tptr)); 511190207Srpaulo break; 512146773Ssam 513190207Srpaulo 514127668Sbms /* 515127668Sbms * FIXME those are the defined TLVs that lack a decoder 516127668Sbms * you are welcome to contribute code ;-) 517127668Sbms */ 518127668Sbms 519127668Sbms case LDP_TLV_HOP_COUNT: 520127668Sbms case LDP_TLV_PATH_VECTOR: 521127668Sbms case LDP_TLV_ATM_LABEL: 522127668Sbms case LDP_TLV_FR_LABEL: 523127668Sbms case LDP_TLV_EXTD_STATUS: 524127668Sbms case LDP_TLV_RETURNED_PDU: 525127668Sbms case LDP_TLV_RETURNED_MSG: 526127668Sbms case LDP_TLV_ATM_SESSION_PARM: 527127668Sbms case LDP_TLV_FR_SESSION_PARM: 528127668Sbms case LDP_TLV_LABEL_REQUEST_MSG_ID: 529127668Sbms 530127668Sbms default: 531127668Sbms if (vflag <= 1) 532127668Sbms print_unknown_data(tptr,"\n\t ",tlv_tlen); 533127668Sbms break; 534127668Sbms } 535127668Sbms return(tlv_len+4); /* Type & Length fields not included */ 536147899Ssam 537147899Ssamtrunc: 538147899Ssam printf("\n\t\t packet exceeded snapshot"); 539147899Ssam return 0; 540241235Sdelphij 541241235Sdelphijbadtlv: 542241235Sdelphij printf("\n\t\t TLV contents go past end of TLV"); 543241235Sdelphij return(tlv_len+4); /* Type & Length fields not included */ 544127668Sbms} 545127668Sbms 546127668Sbmsvoid 547127668Sbmsldp_print(register const u_char *pptr, register u_int len) { 548127668Sbms 549147899Ssam int processed; 550147899Ssam while (len > (sizeof(struct ldp_common_header) + sizeof(struct ldp_msg_header))) { 551147899Ssam processed = ldp_msg_print(pptr); 552147899Ssam if (processed == 0) 553147899Ssam return; 554147899Ssam len -= processed; 555147899Ssam pptr += processed; 556147899Ssam } 557147899Ssam} 558147899Ssam 559147899Ssam 560147899Ssamint 561147899Ssamldp_msg_print(register const u_char *pptr) { 562147899Ssam 563127668Sbms const struct ldp_common_header *ldp_com_header; 564127668Sbms const struct ldp_msg_header *ldp_msg_header; 565127668Sbms const u_char *tptr,*msg_tptr; 566127668Sbms u_short tlen; 567147899Ssam u_short pdu_len,msg_len,msg_type,msg_tlen; 568127668Sbms int hexdump,processed; 569127668Sbms 570127668Sbms tptr=pptr; 571127668Sbms ldp_com_header = (const struct ldp_common_header *)pptr; 572127668Sbms TCHECK(*ldp_com_header); 573127668Sbms 574127668Sbms /* 575127668Sbms * Sanity checking of the header. 576127668Sbms */ 577127668Sbms if (EXTRACT_16BITS(&ldp_com_header->version) != LDP_VERSION) { 578147899Ssam printf("%sLDP version %u packet not supported", 579147899Ssam (vflag < 1) ? "" : "\n\t", 580127668Sbms EXTRACT_16BITS(&ldp_com_header->version)); 581147899Ssam return 0; 582127668Sbms } 583127668Sbms 584127668Sbms /* print the LSR-ID, label-space & length */ 585147899Ssam pdu_len = EXTRACT_16BITS(&ldp_com_header->pdu_length); 586147899Ssam printf("%sLDP, Label-Space-ID: %s:%u, pdu-length: %u", 587127668Sbms (vflag < 1) ? "" : "\n\t", 588127668Sbms ipaddr_string(&ldp_com_header->lsr_id), 589127668Sbms EXTRACT_16BITS(&ldp_com_header->label_space), 590147899Ssam pdu_len); 591127668Sbms 592127668Sbms /* bail out if non-verbose */ 593127668Sbms if (vflag < 1) 594147899Ssam return 0; 595127668Sbms 596127668Sbms /* ok they seem to want to know everything - lets fully decode it */ 597147899Ssam tlen=pdu_len; 598127668Sbms 599146773Ssam tptr += sizeof(const struct ldp_common_header); 600146773Ssam tlen -= sizeof(const struct ldp_common_header)-4; /* Type & Length fields not included */ 601127668Sbms 602127668Sbms while(tlen>0) { 603127668Sbms /* did we capture enough for fully decoding the msg header ? */ 604241235Sdelphij TCHECK2(*tptr, sizeof(struct ldp_msg_header)); 605127668Sbms 606127668Sbms ldp_msg_header = (const struct ldp_msg_header *)tptr; 607127668Sbms msg_len=EXTRACT_16BITS(ldp_msg_header->length); 608127668Sbms msg_type=LDP_MASK_MSG_TYPE(EXTRACT_16BITS(ldp_msg_header->type)); 609127668Sbms 610127668Sbms /* FIXME vendor private / experimental check */ 611127668Sbms printf("\n\t %s Message (0x%04x), length: %u, Message ID: 0x%08x, Flags: [%s if unknown]", 612127668Sbms tok2str(ldp_msg_values, 613127668Sbms "Unknown", 614127668Sbms msg_type), 615127668Sbms msg_type, 616127668Sbms msg_len, 617127668Sbms EXTRACT_32BITS(&ldp_msg_header->id), 618127668Sbms LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_msg_header->type)) ? "continue processing" : "ignore"); 619127668Sbms 620147899Ssam if (msg_len == 0) /* infinite loop protection */ 621147899Ssam return 0; 622147899Ssam 623127668Sbms msg_tptr=tptr+sizeof(struct ldp_msg_header); 624127668Sbms msg_tlen=msg_len-sizeof(struct ldp_msg_header)+4; /* Type & Length fields not included */ 625127668Sbms 626127668Sbms /* did we capture enough for fully decoding the message ? */ 627241235Sdelphij TCHECK2(*tptr, msg_len); 628127668Sbms hexdump=FALSE; 629127668Sbms 630127668Sbms switch(msg_type) { 631127668Sbms 632146773Ssam case LDP_MSG_NOTIF: 633127668Sbms case LDP_MSG_HELLO: 634146773Ssam case LDP_MSG_INIT: 635146773Ssam case LDP_MSG_KEEPALIVE: 636146773Ssam case LDP_MSG_ADDRESS: 637146773Ssam case LDP_MSG_LABEL_MAPPING: 638172683Smlaier case LDP_MSG_ADDRESS_WITHDRAW: 639172683Smlaier case LDP_MSG_LABEL_WITHDRAW: 640127668Sbms while(msg_tlen >= 4) { 641127668Sbms processed = ldp_tlv_print(msg_tptr); 642127668Sbms if (processed == 0) 643127668Sbms break; 644127668Sbms msg_tlen-=processed; 645127668Sbms msg_tptr+=processed; 646127668Sbms } 647127668Sbms break; 648127668Sbms 649127668Sbms /* 650127668Sbms * FIXME those are the defined messages that lack a decoder 651127668Sbms * you are welcome to contribute code ;-) 652127668Sbms */ 653127668Sbms 654127668Sbms case LDP_MSG_LABEL_REQUEST: 655127668Sbms case LDP_MSG_LABEL_RELEASE: 656127668Sbms case LDP_MSG_LABEL_ABORT_REQUEST: 657127668Sbms 658127668Sbms default: 659127668Sbms if (vflag <= 1) 660127668Sbms print_unknown_data(msg_tptr,"\n\t ",msg_tlen); 661127668Sbms break; 662127668Sbms } 663127668Sbms /* do we want to see an additionally hexdump ? */ 664127668Sbms if (vflag > 1 || hexdump==TRUE) 665228926Skevlo print_unknown_data(tptr+sizeof(struct ldp_msg_header),"\n\t ", 666127668Sbms msg_len); 667127668Sbms 668146773Ssam tptr += msg_len+4; 669146773Ssam tlen -= msg_len+4; 670127668Sbms } 671147899Ssam return pdu_len+4; 672127668Sbmstrunc: 673127668Sbms printf("\n\t\t packet exceeded snapshot"); 674147899Ssam return 0; 675127668Sbms} 676127668Sbms 677