1/* 2 * Redistribution and use in source and binary forms, with or without 3 * modification, are permitted provided that: (1) source code 4 * distributions retain the above copyright notice and this paragraph 5 * in its entirety, and (2) distributions including binary code include 6 * the above copyright notice and this paragraph in its entirety in 7 * the documentation or other materials provided with the distribution. 8 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 9 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT 10 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 11 * FOR A PARTICULAR PURPOSE. 12 * 13 * Original code by Hannes Gredler (hannes@juniper.net) 14 * and Steinar Haug (sthaug@nethelp.no) 15 */ 16 17#ifndef lint 18static const char rcsid[] _U_ = 19 "@(#) $Header: /tcpdump/master/tcpdump/print-ldp.c,v 1.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 55struct 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 88struct 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 114static 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 155static 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 RFC 4906; should probably be updated to RFC 4447 (e.g., VC -> PW) */ 184#define LDP_FEC_MARTINI_VC 0x80 185 186static 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 198static 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 */ 206static 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 */ 214static 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 221int ldp_msg_print(register const u_char *); 222int 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#define TLV_TCHECK(minlen) \ 242 TCHECK2(*tptr, minlen); if (tlv_tlen < minlen) goto badtlv; 243 244int 245ldp_tlv_print(register const u_char *tptr) { 246 247 struct ldp_tlv_header { 248 u_int8_t type[2]; 249 u_int8_t length[2]; 250 }; 251 252 const struct ldp_tlv_header *ldp_tlv_header; 253 u_short tlv_type,tlv_len,tlv_tlen,af,ft_flags; 254 u_char fec_type; 255 u_int ui,vc_info_len, vc_info_tlv_type, vc_info_tlv_len,idx; 256 char buf[100]; 257 int i; 258 259 ldp_tlv_header = (const struct ldp_tlv_header *)tptr; 260 tlv_len=EXTRACT_16BITS(ldp_tlv_header->length); 261 tlv_tlen=tlv_len; 262 tlv_type=LDP_MASK_TLV_TYPE(EXTRACT_16BITS(ldp_tlv_header->type)); 263 264 /* FIXME vendor private / experimental check */ 265 printf("\n\t %s TLV (0x%04x), length: %u, Flags: [%s and %s forward if unknown]", 266 tok2str(ldp_tlv_values, 267 "Unknown", 268 tlv_type), 269 tlv_type, 270 tlv_len, 271 LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "continue processing" : "ignore", 272 LDP_MASK_F_BIT(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "do" : "don't"); 273 274 tptr+=sizeof(struct ldp_tlv_header); 275 276 switch(tlv_type) { 277 278 case LDP_TLV_COMMON_HELLO: 279 TLV_TCHECK(4); 280 printf("\n\t Hold Time: %us, Flags: [%s Hello%s]", 281 EXTRACT_16BITS(tptr), 282 (EXTRACT_16BITS(tptr+2)&0x8000) ? "Targeted" : "Link", 283 (EXTRACT_16BITS(tptr+2)&0x4000) ? ", Request for targeted Hellos" : ""); 284 break; 285 286 case LDP_TLV_IPV4_TRANSPORT_ADDR: 287 TLV_TCHECK(4); 288 printf("\n\t IPv4 Transport Address: %s", ipaddr_string(tptr)); 289 break; 290#ifdef INET6 291 case LDP_TLV_IPV6_TRANSPORT_ADDR: 292 TLV_TCHECK(16); 293 printf("\n\t IPv6 Transport Address: %s", ip6addr_string(tptr)); 294 break; 295#endif 296 case LDP_TLV_CONFIG_SEQ_NUMBER: 297 TLV_TCHECK(4); 298 printf("\n\t Sequence Number: %u", EXTRACT_32BITS(tptr)); 299 break; 300 301 case LDP_TLV_ADDRESS_LIST: 302 TLV_TCHECK(LDP_TLV_ADDRESS_LIST_AFNUM_LEN); 303 af = EXTRACT_16BITS(tptr); 304 tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; 305 tlv_tlen -= LDP_TLV_ADDRESS_LIST_AFNUM_LEN; 306 printf("\n\t Address Family: %s, addresses", 307 tok2str(af_values, "Unknown (%u)", af)); 308 switch (af) { 309 case AFNUM_INET: 310 while(tlv_tlen >= sizeof(struct in_addr)) { 311 TCHECK2(*tptr, sizeof(struct in_addr)); 312 printf(" %s",ipaddr_string(tptr)); 313 tlv_tlen-=sizeof(struct in_addr); 314 tptr+=sizeof(struct in_addr); 315 } 316 break; 317#ifdef INET6 318 case AFNUM_INET6: 319 while(tlv_tlen >= sizeof(struct in6_addr)) { 320 TCHECK2(*tptr, sizeof(struct in6_addr)); 321 printf(" %s",ip6addr_string(tptr)); 322 tlv_tlen-=sizeof(struct in6_addr); 323 tptr+=sizeof(struct in6_addr); 324 } 325 break; 326#endif 327 default: 328 /* unknown AF */ 329 break; 330 } 331 break; 332 333 case LDP_TLV_COMMON_SESSION: 334 TLV_TCHECK(8); 335 printf("\n\t Version: %u, Keepalive: %us, Flags: [Downstream %s, Loop Detection %s]", 336 EXTRACT_16BITS(tptr), EXTRACT_16BITS(tptr+2), 337 (EXTRACT_16BITS(tptr+6)&0x8000) ? "On Demand" : "Unsolicited", 338 (EXTRACT_16BITS(tptr+6)&0x4000) ? "Enabled" : "Disabled" 339 ); 340 break; 341 342 case LDP_TLV_FEC: 343 TLV_TCHECK(1); 344 fec_type = *tptr; 345 printf("\n\t %s FEC (0x%02x)", 346 tok2str(ldp_fec_values, "Unknown", fec_type), 347 fec_type); 348 349 tptr+=1; 350 tlv_tlen-=1; 351 switch(fec_type) { 352 353 case LDP_FEC_WILDCARD: 354 break; 355 case LDP_FEC_PREFIX: 356 TLV_TCHECK(2); 357 af = EXTRACT_16BITS(tptr); 358 tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; 359 tlv_tlen-=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; 360 if (af == AFNUM_INET) { 361 i=decode_prefix4(tptr,tlv_tlen,buf,sizeof(buf)); 362 if (i == -2) 363 goto trunc; 364 if (i == -3) 365 printf(": IPv4 prefix (goes past end of TLV)"); 366 else if (i == -1) 367 printf(": IPv4 prefix (invalid length)"); 368 else 369 printf(": IPv4 prefix %s",buf); 370 } 371#ifdef INET6 372 else if (af == AFNUM_INET6) { 373 i=decode_prefix6(tptr,tlv_tlen,buf,sizeof(buf)); 374 if (i == -2) 375 goto trunc; 376 if (i == -3) 377 printf(": IPv4 prefix (goes past end of TLV)"); 378 else if (i == -1) 379 printf(": IPv6 prefix (invalid length)"); 380 else 381 printf(": IPv6 prefix %s",buf); 382 } 383#endif 384 else 385 printf(": Address family %u prefix", af); 386 break; 387 case LDP_FEC_HOSTADDRESS: 388 break; 389 case LDP_FEC_MARTINI_VC: 390 /* 391 * According to RFC 4908, the VC info Length field can be zero, 392 * in which case not only are there no interface parameters, 393 * there's no VC ID. 394 */ 395 TLV_TCHECK(7); 396 vc_info_len = *(tptr+2); 397 398 if (vc_info_len == 0) { 399 printf(": %s, %scontrol word, group-ID %u, VC-info-length: %u", 400 tok2str(l2vpn_encaps_values, "Unknown", EXTRACT_16BITS(tptr)&0x7fff), 401 EXTRACT_16BITS(tptr)&0x8000 ? "" : "no ", 402 EXTRACT_32BITS(tptr+3), 403 vc_info_len); 404 break; 405 } 406 407 /* Make sure we have the VC ID as well */ 408 TLV_TCHECK(11); 409 printf(": %s, %scontrol word, group-ID %u, VC-ID %u, VC-info-length: %u", 410 tok2str(l2vpn_encaps_values, "Unknown", EXTRACT_16BITS(tptr)&0x7fff), 411 EXTRACT_16BITS(tptr)&0x8000 ? "" : "no ", 412 EXTRACT_32BITS(tptr+3), 413 EXTRACT_32BITS(tptr+7), 414 vc_info_len); 415 if (vc_info_len < 4) 416 goto trunc; /* minimum 4, for the VC ID */ 417 vc_info_len -= 4; /* subtract out the VC ID, giving the length of the interface parameters */ 418 419 /* Skip past the fixed information and the VC ID */ 420 tptr+=11; 421 tlv_tlen-=11; 422 TLV_TCHECK(vc_info_len); 423 424 while (vc_info_len > 2) { 425 vc_info_tlv_type = *tptr; 426 vc_info_tlv_len = *(tptr+1); 427 if (vc_info_tlv_len < 2) 428 break; 429 if (vc_info_len < vc_info_tlv_len) 430 break; 431 432 printf("\n\t\tInterface Parameter: %s (0x%02x), len %u", 433 tok2str(ldp_fec_martini_ifparm_values,"Unknown",vc_info_tlv_type), 434 vc_info_tlv_type, 435 vc_info_tlv_len); 436 437 switch(vc_info_tlv_type) { 438 case LDP_FEC_MARTINI_IFPARM_MTU: 439 printf(": %u",EXTRACT_16BITS(tptr+2)); 440 break; 441 442 case LDP_FEC_MARTINI_IFPARM_DESC: 443 printf(": "); 444 for (idx = 2; idx < vc_info_tlv_len; idx++) 445 safeputchar(*(tptr+idx)); 446 break; 447 448 case LDP_FEC_MARTINI_IFPARM_VCCV: 449 printf("\n\t\t Control Channels (0x%02x) = [%s]", 450 *(tptr+2), 451 bittok2str(ldp_fec_martini_ifparm_vccv_cc_values,"none",*(tptr+2))); 452 printf("\n\t\t CV Types (0x%02x) = [%s]", 453 *(tptr+3), 454 bittok2str(ldp_fec_martini_ifparm_vccv_cv_values,"none",*(tptr+3))); 455 break; 456 457 default: 458 print_unknown_data(tptr+2,"\n\t\t ",vc_info_tlv_len-2); 459 break; 460 } 461 462 vc_info_len -= vc_info_tlv_len; 463 tptr += vc_info_tlv_len; 464 } 465 break; 466 } 467 468 break; 469 470 case LDP_TLV_GENERIC_LABEL: 471 TLV_TCHECK(4); 472 printf("\n\t Label: %u", EXTRACT_32BITS(tptr) & 0xfffff); 473 break; 474 475 case LDP_TLV_STATUS: 476 TLV_TCHECK(8); 477 ui = EXTRACT_32BITS(tptr); 478 tptr+=4; 479 printf("\n\t Status: 0x%02x, Flags: [%s and %s forward]", 480 ui&0x3fffffff, 481 ui&0x80000000 ? "Fatal error" : "Advisory Notification", 482 ui&0x40000000 ? "do" : "don't"); 483 ui = EXTRACT_32BITS(tptr); 484 tptr+=4; 485 if (ui) 486 printf(", causing Message ID: 0x%08x", ui); 487 break; 488 489 case LDP_TLV_FT_SESSION: 490 TLV_TCHECK(8); 491 ft_flags = EXTRACT_16BITS(tptr); 492 printf("\n\t Flags: [%sReconnect, %sSave State, %sAll-Label Protection, %s Checkpoint, %sRe-Learn State]", 493 ft_flags&0x8000 ? "" : "No ", 494 ft_flags&0x8 ? "" : "Don't ", 495 ft_flags&0x4 ? "" : "No ", 496 ft_flags&0x2 ? "Sequence Numbered Label" : "All Labels", 497 ft_flags&0x1 ? "" : "Don't "); 498 tptr+=4; 499 ui = EXTRACT_32BITS(tptr); 500 if (ui) 501 printf(", Reconnect Timeout: %ums", ui); 502 tptr+=4; 503 ui = EXTRACT_32BITS(tptr); 504 if (ui) 505 printf(", Recovery Time: %ums", ui); 506 break; 507 508 case LDP_TLV_MTU: 509 TLV_TCHECK(2); 510 printf("\n\t MTU: %u", EXTRACT_16BITS(tptr)); 511 break; 512 513 514 /* 515 * FIXME those are the defined TLVs that lack a decoder 516 * you are welcome to contribute code ;-) 517 */ 518 519 case LDP_TLV_HOP_COUNT: 520 case LDP_TLV_PATH_VECTOR: 521 case LDP_TLV_ATM_LABEL: 522 case LDP_TLV_FR_LABEL: 523 case LDP_TLV_EXTD_STATUS: 524 case LDP_TLV_RETURNED_PDU: 525 case LDP_TLV_RETURNED_MSG: 526 case LDP_TLV_ATM_SESSION_PARM: 527 case LDP_TLV_FR_SESSION_PARM: 528 case LDP_TLV_LABEL_REQUEST_MSG_ID: 529 530 default: 531 if (vflag <= 1) 532 print_unknown_data(tptr,"\n\t ",tlv_tlen); 533 break; 534 } 535 return(tlv_len+4); /* Type & Length fields not included */ 536 537trunc: 538 printf("\n\t\t packet exceeded snapshot"); 539 return 0; 540 541badtlv: 542 printf("\n\t\t TLV contents go past end of TLV"); 543 return(tlv_len+4); /* Type & Length fields not included */ 544} 545 546void 547ldp_print(register const u_char *pptr, register u_int len) { 548 549 int processed; 550 while (len > (sizeof(struct ldp_common_header) + sizeof(struct ldp_msg_header))) { 551 processed = ldp_msg_print(pptr); 552 if (processed == 0) 553 return; 554 len -= processed; 555 pptr += processed; 556 } 557} 558 559 560int 561ldp_msg_print(register const u_char *pptr) { 562 563 const struct ldp_common_header *ldp_com_header; 564 const struct ldp_msg_header *ldp_msg_header; 565 const u_char *tptr,*msg_tptr; 566 u_short tlen; 567 u_short pdu_len,msg_len,msg_type,msg_tlen; 568 int hexdump,processed; 569 570 tptr=pptr; 571 ldp_com_header = (const struct ldp_common_header *)pptr; 572 TCHECK(*ldp_com_header); 573 574 /* 575 * Sanity checking of the header. 576 */ 577 if (EXTRACT_16BITS(&ldp_com_header->version) != LDP_VERSION) { 578 printf("%sLDP version %u packet not supported", 579 (vflag < 1) ? "" : "\n\t", 580 EXTRACT_16BITS(&ldp_com_header->version)); 581 return 0; 582 } 583 584 /* print the LSR-ID, label-space & length */ 585 pdu_len = EXTRACT_16BITS(&ldp_com_header->pdu_length); 586 printf("%sLDP, Label-Space-ID: %s:%u, pdu-length: %u", 587 (vflag < 1) ? "" : "\n\t", 588 ipaddr_string(&ldp_com_header->lsr_id), 589 EXTRACT_16BITS(&ldp_com_header->label_space), 590 pdu_len); 591 592 /* bail out if non-verbose */ 593 if (vflag < 1) 594 return 0; 595 596 /* ok they seem to want to know everything - lets fully decode it */ 597 tlen=pdu_len; 598 599 tptr += sizeof(const struct ldp_common_header); 600 tlen -= sizeof(const struct ldp_common_header)-4; /* Type & Length fields not included */ 601 602 while(tlen>0) { 603 /* did we capture enough for fully decoding the msg header ? */ 604 TCHECK2(*tptr, sizeof(struct ldp_msg_header)); 605 606 ldp_msg_header = (const struct ldp_msg_header *)tptr; 607 msg_len=EXTRACT_16BITS(ldp_msg_header->length); 608 msg_type=LDP_MASK_MSG_TYPE(EXTRACT_16BITS(ldp_msg_header->type)); 609 610 /* FIXME vendor private / experimental check */ 611 printf("\n\t %s Message (0x%04x), length: %u, Message ID: 0x%08x, Flags: [%s if unknown]", 612 tok2str(ldp_msg_values, 613 "Unknown", 614 msg_type), 615 msg_type, 616 msg_len, 617 EXTRACT_32BITS(&ldp_msg_header->id), 618 LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_msg_header->type)) ? "continue processing" : "ignore"); 619 620 if (msg_len == 0) /* infinite loop protection */ 621 return 0; 622 623 msg_tptr=tptr+sizeof(struct ldp_msg_header); 624 msg_tlen=msg_len-sizeof(struct ldp_msg_header)+4; /* Type & Length fields not included */ 625 626 /* did we capture enough for fully decoding the message ? */ 627 TCHECK2(*tptr, msg_len); 628 hexdump=FALSE; 629 630 switch(msg_type) { 631 632 case LDP_MSG_NOTIF: 633 case LDP_MSG_HELLO: 634 case LDP_MSG_INIT: 635 case LDP_MSG_KEEPALIVE: 636 case LDP_MSG_ADDRESS: 637 case LDP_MSG_LABEL_MAPPING: 638 case LDP_MSG_ADDRESS_WITHDRAW: 639 case LDP_MSG_LABEL_WITHDRAW: 640 while(msg_tlen >= 4) { 641 processed = ldp_tlv_print(msg_tptr); 642 if (processed == 0) 643 break; 644 msg_tlen-=processed; 645 msg_tptr+=processed; 646 } 647 break; 648 649 /* 650 * FIXME those are the defined messages that lack a decoder 651 * you are welcome to contribute code ;-) 652 */ 653 654 case LDP_MSG_LABEL_REQUEST: 655 case LDP_MSG_LABEL_RELEASE: 656 case LDP_MSG_LABEL_ABORT_REQUEST: 657 658 default: 659 if (vflag <= 1) 660 print_unknown_data(msg_tptr,"\n\t ",msg_tlen); 661 break; 662 } 663 /* do we want to see an additionally hexdump ? */ 664 if (vflag > 1 || hexdump==TRUE) 665 print_unknown_data(tptr+sizeof(struct ldp_msg_header),"\n\t ", 666 msg_len); 667 668 tptr += msg_len+4; 669 tlen -= msg_len+4; 670 } 671 return pdu_len+4; 672trunc: 673 printf("\n\t\t packet exceeded snapshot"); 674 return 0; 675} 676 677