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