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 */ 15 16 #ifndef lint 17 static const char rcsid[] _U_ = 18 "@(#) $Header: /tcpdump/master/tcpdump/print-ldp.c,v 1.4.2.2 2003/11/16 08:51:31 guy Exp $"; 19 #endif 20 21 #ifdef HAVE_CONFIG_H 22 #include "config.h" 23 #endif 24 25 #include <tcpdump-stdinc.h> 26 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <string.h> 30 31 #include "interface.h" 32 #include "extract.h" 33 #include "addrtoname.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 u_int8_t version[2]; 52 u_int8_t pdu_length[2]; 53 u_int8_t lsr_id[4]; 54 u_int8_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 u_int8_t type[2]; 85 u_int8_t length[2]; 86 u_int8_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 Widthdraw" }, 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_HOP_COUNT 0x0103 130 #define LDP_TLV_PATH_VECTOR 0x0104 131 #define LDP_TLV_GENERIC_LABEL 0x0200 132 #define LDP_TLV_ATM_LABEL 0x0201 133 #define LDP_TLV_FR_LABEL 0x0202 134 #define LDP_TLV_STATUS 0x0300 135 #define LDP_TLV_EXTD_STATUS 0x0301 136 #define LDP_TLV_RETURNED_PDU 0x0302 137 #define LDP_TLV_RETURNED_MSG 0x0303 138 #define LDP_TLV_COMMON_HELLO 0x0400 139 #define LDP_TLV_IPV4_TRANSPORT_ADDR 0x0401 140 #define LDP_TLV_CONFIG_SEQ_NUMBER 0x0402 141 #define LDP_TLV_IPV6_TRANSPORT_ADDR 0x0403 142 #define LDP_TLV_COMMON_SESSION 0x0500 143 #define LDP_TLV_ATM_SESSION_PARM 0x0501 144 #define LDP_TLV_FR_SESSION_PARM 0x0502 145 #define LDP_TLV_LABEL_REQUEST_MSG_ID 0x0600 146 147 static const struct tok ldp_tlv_values[] = { 148 { LDP_TLV_FEC, "FEC" }, 149 { LDP_TLV_ADDRESS_LIST, "Address List" }, 150 { LDP_TLV_HOP_COUNT, "Hop Count" }, 151 { LDP_TLV_PATH_VECTOR, "Path Vector" }, 152 { LDP_TLV_GENERIC_LABEL, "Generic Label" }, 153 { LDP_TLV_ATM_LABEL, "ATM Label" }, 154 { LDP_TLV_FR_LABEL, "Frame-Relay Label" }, 155 { LDP_TLV_STATUS, "Status" }, 156 { LDP_TLV_EXTD_STATUS, "Extended Status" }, 157 { LDP_TLV_RETURNED_PDU, "Returned PDU" }, 158 { LDP_TLV_RETURNED_MSG, "Returned Message" }, 159 { LDP_TLV_COMMON_HELLO, "Common Hello Parameters" }, 160 { LDP_TLV_IPV4_TRANSPORT_ADDR, "IPv4 Transport Address" }, 161 { LDP_TLV_CONFIG_SEQ_NUMBER, "Configuration Sequence Number" }, 162 { LDP_TLV_IPV6_TRANSPORT_ADDR, "IPv6 Transport Address" }, 163 { LDP_TLV_COMMON_SESSION, "Common Session Parameters" }, 164 { LDP_TLV_ATM_SESSION_PARM, "ATM Session Parameters" }, 165 { LDP_TLV_FR_SESSION_PARM, "Frame-Relay Session Parameters" }, 166 { LDP_TLV_LABEL_REQUEST_MSG_ID, "Label Request Message ID" }, 167 { 0, NULL} 168 }; 169 170 #define FALSE 0 171 #define TRUE 1 172 173 int ldp_tlv_print(register const u_char *); 174 175 /* 176 * ldp tlv header 177 * 178 * 0 1 2 3 179 * 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 180 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 181 * |U|F| Type | Length | 182 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 183 * | | 184 * | Value | 185 * ~ ~ 186 * | | 187 * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 188 * | | 189 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 190 */ 191 192 int 193 ldp_tlv_print(register const u_char *tptr) { 194 195 struct ldp_tlv_header { 196 u_int8_t type[2]; 197 u_int8_t length[2]; 198 }; 199 200 const struct ldp_tlv_header *ldp_tlv_header; 201 u_short tlv_type,tlv_len,tlv_tlen; 202 203 ldp_tlv_header = (const struct ldp_tlv_header *)tptr; 204 tlv_len=EXTRACT_16BITS(ldp_tlv_header->length); 205 tlv_tlen=tlv_len; 206 tlv_type=LDP_MASK_TLV_TYPE(EXTRACT_16BITS(ldp_tlv_header->type)); 207 208 /* FIXME vendor private / experimental check */ 209 printf("\n\t %s TLV (0x%04x), length: %u, Flags: [%s and %s forward if unknown]", 210 tok2str(ldp_tlv_values, 211 "Unknown", 212 tlv_type), 213 tlv_type, 214 tlv_len, 215 LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "continue processing" : "ignore", 216 LDP_MASK_F_BIT(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "do" : "don't"); 217 218 tptr+=sizeof(struct ldp_tlv_header); 219 220 switch(tlv_type) { 221 222 case LDP_TLV_COMMON_HELLO: 223 printf("\n\t Hold Time: %us, Flags: [%s Hello%s]", 224 EXTRACT_16BITS(tptr), 225 (EXTRACT_16BITS(tptr+2)&0x8000) ? "Targeted" : "Link", 226 (EXTRACT_16BITS(tptr+2)&0x4000) ? ", Request for targeted Hellos" : ""); 227 break; 228 229 case LDP_TLV_IPV4_TRANSPORT_ADDR: 230 printf("\n\t IPv4 Transport Address: %s", ipaddr_string(tptr)); 231 break; 232 #ifdef INET6 233 case LDP_TLV_IPV6_TRANSPORT_ADDR: 234 printf("\n\t IPv6 Transport Address: %s", ip6addr_string(tptr)); 235 break; 236 #endif 237 case LDP_TLV_CONFIG_SEQ_NUMBER: 238 printf("\n\t Sequence Number: %u", EXTRACT_32BITS(tptr)); 239 break; 240 241 /* 242 * FIXME those are the defined TLVs that lack a decoder 243 * you are welcome to contribute code ;-) 244 */ 245 246 case LDP_TLV_FEC: 247 case LDP_TLV_ADDRESS_LIST: 248 case LDP_TLV_HOP_COUNT: 249 case LDP_TLV_PATH_VECTOR: 250 case LDP_TLV_GENERIC_LABEL: 251 case LDP_TLV_ATM_LABEL: 252 case LDP_TLV_FR_LABEL: 253 case LDP_TLV_STATUS: 254 case LDP_TLV_EXTD_STATUS: 255 case LDP_TLV_RETURNED_PDU: 256 case LDP_TLV_RETURNED_MSG: 257 case LDP_TLV_COMMON_SESSION: 258 case LDP_TLV_ATM_SESSION_PARM: 259 case LDP_TLV_FR_SESSION_PARM: 260 case LDP_TLV_LABEL_REQUEST_MSG_ID: 261 262 default: 263 if (vflag <= 1) 264 print_unknown_data(tptr,"\n\t ",tlv_tlen); 265 break; 266 } 267 return(tlv_len+4); /* Type & Length fields not included */ 268 } 269 270 void 271 ldp_print(register const u_char *pptr, register u_int len) { 272 273 const struct ldp_common_header *ldp_com_header; 274 const struct ldp_msg_header *ldp_msg_header; 275 const u_char *tptr,*msg_tptr; 276 u_short tlen; 277 u_short msg_len,msg_type,msg_tlen; 278 int hexdump,processed; 279 280 tptr=pptr; 281 ldp_com_header = (const struct ldp_common_header *)pptr; 282 TCHECK(*ldp_com_header); 283 284 /* 285 * Sanity checking of the header. 286 */ 287 if (EXTRACT_16BITS(&ldp_com_header->version) != LDP_VERSION) { 288 printf("LDP version %u packet not supported", 289 EXTRACT_16BITS(&ldp_com_header->version)); 290 return; 291 } 292 293 /* print the LSR-ID, label-space & length */ 294 printf("%sLDP, Label-Space-ID: %s:%u, length: %u", 295 (vflag < 1) ? "" : "\n\t", 296 ipaddr_string(&ldp_com_header->lsr_id), 297 EXTRACT_16BITS(&ldp_com_header->label_space), 298 len); 299 300 /* bail out if non-verbose */ 301 if (vflag < 1) 302 return; 303 304 /* ok they seem to want to know everything - lets fully decode it */ 305 tlen=EXTRACT_16BITS(ldp_com_header->pdu_length); 306 307 tptr+=sizeof(const struct ldp_common_header); 308 tlen-=sizeof(const struct ldp_common_header); 309 310 while(tlen>0) { 311 /* did we capture enough for fully decoding the msg header ? */ 312 if (!TTEST2(*tptr, sizeof(struct ldp_msg_header))) 313 goto trunc; 314 315 ldp_msg_header = (const struct ldp_msg_header *)tptr; 316 msg_len=EXTRACT_16BITS(ldp_msg_header->length); 317 msg_type=LDP_MASK_MSG_TYPE(EXTRACT_16BITS(ldp_msg_header->type)); 318 319 /* FIXME vendor private / experimental check */ 320 printf("\n\t %s Message (0x%04x), length: %u, Message ID: 0x%08x, Flags: [%s if unknown]", 321 tok2str(ldp_msg_values, 322 "Unknown", 323 msg_type), 324 msg_type, 325 msg_len, 326 EXTRACT_32BITS(&ldp_msg_header->id), 327 LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_msg_header->type)) ? "continue processing" : "ignore"); 328 329 msg_tptr=tptr+sizeof(struct ldp_msg_header); 330 msg_tlen=msg_len-sizeof(struct ldp_msg_header)+4; /* Type & Length fields not included */ 331 332 /* did we capture enough for fully decoding the message ? */ 333 if (!TTEST2(*tptr, msg_len)) 334 goto trunc; 335 hexdump=FALSE; 336 337 switch(msg_type) { 338 339 case LDP_MSG_HELLO: 340 while(msg_tlen >= 4) { 341 processed = ldp_tlv_print(msg_tptr); 342 if (processed == 0) 343 break; 344 msg_tlen-=processed; 345 msg_tptr+=processed; 346 } 347 break; 348 349 /* 350 * FIXME those are the defined messages that lack a decoder 351 * you are welcome to contribute code ;-) 352 */ 353 354 case LDP_MSG_NOTIF: 355 case LDP_MSG_INIT: 356 case LDP_MSG_KEEPALIVE: 357 case LDP_MSG_ADDRESS: 358 case LDP_MSG_ADDRESS_WITHDRAW: 359 case LDP_MSG_LABEL_MAPPING: 360 case LDP_MSG_LABEL_REQUEST: 361 case LDP_MSG_LABEL_WITHDRAW: 362 case LDP_MSG_LABEL_RELEASE: 363 case LDP_MSG_LABEL_ABORT_REQUEST: 364 365 default: 366 if (vflag <= 1) 367 print_unknown_data(msg_tptr,"\n\t ",msg_tlen); 368 break; 369 } 370 /* do we want to see an additionally hexdump ? */ 371 if (vflag > 1 || hexdump==TRUE) 372 print_unknown_data(tptr+sizeof(sizeof(struct ldp_msg_header)),"\n\t ", 373 msg_len); 374 375 tptr+=msg_len; 376 tlen-=msg_len; 377 } 378 return; 379 trunc: 380 printf("\n\t\t packet exceeded snapshot"); 381 } 382 383