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