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 #ifndef lint 18 static const char rcsid[] _U_ = 19 "@(#) $Header: /tcpdump/master/tcpdump/print-ldp.c,v 1.8 2004/06/15 09:42:42 hannes Exp $"; 20 #endif 21 22 #ifdef HAVE_CONFIG_H 23 #include "config.h" 24 #endif 25 26 #include <tcpdump-stdinc.h> 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <string.h> 31 32 #include "interface.h" 33 #include "decode_prefix.h" 34 #include "extract.h" 35 #include "addrtoname.h" 36 37 #include "l2vpn.h" 38 39 /* 40 * ldp common header 41 * 42 * 0 1 2 3 43 * 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 44 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 45 * | Version | PDU Length | 46 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 47 * | LDP Identifier | 48 * + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 49 * | | 50 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 51 * 52 */ 53 54 struct ldp_common_header { 55 u_int8_t version[2]; 56 u_int8_t pdu_length[2]; 57 u_int8_t lsr_id[4]; 58 u_int8_t label_space[2]; 59 }; 60 61 #define LDP_VERSION 1 62 63 /* 64 * ldp message header 65 * 66 * 0 1 2 3 67 * 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 68 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 69 * |U| Message Type | Message Length | 70 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 71 * | Message ID | 72 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 73 * | | 74 * + + 75 * | Mandatory Parameters | 76 * + + 77 * | | 78 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 79 * | | 80 * + + 81 * | Optional Parameters | 82 * + + 83 * | | 84 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 85 */ 86 87 struct ldp_msg_header { 88 u_int8_t type[2]; 89 u_int8_t length[2]; 90 u_int8_t id[4]; 91 }; 92 93 #define LDP_MASK_MSG_TYPE(x) ((x)&0x7fff) 94 #define LDP_MASK_U_BIT(x) ((x)&0x8000) 95 96 #define LDP_MSG_NOTIF 0x0001 97 #define LDP_MSG_HELLO 0x0100 98 #define LDP_MSG_INIT 0x0200 99 #define LDP_MSG_KEEPALIVE 0x0201 100 #define LDP_MSG_ADDRESS 0x0300 101 #define LDP_MSG_ADDRESS_WITHDRAW 0x0301 102 #define LDP_MSG_LABEL_MAPPING 0x0400 103 #define LDP_MSG_LABEL_REQUEST 0x0401 104 #define LDP_MSG_LABEL_WITHDRAW 0x0402 105 #define LDP_MSG_LABEL_RELEASE 0x0403 106 #define LDP_MSG_LABEL_ABORT_REQUEST 0x0404 107 108 #define LDP_VENDOR_PRIVATE_MIN 0x3e00 109 #define LDP_VENDOR_PRIVATE_MAX 0x3eff 110 #define LDP_EXPERIMENTAL_MIN 0x3f00 111 #define LDP_EXPERIMENTAL_MAX 0x3fff 112 113 static const struct tok ldp_msg_values[] = { 114 { LDP_MSG_NOTIF, "Notification" }, 115 { LDP_MSG_HELLO, "Hello" }, 116 { LDP_MSG_INIT, "Initialization" }, 117 { LDP_MSG_KEEPALIVE, "Keepalive" }, 118 { LDP_MSG_ADDRESS, "Address" }, 119 { LDP_MSG_ADDRESS_WITHDRAW, "Address Widthdraw" }, 120 { LDP_MSG_LABEL_MAPPING, "Label Mapping" }, 121 { LDP_MSG_LABEL_REQUEST, "Label Request" }, 122 { LDP_MSG_LABEL_WITHDRAW, "Label Withdraw" }, 123 { LDP_MSG_LABEL_RELEASE, "Label Release" }, 124 { LDP_MSG_LABEL_ABORT_REQUEST, "Label Abort Request" }, 125 { 0, NULL} 126 }; 127 128 #define LDP_MASK_TLV_TYPE(x) ((x)&0x3fff) 129 #define LDP_MASK_F_BIT(x) ((x)&0x4000) 130 131 #define LDP_TLV_FEC 0x0100 132 #define LDP_TLV_ADDRESS_LIST 0x0101 133 #define LDP_TLV_HOP_COUNT 0x0103 134 #define LDP_TLV_PATH_VECTOR 0x0104 135 #define LDP_TLV_GENERIC_LABEL 0x0200 136 #define LDP_TLV_ATM_LABEL 0x0201 137 #define LDP_TLV_FR_LABEL 0x0202 138 #define LDP_TLV_STATUS 0x0300 139 #define LDP_TLV_EXTD_STATUS 0x0301 140 #define LDP_TLV_RETURNED_PDU 0x0302 141 #define LDP_TLV_RETURNED_MSG 0x0303 142 #define LDP_TLV_COMMON_HELLO 0x0400 143 #define LDP_TLV_IPV4_TRANSPORT_ADDR 0x0401 144 #define LDP_TLV_CONFIG_SEQ_NUMBER 0x0402 145 #define LDP_TLV_IPV6_TRANSPORT_ADDR 0x0403 146 #define LDP_TLV_COMMON_SESSION 0x0500 147 #define LDP_TLV_ATM_SESSION_PARM 0x0501 148 #define LDP_TLV_FR_SESSION_PARM 0x0502 149 #define LDP_TLV_FT_SESSION 0x0503 150 #define LDP_TLV_LABEL_REQUEST_MSG_ID 0x0600 151 152 static 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 { 0, NULL} 174 }; 175 176 #define LDP_FEC_WILDCARD 0x01 177 #define LDP_FEC_PREFIX 0x02 178 #define LDP_FEC_HOSTADDRESS 0x03 179 /* From draft-martini-l2circuit-trans-mpls-13.txt */ 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 /* RFC1700 address family numbers, same definition in print-bgp.c */ 191 #define AFNUM_INET 1 192 #define AFNUM_INET6 2 193 194 #define FALSE 0 195 #define TRUE 1 196 197 int ldp_tlv_print(register const u_char *); 198 199 /* 200 * ldp tlv header 201 * 202 * 0 1 2 3 203 * 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 204 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 205 * |U|F| Type | Length | 206 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 207 * | | 208 * | Value | 209 * ~ ~ 210 * | | 211 * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 212 * | | 213 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 214 */ 215 216 int 217 ldp_tlv_print(register const u_char *tptr) { 218 219 struct ldp_tlv_header { 220 u_int8_t type[2]; 221 u_int8_t length[2]; 222 }; 223 224 const struct ldp_tlv_header *ldp_tlv_header; 225 u_short tlv_type,tlv_len,tlv_tlen,af,ft_flags; 226 u_char fec_type; 227 u_int ui; 228 char buf[100]; 229 int i; 230 231 ldp_tlv_header = (const struct ldp_tlv_header *)tptr; 232 tlv_len=EXTRACT_16BITS(ldp_tlv_header->length); 233 tlv_tlen=tlv_len; 234 tlv_type=LDP_MASK_TLV_TYPE(EXTRACT_16BITS(ldp_tlv_header->type)); 235 236 /* FIXME vendor private / experimental check */ 237 printf("\n\t %s TLV (0x%04x), length: %u, Flags: [%s and %s forward if unknown]", 238 tok2str(ldp_tlv_values, 239 "Unknown", 240 tlv_type), 241 tlv_type, 242 tlv_len, 243 LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "continue processing" : "ignore", 244 LDP_MASK_F_BIT(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "do" : "don't"); 245 246 tptr+=sizeof(struct ldp_tlv_header); 247 248 switch(tlv_type) { 249 250 case LDP_TLV_COMMON_HELLO: 251 printf("\n\t Hold Time: %us, Flags: [%s Hello%s]", 252 EXTRACT_16BITS(tptr), 253 (EXTRACT_16BITS(tptr+2)&0x8000) ? "Targeted" : "Link", 254 (EXTRACT_16BITS(tptr+2)&0x4000) ? ", Request for targeted Hellos" : ""); 255 break; 256 257 case LDP_TLV_IPV4_TRANSPORT_ADDR: 258 printf("\n\t IPv4 Transport Address: %s", ipaddr_string(tptr)); 259 break; 260 #ifdef INET6 261 case LDP_TLV_IPV6_TRANSPORT_ADDR: 262 printf("\n\t IPv6 Transport Address: %s", ip6addr_string(tptr)); 263 break; 264 #endif 265 case LDP_TLV_CONFIG_SEQ_NUMBER: 266 printf("\n\t Sequence Number: %u", EXTRACT_32BITS(tptr)); 267 break; 268 269 case LDP_TLV_ADDRESS_LIST: 270 af = EXTRACT_16BITS(tptr); 271 tptr+=2; 272 printf("\n\t Adress Family: "); 273 if (af == AFNUM_INET) { 274 printf("IPv4, addresses:"); 275 for (i=0; i<(tlv_tlen-2)/4; i++) { 276 printf(" %s",ipaddr_string(tptr)); 277 tptr+=4; 278 } 279 } 280 #ifdef INET6 281 else if (af == AFNUM_INET6) { 282 printf("IPv6, addresses:"); 283 for (i=0; i<(tlv_tlen-2)/16; i++) { 284 printf(" %s",ip6addr_string(tptr)); 285 tptr+=16; 286 } 287 } 288 #endif 289 break; 290 291 case LDP_TLV_COMMON_SESSION: 292 printf("\n\t Version: %u, Keepalive: %us, Flags: [Downstream %s, Loop Detection %s]", 293 EXTRACT_16BITS(tptr), EXTRACT_16BITS(tptr+2), 294 (EXTRACT_16BITS(tptr+6)&0x8000) ? "On Demand" : "Unsolicited", 295 (EXTRACT_16BITS(tptr+6)&0x4000) ? "Enabled" : "Disabled" 296 ); 297 break; 298 299 case LDP_TLV_FEC: 300 fec_type = *tptr; 301 printf("\n\t %s FEC (0x%02x)", 302 tok2str(ldp_fec_values, "Unknown", fec_type), 303 fec_type); 304 305 tptr+=1; 306 switch(fec_type) { 307 308 case LDP_FEC_WILDCARD: 309 break; 310 case LDP_FEC_PREFIX: 311 af = EXTRACT_16BITS(tptr); 312 tptr+=2; 313 if (af == AFNUM_INET) { 314 i=decode_prefix4(tptr,buf,sizeof(buf)); 315 printf(": IPv4 prefix %s",buf); 316 } 317 #ifdef INET6 318 else if (af == AFNUM_INET6) { 319 i=decode_prefix6(tptr,buf,sizeof(buf)); 320 printf(": IPv6 prefix %s",buf); 321 } 322 #endif 323 break; 324 case LDP_FEC_HOSTADDRESS: 325 break; 326 case LDP_FEC_MARTINI_VC: 327 printf(": %s, %scontrol word, VC %u", 328 tok2str(l2vpn_encaps_values, "Unknown", EXTRACT_16BITS(tptr)&0x7fff), 329 EXTRACT_16BITS(tptr)&0x8000 ? "" : "no ", 330 EXTRACT_32BITS(tptr+7)); 331 break; 332 } 333 334 break; 335 336 case LDP_TLV_GENERIC_LABEL: 337 printf("\n\t Label: %u", EXTRACT_32BITS(tptr) & 0xfffff); 338 break; 339 340 case LDP_TLV_STATUS: 341 ui = EXTRACT_32BITS(tptr); 342 tptr+=4; 343 printf("\n\t Status: 0x%02x, Flags: [%s and %s forward]", 344 ui&0x3fffffff, 345 ui&0x80000000 ? "Fatal error" : "Advisory Notification", 346 ui&0x40000000 ? "do" : "don't"); 347 ui = EXTRACT_32BITS(tptr); 348 tptr+=4; 349 if (ui) 350 printf(", causing Message ID: 0x%08x", ui); 351 break; 352 353 case LDP_TLV_FT_SESSION: 354 ft_flags = EXTRACT_16BITS(tptr); 355 printf("\n\t Flags: [%sReconnect, %sSave State, %sAll-Label Protection, %s Checkpoint, %sRe-Learn State]", 356 ft_flags&0x8000 ? "" : "No ", 357 ft_flags&0x8 ? "" : "Don't ", 358 ft_flags&0x4 ? "" : "No ", 359 ft_flags&0x2 ? "Sequence Numbered Label" : "All Labels", 360 ft_flags&0x1 ? "" : "Don't "); 361 tptr+=4; 362 ui = EXTRACT_32BITS(tptr); 363 if (ui) 364 printf(", Reconnect Timeout: %ums", ui); 365 tptr+=4; 366 ui = EXTRACT_32BITS(tptr); 367 if (ui) 368 printf(", Recovery Time: %ums", ui); 369 break; 370 371 372 /* 373 * FIXME those are the defined TLVs that lack a decoder 374 * you are welcome to contribute code ;-) 375 */ 376 377 case LDP_TLV_HOP_COUNT: 378 case LDP_TLV_PATH_VECTOR: 379 case LDP_TLV_ATM_LABEL: 380 case LDP_TLV_FR_LABEL: 381 case LDP_TLV_EXTD_STATUS: 382 case LDP_TLV_RETURNED_PDU: 383 case LDP_TLV_RETURNED_MSG: 384 case LDP_TLV_ATM_SESSION_PARM: 385 case LDP_TLV_FR_SESSION_PARM: 386 case LDP_TLV_LABEL_REQUEST_MSG_ID: 387 388 default: 389 if (vflag <= 1) 390 print_unknown_data(tptr,"\n\t ",tlv_tlen); 391 break; 392 } 393 return(tlv_len+4); /* Type & Length fields not included */ 394 } 395 396 void 397 ldp_print(register const u_char *pptr, register u_int len) { 398 399 const struct ldp_common_header *ldp_com_header; 400 const struct ldp_msg_header *ldp_msg_header; 401 const u_char *tptr,*msg_tptr; 402 u_short tlen; 403 u_short msg_len,msg_type,msg_tlen; 404 int hexdump,processed; 405 406 tptr=pptr; 407 ldp_com_header = (const struct ldp_common_header *)pptr; 408 TCHECK(*ldp_com_header); 409 410 /* 411 * Sanity checking of the header. 412 */ 413 if (EXTRACT_16BITS(&ldp_com_header->version) != LDP_VERSION) { 414 printf("LDP version %u packet not supported", 415 EXTRACT_16BITS(&ldp_com_header->version)); 416 return; 417 } 418 419 /* print the LSR-ID, label-space & length */ 420 printf("%sLDP, Label-Space-ID: %s:%u, length: %u", 421 (vflag < 1) ? "" : "\n\t", 422 ipaddr_string(&ldp_com_header->lsr_id), 423 EXTRACT_16BITS(&ldp_com_header->label_space), 424 len); 425 426 /* bail out if non-verbose */ 427 if (vflag < 1) 428 return; 429 430 /* ok they seem to want to know everything - lets fully decode it */ 431 tlen=EXTRACT_16BITS(ldp_com_header->pdu_length); 432 433 tptr += sizeof(const struct ldp_common_header); 434 tlen -= sizeof(const struct ldp_common_header)-4; /* Type & Length fields not included */ 435 436 while(tlen>0) { 437 /* did we capture enough for fully decoding the msg header ? */ 438 if (!TTEST2(*tptr, sizeof(struct ldp_msg_header))) 439 goto trunc; 440 441 ldp_msg_header = (const struct ldp_msg_header *)tptr; 442 msg_len=EXTRACT_16BITS(ldp_msg_header->length); 443 msg_type=LDP_MASK_MSG_TYPE(EXTRACT_16BITS(ldp_msg_header->type)); 444 445 /* FIXME vendor private / experimental check */ 446 printf("\n\t %s Message (0x%04x), length: %u, Message ID: 0x%08x, Flags: [%s if unknown]", 447 tok2str(ldp_msg_values, 448 "Unknown", 449 msg_type), 450 msg_type, 451 msg_len, 452 EXTRACT_32BITS(&ldp_msg_header->id), 453 LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_msg_header->type)) ? "continue processing" : "ignore"); 454 455 msg_tptr=tptr+sizeof(struct ldp_msg_header); 456 msg_tlen=msg_len-sizeof(struct ldp_msg_header)+4; /* Type & Length fields not included */ 457 458 /* did we capture enough for fully decoding the message ? */ 459 if (!TTEST2(*tptr, msg_len)) 460 goto trunc; 461 hexdump=FALSE; 462 463 switch(msg_type) { 464 465 case LDP_MSG_NOTIF: 466 case LDP_MSG_HELLO: 467 case LDP_MSG_INIT: 468 case LDP_MSG_KEEPALIVE: 469 case LDP_MSG_ADDRESS: 470 case LDP_MSG_LABEL_MAPPING: 471 while(msg_tlen >= 4) { 472 processed = ldp_tlv_print(msg_tptr); 473 if (processed == 0) 474 break; 475 msg_tlen-=processed; 476 msg_tptr+=processed; 477 } 478 break; 479 480 /* 481 * FIXME those are the defined messages that lack a decoder 482 * you are welcome to contribute code ;-) 483 */ 484 485 case LDP_MSG_ADDRESS_WITHDRAW: 486 case LDP_MSG_LABEL_REQUEST: 487 case LDP_MSG_LABEL_WITHDRAW: 488 case LDP_MSG_LABEL_RELEASE: 489 case LDP_MSG_LABEL_ABORT_REQUEST: 490 491 default: 492 if (vflag <= 1) 493 print_unknown_data(msg_tptr,"\n\t ",msg_tlen); 494 break; 495 } 496 /* do we want to see an additionally hexdump ? */ 497 if (vflag > 1 || hexdump==TRUE) 498 print_unknown_data(tptr+sizeof(sizeof(struct ldp_msg_header)),"\n\t ", 499 msg_len); 500 501 tptr += msg_len+4; 502 tlen -= msg_len+4; 503 } 504 return; 505 trunc: 506 printf("\n\t\t packet exceeded snapshot"); 507 } 508 509