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.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 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_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 155 static 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 draft-martini-l2circuit-trans-mpls-13.txt */ 184 #define LDP_FEC_MARTINI_VC 0x80 185 186 static 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 198 static 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 */ 206 static 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 */ 214 static 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 221 int ldp_msg_print(register const u_char *); 222 int 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 int 242 ldp_tlv_print(register const u_char *tptr) { 243 244 struct ldp_tlv_header { 245 u_int8_t type[2]; 246 u_int8_t length[2]; 247 }; 248 249 const struct ldp_tlv_header *ldp_tlv_header; 250 u_short tlv_type,tlv_len,tlv_tlen,af,ft_flags; 251 u_char fec_type; 252 u_int ui,vc_info_len, vc_info_tlv_type, vc_info_tlv_len,idx; 253 char buf[100]; 254 int i; 255 256 ldp_tlv_header = (const struct ldp_tlv_header *)tptr; 257 tlv_len=EXTRACT_16BITS(ldp_tlv_header->length); 258 tlv_tlen=tlv_len; 259 tlv_type=LDP_MASK_TLV_TYPE(EXTRACT_16BITS(ldp_tlv_header->type)); 260 261 /* FIXME vendor private / experimental check */ 262 printf("\n\t %s TLV (0x%04x), length: %u, Flags: [%s and %s forward if unknown]", 263 tok2str(ldp_tlv_values, 264 "Unknown", 265 tlv_type), 266 tlv_type, 267 tlv_len, 268 LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "continue processing" : "ignore", 269 LDP_MASK_F_BIT(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "do" : "don't"); 270 271 tptr+=sizeof(struct ldp_tlv_header); 272 273 switch(tlv_type) { 274 275 case LDP_TLV_COMMON_HELLO: 276 printf("\n\t Hold Time: %us, Flags: [%s Hello%s]", 277 EXTRACT_16BITS(tptr), 278 (EXTRACT_16BITS(tptr+2)&0x8000) ? "Targeted" : "Link", 279 (EXTRACT_16BITS(tptr+2)&0x4000) ? ", Request for targeted Hellos" : ""); 280 break; 281 282 case LDP_TLV_IPV4_TRANSPORT_ADDR: 283 printf("\n\t IPv4 Transport Address: %s", ipaddr_string(tptr)); 284 break; 285 #ifdef INET6 286 case LDP_TLV_IPV6_TRANSPORT_ADDR: 287 printf("\n\t IPv6 Transport Address: %s", ip6addr_string(tptr)); 288 break; 289 #endif 290 case LDP_TLV_CONFIG_SEQ_NUMBER: 291 printf("\n\t Sequence Number: %u", EXTRACT_32BITS(tptr)); 292 break; 293 294 case LDP_TLV_ADDRESS_LIST: 295 af = EXTRACT_16BITS(tptr); 296 tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; 297 tlv_tlen -= LDP_TLV_ADDRESS_LIST_AFNUM_LEN; 298 printf("\n\t Address Family: %s, addresses", 299 tok2str(af_values, "Unknown (%u)", af)); 300 switch (af) { 301 case AFNUM_INET: 302 while(tlv_tlen >= sizeof(struct in_addr)) { 303 printf(" %s",ipaddr_string(tptr)); 304 tlv_tlen-=sizeof(struct in_addr); 305 tptr+=sizeof(struct in_addr); 306 } 307 break; 308 #ifdef INET6 309 case AFNUM_INET6: 310 while(tlv_tlen >= sizeof(struct in6_addr)) { 311 printf(" %s",ip6addr_string(tptr)); 312 tlv_tlen-=sizeof(struct in6_addr); 313 tptr+=sizeof(struct in6_addr); 314 } 315 break; 316 #endif 317 default: 318 /* unknown AF */ 319 break; 320 } 321 break; 322 323 case LDP_TLV_COMMON_SESSION: 324 printf("\n\t Version: %u, Keepalive: %us, Flags: [Downstream %s, Loop Detection %s]", 325 EXTRACT_16BITS(tptr), EXTRACT_16BITS(tptr+2), 326 (EXTRACT_16BITS(tptr+6)&0x8000) ? "On Demand" : "Unsolicited", 327 (EXTRACT_16BITS(tptr+6)&0x4000) ? "Enabled" : "Disabled" 328 ); 329 break; 330 331 case LDP_TLV_FEC: 332 fec_type = *tptr; 333 printf("\n\t %s FEC (0x%02x)", 334 tok2str(ldp_fec_values, "Unknown", fec_type), 335 fec_type); 336 337 tptr+=1; 338 switch(fec_type) { 339 340 case LDP_FEC_WILDCARD: 341 break; 342 case LDP_FEC_PREFIX: 343 af = EXTRACT_16BITS(tptr); 344 tptr+=2; 345 if (af == AFNUM_INET) { 346 i=decode_prefix4(tptr,buf,sizeof(buf)); 347 printf(": IPv4 prefix %s",buf); 348 } 349 #ifdef INET6 350 else if (af == AFNUM_INET6) { 351 i=decode_prefix6(tptr,buf,sizeof(buf)); 352 printf(": IPv6 prefix %s",buf); 353 } 354 #endif 355 break; 356 case LDP_FEC_HOSTADDRESS: 357 break; 358 case LDP_FEC_MARTINI_VC: 359 if (!TTEST2(*tptr, 11)) 360 goto trunc; 361 vc_info_len = *(tptr+2); 362 363 printf(": %s, %scontrol word, group-ID %u, VC-ID %u, VC-info-length: %u", 364 tok2str(l2vpn_encaps_values, "Unknown", EXTRACT_16BITS(tptr)&0x7fff), 365 EXTRACT_16BITS(tptr)&0x8000 ? "" : "no ", 366 EXTRACT_32BITS(tptr+3), 367 EXTRACT_32BITS(tptr+7), 368 vc_info_len); 369 370 if (vc_info_len == 0) /* infinite loop protection */ 371 break; 372 373 tptr+=11; 374 if (!TTEST2(*tptr, vc_info_len)) 375 goto trunc; 376 377 while (vc_info_len > 2) { 378 vc_info_tlv_type = *tptr; 379 vc_info_tlv_len = *(tptr+1); 380 if (vc_info_tlv_len < 2) 381 break; 382 if (vc_info_len < vc_info_tlv_len) 383 break; 384 385 printf("\n\t\tInterface Parameter: %s (0x%02x), len %u", 386 tok2str(ldp_fec_martini_ifparm_values,"Unknown",vc_info_tlv_type), 387 vc_info_tlv_type, 388 vc_info_tlv_len); 389 390 switch(vc_info_tlv_type) { 391 case LDP_FEC_MARTINI_IFPARM_MTU: 392 printf(": %u",EXTRACT_16BITS(tptr+2)); 393 break; 394 395 case LDP_FEC_MARTINI_IFPARM_DESC: 396 printf(": "); 397 for (idx = 2; idx < vc_info_tlv_len; idx++) 398 safeputchar(*(tptr+idx)); 399 break; 400 401 case LDP_FEC_MARTINI_IFPARM_VCCV: 402 printf("\n\t\t Control Channels (0x%02x) = [%s]", 403 *(tptr+2), 404 bittok2str(ldp_fec_martini_ifparm_vccv_cc_values,"none",*(tptr+2))); 405 printf("\n\t\t CV Types (0x%02x) = [%s]", 406 *(tptr+3), 407 bittok2str(ldp_fec_martini_ifparm_vccv_cv_values,"none",*(tptr+3))); 408 break; 409 410 default: 411 print_unknown_data(tptr+2,"\n\t\t ",vc_info_tlv_len-2); 412 break; 413 } 414 415 vc_info_len -= vc_info_tlv_len; 416 tptr += vc_info_tlv_len; 417 } 418 break; 419 } 420 421 break; 422 423 case LDP_TLV_GENERIC_LABEL: 424 printf("\n\t Label: %u", EXTRACT_32BITS(tptr) & 0xfffff); 425 break; 426 427 case LDP_TLV_STATUS: 428 ui = EXTRACT_32BITS(tptr); 429 tptr+=4; 430 printf("\n\t Status: 0x%02x, Flags: [%s and %s forward]", 431 ui&0x3fffffff, 432 ui&0x80000000 ? "Fatal error" : "Advisory Notification", 433 ui&0x40000000 ? "do" : "don't"); 434 ui = EXTRACT_32BITS(tptr); 435 tptr+=4; 436 if (ui) 437 printf(", causing Message ID: 0x%08x", ui); 438 break; 439 440 case LDP_TLV_FT_SESSION: 441 ft_flags = EXTRACT_16BITS(tptr); 442 printf("\n\t Flags: [%sReconnect, %sSave State, %sAll-Label Protection, %s Checkpoint, %sRe-Learn State]", 443 ft_flags&0x8000 ? "" : "No ", 444 ft_flags&0x8 ? "" : "Don't ", 445 ft_flags&0x4 ? "" : "No ", 446 ft_flags&0x2 ? "Sequence Numbered Label" : "All Labels", 447 ft_flags&0x1 ? "" : "Don't "); 448 tptr+=4; 449 ui = EXTRACT_32BITS(tptr); 450 if (ui) 451 printf(", Reconnect Timeout: %ums", ui); 452 tptr+=4; 453 ui = EXTRACT_32BITS(tptr); 454 if (ui) 455 printf(", Recovery Time: %ums", ui); 456 break; 457 458 case LDP_TLV_MTU: 459 printf("\n\t MTU: %u", EXTRACT_16BITS(tptr)); 460 break; 461 462 463 /* 464 * FIXME those are the defined TLVs that lack a decoder 465 * you are welcome to contribute code ;-) 466 */ 467 468 case LDP_TLV_HOP_COUNT: 469 case LDP_TLV_PATH_VECTOR: 470 case LDP_TLV_ATM_LABEL: 471 case LDP_TLV_FR_LABEL: 472 case LDP_TLV_EXTD_STATUS: 473 case LDP_TLV_RETURNED_PDU: 474 case LDP_TLV_RETURNED_MSG: 475 case LDP_TLV_ATM_SESSION_PARM: 476 case LDP_TLV_FR_SESSION_PARM: 477 case LDP_TLV_LABEL_REQUEST_MSG_ID: 478 479 default: 480 if (vflag <= 1) 481 print_unknown_data(tptr,"\n\t ",tlv_tlen); 482 break; 483 } 484 return(tlv_len+4); /* Type & Length fields not included */ 485 486 trunc: 487 printf("\n\t\t packet exceeded snapshot"); 488 return 0; 489 } 490 491 void 492 ldp_print(register const u_char *pptr, register u_int len) { 493 494 int processed; 495 while (len > (sizeof(struct ldp_common_header) + sizeof(struct ldp_msg_header))) { 496 processed = ldp_msg_print(pptr); 497 if (processed == 0) 498 return; 499 len -= processed; 500 pptr += processed; 501 } 502 } 503 504 505 int 506 ldp_msg_print(register const u_char *pptr) { 507 508 const struct ldp_common_header *ldp_com_header; 509 const struct ldp_msg_header *ldp_msg_header; 510 const u_char *tptr,*msg_tptr; 511 u_short tlen; 512 u_short pdu_len,msg_len,msg_type,msg_tlen; 513 int hexdump,processed; 514 515 tptr=pptr; 516 ldp_com_header = (const struct ldp_common_header *)pptr; 517 TCHECK(*ldp_com_header); 518 519 /* 520 * Sanity checking of the header. 521 */ 522 if (EXTRACT_16BITS(&ldp_com_header->version) != LDP_VERSION) { 523 printf("%sLDP version %u packet not supported", 524 (vflag < 1) ? "" : "\n\t", 525 EXTRACT_16BITS(&ldp_com_header->version)); 526 return 0; 527 } 528 529 /* print the LSR-ID, label-space & length */ 530 pdu_len = EXTRACT_16BITS(&ldp_com_header->pdu_length); 531 printf("%sLDP, Label-Space-ID: %s:%u, pdu-length: %u", 532 (vflag < 1) ? "" : "\n\t", 533 ipaddr_string(&ldp_com_header->lsr_id), 534 EXTRACT_16BITS(&ldp_com_header->label_space), 535 pdu_len); 536 537 /* bail out if non-verbose */ 538 if (vflag < 1) 539 return 0; 540 541 /* ok they seem to want to know everything - lets fully decode it */ 542 tlen=pdu_len; 543 544 tptr += sizeof(const struct ldp_common_header); 545 tlen -= sizeof(const struct ldp_common_header)-4; /* Type & Length fields not included */ 546 547 while(tlen>0) { 548 /* did we capture enough for fully decoding the msg header ? */ 549 if (!TTEST2(*tptr, sizeof(struct ldp_msg_header))) 550 goto trunc; 551 552 ldp_msg_header = (const struct ldp_msg_header *)tptr; 553 msg_len=EXTRACT_16BITS(ldp_msg_header->length); 554 msg_type=LDP_MASK_MSG_TYPE(EXTRACT_16BITS(ldp_msg_header->type)); 555 556 /* FIXME vendor private / experimental check */ 557 printf("\n\t %s Message (0x%04x), length: %u, Message ID: 0x%08x, Flags: [%s if unknown]", 558 tok2str(ldp_msg_values, 559 "Unknown", 560 msg_type), 561 msg_type, 562 msg_len, 563 EXTRACT_32BITS(&ldp_msg_header->id), 564 LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_msg_header->type)) ? "continue processing" : "ignore"); 565 566 if (msg_len == 0) /* infinite loop protection */ 567 return 0; 568 569 msg_tptr=tptr+sizeof(struct ldp_msg_header); 570 msg_tlen=msg_len-sizeof(struct ldp_msg_header)+4; /* Type & Length fields not included */ 571 572 /* did we capture enough for fully decoding the message ? */ 573 if (!TTEST2(*tptr, msg_len)) 574 goto trunc; 575 hexdump=FALSE; 576 577 switch(msg_type) { 578 579 case LDP_MSG_NOTIF: 580 case LDP_MSG_HELLO: 581 case LDP_MSG_INIT: 582 case LDP_MSG_KEEPALIVE: 583 case LDP_MSG_ADDRESS: 584 case LDP_MSG_LABEL_MAPPING: 585 case LDP_MSG_ADDRESS_WITHDRAW: 586 case LDP_MSG_LABEL_WITHDRAW: 587 while(msg_tlen >= 4) { 588 processed = ldp_tlv_print(msg_tptr); 589 if (processed == 0) 590 break; 591 msg_tlen-=processed; 592 msg_tptr+=processed; 593 } 594 break; 595 596 /* 597 * FIXME those are the defined messages that lack a decoder 598 * you are welcome to contribute code ;-) 599 */ 600 601 case LDP_MSG_LABEL_REQUEST: 602 case LDP_MSG_LABEL_RELEASE: 603 case LDP_MSG_LABEL_ABORT_REQUEST: 604 605 default: 606 if (vflag <= 1) 607 print_unknown_data(msg_tptr,"\n\t ",msg_tlen); 608 break; 609 } 610 /* do we want to see an additionally hexdump ? */ 611 if (vflag > 1 || hexdump==TRUE) 612 print_unknown_data(tptr+sizeof(sizeof(struct ldp_msg_header)),"\n\t ", 613 msg_len); 614 615 tptr += msg_len+4; 616 tlen -= msg_len+4; 617 } 618 return pdu_len+4; 619 trunc: 620 printf("\n\t\t packet exceeded snapshot"); 621 return 0; 622 } 623 624