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