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