1 /* 2 * Copyright (c) 1998-2007 The TCPDUMP project 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that: (1) source code 6 * distributions retain the above copyright notice and this paragraph 7 * in its entirety, and (2) distributions including binary code include 8 * the above copyright notice and this paragraph in its entirety in 9 * the documentation or other materials provided with the distribution. 10 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 11 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT 12 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 13 * FOR A PARTICULAR PURPOSE. 14 * 15 * VLAN TRUNKING PROTOCOL (VTP) 16 * 17 * Reference documentation: 18 * http://www.cisco.com/en/US/tech/tk389/tk689/technologies_tech_note09186a0080094c52.shtml 19 * http://www.cisco.com/warp/public/473/21.html 20 * http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm 21 * 22 * Original code ode by Carles Kishimoto <carles.kishimoto@gmail.com> 23 */ 24 25 #ifdef HAVE_CONFIG_H 26 #include "config.h" 27 #endif 28 29 #include <tcpdump-stdinc.h> 30 31 #include <stdio.h> 32 #include <string.h> 33 34 #include "interface.h" 35 #include "addrtoname.h" 36 #include "extract.h" 37 #include "nlpid.h" 38 39 #define VTP_HEADER_LEN 36 40 #define VTP_DOMAIN_NAME_LEN 32 41 #define VTP_MD5_DIGEST_LEN 16 42 #define VTP_UPDATE_TIMESTAMP_LEN 12 43 #define VTP_VLAN_INFO_OFFSET 12 44 45 #define VTP_SUMMARY_ADV 0x01 46 #define VTP_SUBSET_ADV 0x02 47 #define VTP_ADV_REQUEST 0x03 48 #define VTP_JOIN_MESSAGE 0x04 49 50 struct vtp_vlan_ { 51 u_int8_t len; 52 u_int8_t status; 53 u_int8_t type; 54 u_int8_t name_len; 55 u_int16_t vlanid; 56 u_int16_t mtu; 57 u_int32_t index; 58 }; 59 60 static struct tok vtp_message_type_values[] = { 61 { VTP_SUMMARY_ADV, "Summary advertisement"}, 62 { VTP_SUBSET_ADV, "Subset advertisement"}, 63 { VTP_ADV_REQUEST, "Advertisement request"}, 64 { VTP_JOIN_MESSAGE, "Join message"}, 65 { 0, NULL } 66 }; 67 68 static struct tok vtp_header_values[] = { 69 { 0x01, "Followers"}, /* On Summary advertisement, 3rd byte is Followers */ 70 { 0x02, "Seq number"}, /* On Subset advertisement, 3rd byte is Sequence number */ 71 { 0x03, "Rsvd"}, /* On Adver. requests 3rd byte is Rsvd */ 72 { 0x04, "Rsvd"}, /* On Adver. requests 3rd byte is Rsvd */ 73 { 0, NULL } 74 }; 75 76 static struct tok vtp_vlan_type_values[] = { 77 { 0x01, "Ethernet"}, 78 { 0x02, "FDDI"}, 79 { 0x03, "TrCRF"}, 80 { 0x04, "FDDI-net"}, 81 { 0x05, "TrBRF"}, 82 { 0, NULL } 83 }; 84 85 static struct tok vtp_vlan_status[] = { 86 { 0x00, "Operational"}, 87 { 0x01, "Suspended"}, 88 { 0, NULL } 89 }; 90 91 #define VTP_VLAN_SOURCE_ROUTING_RING_NUMBER 0x01 92 #define VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER 0x02 93 #define VTP_VLAN_STP_TYPE 0x03 94 #define VTP_VLAN_PARENT_VLAN 0x04 95 #define VTP_VLAN_TRANS_BRIDGED_VLAN 0x05 96 #define VTP_VLAN_PRUNING 0x06 97 #define VTP_VLAN_BRIDGE_TYPE 0x07 98 #define VTP_VLAN_ARP_HOP_COUNT 0x08 99 #define VTP_VLAN_STE_HOP_COUNT 0x09 100 #define VTP_VLAN_BACKUP_CRF_MODE 0x0A 101 102 static struct tok vtp_vlan_tlv_values[] = { 103 { VTP_VLAN_SOURCE_ROUTING_RING_NUMBER, "Source-Routing Ring Number TLV"}, 104 { VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER, "Source-Routing Bridge Number TLV"}, 105 { VTP_VLAN_STP_TYPE, "STP type TLV"}, 106 { VTP_VLAN_PARENT_VLAN, "Parent VLAN TLV"}, 107 { VTP_VLAN_TRANS_BRIDGED_VLAN, "Translationally bridged VLANs TLV"}, 108 { VTP_VLAN_PRUNING, "Pruning TLV"}, 109 { VTP_VLAN_BRIDGE_TYPE, "Bridge Type TLV"}, 110 { VTP_VLAN_ARP_HOP_COUNT, "Max ARP Hop Count TLV"}, 111 { VTP_VLAN_STE_HOP_COUNT, "Max STE Hop Count TLV"}, 112 { VTP_VLAN_BACKUP_CRF_MODE, "Backup CRF Mode TLV"}, 113 { 0, NULL } 114 }; 115 116 static struct tok vtp_stp_type_values[] = { 117 { 1, "SRT"}, 118 { 2, "SRB"}, 119 { 3, "Auto"}, 120 { 0, NULL } 121 }; 122 123 void 124 vtp_print (const u_char *pptr, u_int length) 125 { 126 int type, len, tlv_len, tlv_value; 127 const u_char *tptr; 128 const struct vtp_vlan_ *vtp_vlan; 129 130 if (length < VTP_HEADER_LEN) 131 goto trunc; 132 133 tptr = pptr; 134 135 if (!TTEST2(*tptr, VTP_HEADER_LEN)) 136 goto trunc; 137 138 type = *(tptr+1); 139 printf("VTPv%u, Message %s (0x%02x), length %u", 140 *tptr, 141 tok2str(vtp_message_type_values,"Unknown message type", type), 142 *(tptr+1), 143 length); 144 145 /* In non-verbose mode, just print version and message type */ 146 if (vflag < 1) { 147 return; 148 } 149 150 /* verbose mode print all fields */ 151 printf("\n\tDomain name: %s, %s: %u", 152 (tptr+4), 153 tok2str(vtp_header_values,"Unknown",*(tptr+1)), 154 *(tptr+2)); 155 156 tptr += VTP_HEADER_LEN; 157 158 switch (type) { 159 160 case VTP_SUMMARY_ADV: 161 162 /* 163 * SUMMARY ADVERTISEMENT 164 * 165 * 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 166 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 167 * | Version | Code | Followers | MmgtD Len | 168 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 169 * | Management Domain Name | 170 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 171 * | Configuration revision number | 172 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 173 * | Updater Identity IP address | 174 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 175 * | Update Timestamp (12 bytes) | 176 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 177 * | MD5 digest (16 bytes) | 178 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 179 * 180 */ 181 182 printf("\n\t Config Rev %x, Updater %s", 183 EXTRACT_32BITS(tptr), 184 ipaddr_string(tptr+4)); 185 tptr += 8; 186 printf(", Timestamp 0x%08x 0x%08x 0x%08x", 187 EXTRACT_32BITS(tptr), 188 EXTRACT_32BITS(tptr + 4), 189 EXTRACT_32BITS(tptr + 8)); 190 tptr += VTP_UPDATE_TIMESTAMP_LEN; 191 printf(", MD5 digest: %08x%08x%08x%08x", 192 EXTRACT_32BITS(tptr), 193 EXTRACT_32BITS(tptr + 4), 194 EXTRACT_32BITS(tptr + 8), 195 EXTRACT_32BITS(tptr + 12)); 196 tptr += VTP_MD5_DIGEST_LEN; 197 break; 198 199 case VTP_SUBSET_ADV: 200 201 /* 202 * SUBSET ADVERTISEMENT 203 * 204 * 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 205 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 206 * | Version | Code | Seq number | MmgtD Len | 207 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 208 * | Management Domain Name | 209 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 210 * | Configuration revision number | 211 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 212 * | VLAN info field 1 | 213 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 214 * | ................ | 215 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 216 * | VLAN info field N | 217 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 218 * 219 */ 220 221 printf(", Config Rev %x", EXTRACT_32BITS(tptr)); 222 223 /* 224 * VLAN INFORMATION 225 * 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 226 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 227 * | V info len | Status | VLAN type | VLAN name len | 228 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 229 * | ISL vlan id | MTU size | 230 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 231 * | 802.10 index (SAID) | 232 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 233 * | VLAN name | 234 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 235 * 236 */ 237 238 tptr += 4; 239 while (tptr < (pptr+length)) { 240 241 len = *tptr; 242 if (len == 0) 243 break; 244 245 if (!TTEST2(*tptr, len)) 246 goto trunc; 247 248 vtp_vlan = (struct vtp_vlan_*)tptr; 249 printf("\n\tVLAN info status %s, type %s, VLAN-id %u, MTU %u, SAID 0x%08x, Name %s", 250 tok2str(vtp_vlan_status,"Unknown",vtp_vlan->status), 251 tok2str(vtp_vlan_type_values,"Unknown",vtp_vlan->type), 252 EXTRACT_16BITS(&vtp_vlan->vlanid), 253 EXTRACT_16BITS(&vtp_vlan->mtu), 254 EXTRACT_32BITS(&vtp_vlan->index), 255 (tptr + VTP_VLAN_INFO_OFFSET)); 256 257 /* 258 * Vlan names are aligned to 32-bit boundaries. 259 */ 260 len -= VTP_VLAN_INFO_OFFSET + 4*((vtp_vlan->name_len + 3)/4); 261 tptr += VTP_VLAN_INFO_OFFSET + 4*((vtp_vlan->name_len + 3)/4); 262 263 /* TLV information follows */ 264 265 while (len > 0) { 266 267 /* 268 * Cisco specs says 2 bytes for type + 2 bytes for length, take only 1 269 * See: http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm 270 */ 271 type = *tptr; 272 tlv_len = *(tptr+1); 273 274 printf("\n\t\t%s (0x%04x) TLV", 275 tok2str(vtp_vlan_tlv_values, "Unknown", type), 276 type); 277 278 /* 279 * infinite loop check 280 */ 281 if (type == 0 || tlv_len == 0) { 282 return; 283 } 284 285 if (!TTEST2(*tptr, tlv_len*2 +2)) 286 goto trunc; 287 288 tlv_value = EXTRACT_16BITS(tptr+2); 289 290 switch (type) { 291 case VTP_VLAN_STE_HOP_COUNT: 292 printf(", %u", tlv_value); 293 break; 294 295 case VTP_VLAN_PRUNING: 296 printf(", %s (%u)", 297 tlv_value == 1 ? "Enabled" : "Disabled", 298 tlv_value); 299 break; 300 301 case VTP_VLAN_STP_TYPE: 302 printf(", %s (%u)", 303 tok2str(vtp_stp_type_values, "Unknown", tlv_value), 304 tlv_value); 305 break; 306 307 case VTP_VLAN_BRIDGE_TYPE: 308 printf(", %s (%u)", 309 tlv_value == 1 ? "SRB" : "SRT", 310 tlv_value); 311 break; 312 313 case VTP_VLAN_BACKUP_CRF_MODE: 314 printf(", %s (%u)", 315 tlv_value == 1 ? "Backup" : "Not backup", 316 tlv_value); 317 break; 318 319 /* 320 * FIXME those are the defined TLVs that lack a decoder 321 * you are welcome to contribute code ;-) 322 */ 323 324 case VTP_VLAN_SOURCE_ROUTING_RING_NUMBER: 325 case VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER: 326 case VTP_VLAN_PARENT_VLAN: 327 case VTP_VLAN_TRANS_BRIDGED_VLAN: 328 case VTP_VLAN_ARP_HOP_COUNT: 329 default: 330 print_unknown_data(tptr, "\n\t\t ", 2 + tlv_len*2); 331 break; 332 } 333 len -= 2 + tlv_len*2; 334 tptr += 2 + tlv_len*2; 335 } 336 } 337 break; 338 339 case VTP_ADV_REQUEST: 340 341 /* 342 * ADVERTISEMENT REQUEST 343 * 344 * 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 345 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 346 * | Version | Code | Reserved | MmgtD Len | 347 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 348 * | Management Domain Name | 349 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 350 * | Start value | 351 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 352 * 353 */ 354 355 printf("\n\tStart value: %u", EXTRACT_32BITS(tptr)); 356 break; 357 358 case VTP_JOIN_MESSAGE: 359 360 /* FIXME - Could not find message format */ 361 break; 362 363 default: 364 break; 365 } 366 367 return; 368 369 trunc: 370 printf("[|vtp]"); 371 } 372 373 /* 374 * Local Variables: 375 * c-style: whitesmith 376 * c-basic-offset: 4 377 * End: 378 */ 379