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