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