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