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