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.5 2014/11/20 03:05:03 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_msg_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 243 struct ldp_tlv_header { 244 uint8_t type[2]; 245 uint8_t length[2]; 246 }; 247 248 const struct ldp_tlv_header *ldp_tlv_header; 249 u_short tlv_type,tlv_len,tlv_tlen,af,ft_flags; 250 u_char fec_type; 251 u_int ui,vc_info_len, vc_info_tlv_type, vc_info_tlv_len,idx; 252 char buf[100]; 253 int i; 254 255 ldp_tlv_header = (const struct ldp_tlv_header *)tptr; 256 tlv_len=EXTRACT_16BITS(ldp_tlv_header->length); 257 tlv_tlen=tlv_len; 258 tlv_type=LDP_MASK_TLV_TYPE(EXTRACT_16BITS(ldp_tlv_header->type)); 259 260 /* FIXME vendor private / experimental check */ 261 ND_PRINT((ndo, "\n\t %s TLV (0x%04x), length: %u, Flags: [%s and %s forward if unknown]", 262 tok2str(ldp_tlv_values, 263 "Unknown", 264 tlv_type), 265 tlv_type, 266 tlv_len, 267 LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "continue processing" : "ignore", 268 LDP_MASK_F_BIT(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "do" : "don't")); 269 270 tptr+=sizeof(struct ldp_tlv_header); 271 272 switch(tlv_type) { 273 274 case LDP_TLV_COMMON_HELLO: 275 TLV_TCHECK(4); 276 ND_PRINT((ndo, "\n\t Hold Time: %us, Flags: [%s Hello%s]", 277 EXTRACT_16BITS(tptr), 278 (EXTRACT_16BITS(tptr+2)&0x8000) ? "Targeted" : "Link", 279 (EXTRACT_16BITS(tptr+2)&0x4000) ? ", Request for targeted Hellos" : "")); 280 break; 281 282 case LDP_TLV_IPV4_TRANSPORT_ADDR: 283 TLV_TCHECK(4); 284 ND_PRINT((ndo, "\n\t IPv4 Transport Address: %s", ipaddr_string(ndo, tptr))); 285 break; 286 #ifdef INET6 287 case LDP_TLV_IPV6_TRANSPORT_ADDR: 288 TLV_TCHECK(16); 289 ND_PRINT((ndo, "\n\t IPv6 Transport Address: %s", ip6addr_string(ndo, tptr))); 290 break; 291 #endif 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 #ifdef INET6 314 case AFNUM_INET6: 315 while(tlv_tlen >= sizeof(struct in6_addr)) { 316 ND_TCHECK2(*tptr, sizeof(struct in6_addr)); 317 ND_PRINT((ndo, " %s", ip6addr_string(ndo, tptr))); 318 tlv_tlen-=sizeof(struct in6_addr); 319 tptr+=sizeof(struct in6_addr); 320 } 321 break; 322 #endif 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 #ifdef INET6 368 else if (af == AFNUM_INET6) { 369 i=decode_prefix6(ndo, tptr, tlv_tlen, buf, sizeof(buf)); 370 if (i == -2) 371 goto trunc; 372 if (i == -3) 373 ND_PRINT((ndo, ": IPv4 prefix (goes past end of TLV)")); 374 else if (i == -1) 375 ND_PRINT((ndo, ": IPv6 prefix (invalid length)")); 376 else 377 ND_PRINT((ndo, ": IPv6 prefix %s", buf)); 378 } 379 #endif 380 else 381 ND_PRINT((ndo, ": Address family %u prefix", af)); 382 break; 383 case LDP_FEC_HOSTADDRESS: 384 break; 385 case LDP_FEC_MARTINI_VC: 386 /* 387 * According to RFC 4908, the VC info Length field can be zero, 388 * in which case not only are there no interface parameters, 389 * there's no VC ID. 390 */ 391 TLV_TCHECK(7); 392 vc_info_len = *(tptr+2); 393 394 if (vc_info_len == 0) { 395 ND_PRINT((ndo, ": %s, %scontrol word, group-ID %u, VC-info-length: %u", 396 tok2str(l2vpn_encaps_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(l2vpn_encaps_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 goto trunc; /* minimum 4, for the VC ID */ 413 vc_info_len -= 4; /* subtract out the VC ID, giving the length of the interface parameters */ 414 415 /* Skip past the fixed information and the VC ID */ 416 tptr+=11; 417 tlv_tlen-=11; 418 TLV_TCHECK(vc_info_len); 419 420 while (vc_info_len > 2) { 421 vc_info_tlv_type = *tptr; 422 vc_info_tlv_len = *(tptr+1); 423 if (vc_info_tlv_len < 2) 424 break; 425 if (vc_info_len < vc_info_tlv_len) 426 break; 427 428 ND_PRINT((ndo, "\n\t\tInterface Parameter: %s (0x%02x), len %u", 429 tok2str(ldp_fec_martini_ifparm_values,"Unknown",vc_info_tlv_type), 430 vc_info_tlv_type, 431 vc_info_tlv_len)); 432 433 switch(vc_info_tlv_type) { 434 case LDP_FEC_MARTINI_IFPARM_MTU: 435 ND_PRINT((ndo, ": %u", EXTRACT_16BITS(tptr+2))); 436 break; 437 438 case LDP_FEC_MARTINI_IFPARM_DESC: 439 ND_PRINT((ndo, ": ")); 440 for (idx = 2; idx < vc_info_tlv_len; idx++) 441 safeputchar(ndo, *(tptr + idx)); 442 break; 443 444 case LDP_FEC_MARTINI_IFPARM_VCCV: 445 ND_PRINT((ndo, "\n\t\t Control Channels (0x%02x) = [%s]", 446 *(tptr+2), 447 bittok2str(ldp_fec_martini_ifparm_vccv_cc_values, "none", *(tptr+2)))); 448 ND_PRINT((ndo, "\n\t\t CV Types (0x%02x) = [%s]", 449 *(tptr+3), 450 bittok2str(ldp_fec_martini_ifparm_vccv_cv_values, "none", *(tptr+3)))); 451 break; 452 453 default: 454 print_unknown_data(ndo, tptr+2, "\n\t\t ", vc_info_tlv_len-2); 455 break; 456 } 457 458 vc_info_len -= vc_info_tlv_len; 459 tptr += vc_info_tlv_len; 460 } 461 break; 462 } 463 464 break; 465 466 case LDP_TLV_GENERIC_LABEL: 467 TLV_TCHECK(4); 468 ND_PRINT((ndo, "\n\t Label: %u", EXTRACT_32BITS(tptr) & 0xfffff)); 469 break; 470 471 case LDP_TLV_STATUS: 472 TLV_TCHECK(8); 473 ui = EXTRACT_32BITS(tptr); 474 tptr+=4; 475 ND_PRINT((ndo, "\n\t Status: 0x%02x, Flags: [%s and %s forward]", 476 ui&0x3fffffff, 477 ui&0x80000000 ? "Fatal error" : "Advisory Notification", 478 ui&0x40000000 ? "do" : "don't")); 479 ui = EXTRACT_32BITS(tptr); 480 tptr+=4; 481 if (ui) 482 ND_PRINT((ndo, ", causing Message ID: 0x%08x", ui)); 483 break; 484 485 case LDP_TLV_FT_SESSION: 486 TLV_TCHECK(8); 487 ft_flags = EXTRACT_16BITS(tptr); 488 ND_PRINT((ndo, "\n\t Flags: [%sReconnect, %sSave State, %sAll-Label Protection, %s Checkpoint, %sRe-Learn State]", 489 ft_flags&0x8000 ? "" : "No ", 490 ft_flags&0x8 ? "" : "Don't ", 491 ft_flags&0x4 ? "" : "No ", 492 ft_flags&0x2 ? "Sequence Numbered Label" : "All Labels", 493 ft_flags&0x1 ? "" : "Don't ")); 494 tptr+=4; 495 ui = EXTRACT_32BITS(tptr); 496 if (ui) 497 ND_PRINT((ndo, ", Reconnect Timeout: %ums", ui)); 498 tptr+=4; 499 ui = EXTRACT_32BITS(tptr); 500 if (ui) 501 ND_PRINT((ndo, ", Recovery Time: %ums", ui)); 502 break; 503 504 case LDP_TLV_MTU: 505 TLV_TCHECK(2); 506 ND_PRINT((ndo, "\n\t MTU: %u", EXTRACT_16BITS(tptr))); 507 break; 508 509 510 /* 511 * FIXME those are the defined TLVs that lack a decoder 512 * you are welcome to contribute code ;-) 513 */ 514 515 case LDP_TLV_HOP_COUNT: 516 case LDP_TLV_PATH_VECTOR: 517 case LDP_TLV_ATM_LABEL: 518 case LDP_TLV_FR_LABEL: 519 case LDP_TLV_EXTD_STATUS: 520 case LDP_TLV_RETURNED_PDU: 521 case LDP_TLV_RETURNED_MSG: 522 case LDP_TLV_ATM_SESSION_PARM: 523 case LDP_TLV_FR_SESSION_PARM: 524 case LDP_TLV_LABEL_REQUEST_MSG_ID: 525 526 default: 527 if (ndo->ndo_vflag <= 1) 528 print_unknown_data(ndo, tptr, "\n\t ", tlv_tlen); 529 break; 530 } 531 return(tlv_len+4); /* Type & Length fields not included */ 532 533 trunc: 534 ND_PRINT((ndo, "\n\t\t packet exceeded snapshot")); 535 return 0; 536 537 badtlv: 538 ND_PRINT((ndo, "\n\t\t TLV contents go past end of TLV")); 539 return(tlv_len+4); /* Type & Length fields not included */ 540 } 541 542 void 543 ldp_print(netdissect_options *ndo, 544 register const u_char *pptr, register u_int len) { 545 546 int processed; 547 while (len > (sizeof(struct ldp_common_header) + sizeof(struct ldp_msg_header))) { 548 processed = ldp_msg_print(ndo, pptr); 549 if (processed == 0) 550 return; 551 len -= processed; 552 pptr += processed; 553 } 554 } 555 556 static int 557 ldp_msg_print(netdissect_options *ndo, 558 register const u_char *pptr) { 559 560 const struct ldp_common_header *ldp_com_header; 561 const struct ldp_msg_header *ldp_msg_header; 562 const u_char *tptr,*msg_tptr; 563 u_short tlen; 564 u_short pdu_len,msg_len,msg_type,msg_tlen; 565 int hexdump,processed; 566 567 tptr=pptr; 568 ldp_com_header = (const struct ldp_common_header *)pptr; 569 ND_TCHECK(*ldp_com_header); 570 571 /* 572 * Sanity checking of the header. 573 */ 574 if (EXTRACT_16BITS(&ldp_com_header->version) != LDP_VERSION) { 575 ND_PRINT((ndo, "%sLDP version %u packet not supported", 576 (ndo->ndo_vflag < 1) ? "" : "\n\t", 577 EXTRACT_16BITS(&ldp_com_header->version))); 578 return 0; 579 } 580 581 /* print the LSR-ID, label-space & length */ 582 pdu_len = EXTRACT_16BITS(&ldp_com_header->pdu_length); 583 ND_PRINT((ndo, "%sLDP, Label-Space-ID: %s:%u, pdu-length: %u", 584 (ndo->ndo_vflag < 1) ? "" : "\n\t", 585 ipaddr_string(ndo, &ldp_com_header->lsr_id), 586 EXTRACT_16BITS(&ldp_com_header->label_space), 587 pdu_len)); 588 589 /* bail out if non-verbose */ 590 if (ndo->ndo_vflag < 1) 591 return 0; 592 593 /* ok they seem to want to know everything - lets fully decode it */ 594 tlen=pdu_len; 595 596 tptr += sizeof(const struct ldp_common_header); 597 tlen -= sizeof(const struct ldp_common_header)-4; /* Type & Length fields not included */ 598 599 while(tlen>0) { 600 /* did we capture enough for fully decoding the msg header ? */ 601 ND_TCHECK2(*tptr, sizeof(struct ldp_msg_header)); 602 603 ldp_msg_header = (const struct ldp_msg_header *)tptr; 604 msg_len=EXTRACT_16BITS(ldp_msg_header->length); 605 msg_type=LDP_MASK_MSG_TYPE(EXTRACT_16BITS(ldp_msg_header->type)); 606 607 /* FIXME vendor private / experimental check */ 608 ND_PRINT((ndo, "\n\t %s Message (0x%04x), length: %u, Message ID: 0x%08x, Flags: [%s if unknown]", 609 tok2str(ldp_msg_values, 610 "Unknown", 611 msg_type), 612 msg_type, 613 msg_len, 614 EXTRACT_32BITS(&ldp_msg_header->id), 615 LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_msg_header->type)) ? "continue processing" : "ignore")); 616 617 if (msg_len == 0) /* infinite loop protection */ 618 return 0; 619 620 msg_tptr=tptr+sizeof(struct ldp_msg_header); 621 msg_tlen=msg_len-sizeof(struct ldp_msg_header)+4; /* Type & Length fields not included */ 622 623 /* did we capture enough for fully decoding the message ? */ 624 ND_TCHECK2(*tptr, msg_len); 625 hexdump=FALSE; 626 627 switch(msg_type) { 628 629 case LDP_MSG_NOTIF: 630 case LDP_MSG_HELLO: 631 case LDP_MSG_INIT: 632 case LDP_MSG_KEEPALIVE: 633 case LDP_MSG_ADDRESS: 634 case LDP_MSG_LABEL_MAPPING: 635 case LDP_MSG_ADDRESS_WITHDRAW: 636 case LDP_MSG_LABEL_WITHDRAW: 637 while(msg_tlen >= 4) { 638 processed = ldp_tlv_print(ndo, msg_tptr); 639 if (processed == 0) 640 break; 641 msg_tlen-=processed; 642 msg_tptr+=processed; 643 } 644 break; 645 646 /* 647 * FIXME those are the defined messages that lack a decoder 648 * you are welcome to contribute code ;-) 649 */ 650 651 case LDP_MSG_LABEL_REQUEST: 652 case LDP_MSG_LABEL_RELEASE: 653 case LDP_MSG_LABEL_ABORT_REQUEST: 654 655 default: 656 if (ndo->ndo_vflag <= 1) 657 print_unknown_data(ndo, msg_tptr, "\n\t ", msg_tlen); 658 break; 659 } 660 /* do we want to see an additionally hexdump ? */ 661 if (ndo->ndo_vflag > 1 || hexdump==TRUE) 662 print_unknown_data(ndo, tptr+sizeof(struct ldp_msg_header), "\n\t ", 663 msg_len); 664 665 tptr += msg_len+4; 666 tlen -= msg_len+4; 667 } 668 return pdu_len+4; 669 trunc: 670 ND_PRINT((ndo, "\n\t\t packet exceeded snapshot")); 671 return 0; 672 } 673 674 /* 675 * Local Variables: 676 * c-style: whitesmith 677 * c-basic-offset: 8 678 * End: 679 */ 680