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