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