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