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