1210284Sjmallett/* 2215990Sjmallett * Copyright (c) 1998-2007 The TCPDUMP project 3215990Sjmallett * 4210284Sjmallett * Redistribution and use in source and binary forms, with or without 5210284Sjmallett * modification, are permitted provided that: (1) source code 6215990Sjmallett * distributions retain the above copyright notice and this paragraph 7215990Sjmallett * in its entirety, and (2) distributions including binary code include 8215990Sjmallett * the above copyright notice and this paragraph in its entirety in 9210284Sjmallett * the documentation or other materials provided with the distribution. 10215990Sjmallett * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 11215990Sjmallett * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT 12210284Sjmallett * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 13215990Sjmallett * FOR A PARTICULAR PURPOSE. 14215990Sjmallett * 15215990Sjmallett * VLAN TRUNKING PROTOCOL (VTP) 16215990Sjmallett * 17215990Sjmallett * Reference documentation: 18215990Sjmallett * http://www.cisco.com/en/US/tech/tk389/tk689/technologies_tech_note09186a0080094c52.shtml 19215990Sjmallett * http://www.cisco.com/warp/public/473/21.html 20215990Sjmallett * http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm 21215990Sjmallett * 22215990Sjmallett * Original code ode by Carles Kishimoto <carles.kishimoto@gmail.com> 23215990Sjmallett */ 24215990Sjmallett 25215990Sjmallett#ifdef HAVE_CONFIG_H 26215990Sjmallett#include "config.h" 27215990Sjmallett#endif 28215990Sjmallett 29215990Sjmallett#include <tcpdump-stdinc.h> 30215990Sjmallett 31215990Sjmallett#include <stdio.h> 32215990Sjmallett#include <string.h> 33215990Sjmallett 34215990Sjmallett#include "interface.h" 35215990Sjmallett#include "addrtoname.h" 36215990Sjmallett#include "extract.h" 37215990Sjmallett#include "nlpid.h" 38210284Sjmallett 39210284Sjmallett#define VTP_HEADER_LEN 36 40210284Sjmallett#define VTP_DOMAIN_NAME_LEN 32 41210284Sjmallett#define VTP_MD5_DIGEST_LEN 16 42210284Sjmallett#define VTP_UPDATE_TIMESTAMP_LEN 12 43210284Sjmallett#define VTP_VLAN_INFO_OFFSET 12 44210284Sjmallett 45215990Sjmallett#define VTP_SUMMARY_ADV 0x01 46210284Sjmallett#define VTP_SUBSET_ADV 0x02 47210284Sjmallett#define VTP_ADV_REQUEST 0x03 48210284Sjmallett#define VTP_JOIN_MESSAGE 0x04 49210284Sjmallett 50210284Sjmallettstruct vtp_vlan_ { 51215990Sjmallett u_int8_t len; 52210284Sjmallett u_int8_t status; 53210284Sjmallett u_int8_t type; 54210284Sjmallett u_int8_t name_len; 55210284Sjmallett u_int16_t vlanid; 56210284Sjmallett u_int16_t mtu; 57215990Sjmallett u_int32_t index; 58210284Sjmallett}; 59210284Sjmallett 60210284Sjmallettstatic struct tok vtp_message_type_values[] = { 61210284Sjmallett { VTP_SUMMARY_ADV, "Summary advertisement"}, 62210284Sjmallett { VTP_SUBSET_ADV, "Subset advertisement"}, 63210284Sjmallett { VTP_ADV_REQUEST, "Advertisement request"}, 64210284Sjmallett { VTP_JOIN_MESSAGE, "Join message"}, 65210284Sjmallett { 0, NULL } 66210284Sjmallett}; 67210284Sjmallett 68210284Sjmallettstatic struct tok vtp_header_values[] = { 69210284Sjmallett { 0x01, "Followers"}, /* On Summary advertisement, 3rd byte is Followers */ 70210284Sjmallett { 0x02, "Seq number"}, /* On Subset advertisement, 3rd byte is Sequence number */ 71210284Sjmallett { 0x03, "Rsvd"}, /* On Adver. requests 3rd byte is Rsvd */ 72210284Sjmallett { 0x04, "Rsvd"}, /* On Adver. requests 3rd byte is Rsvd */ 73210284Sjmallett { 0, NULL } 74210284Sjmallett}; 75210284Sjmallett 76210284Sjmallettstatic struct tok vtp_vlan_type_values[] = { 77210284Sjmallett { 0x01, "Ethernet"}, 78210284Sjmallett { 0x02, "FDDI"}, 79210284Sjmallett { 0x03, "TrCRF"}, 80210284Sjmallett { 0x04, "FDDI-net"}, 81210284Sjmallett { 0x05, "TrBRF"}, 82210284Sjmallett { 0, NULL } 83210284Sjmallett}; 84210284Sjmallett 85210284Sjmallettstatic struct tok vtp_vlan_status[] = { 86210284Sjmallett { 0x00, "Operational"}, 87210284Sjmallett { 0x01, "Suspended"}, 88210284Sjmallett { 0, NULL } 89210284Sjmallett}; 90210284Sjmallett 91210284Sjmallett#define VTP_VLAN_SOURCE_ROUTING_RING_NUMBER 0x01 92210284Sjmallett#define VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER 0x02 93210284Sjmallett#define VTP_VLAN_STP_TYPE 0x03 94210284Sjmallett#define VTP_VLAN_PARENT_VLAN 0x04 95210284Sjmallett#define VTP_VLAN_TRANS_BRIDGED_VLAN 0x05 96210284Sjmallett#define VTP_VLAN_PRUNING 0x06 97210284Sjmallett#define VTP_VLAN_BRIDGE_TYPE 0x07 98210284Sjmallett#define VTP_VLAN_ARP_HOP_COUNT 0x08 99210284Sjmallett#define VTP_VLAN_STE_HOP_COUNT 0x09 100210284Sjmallett#define VTP_VLAN_BACKUP_CRF_MODE 0x0A 101210284Sjmallett 102210284Sjmallettstatic struct tok vtp_vlan_tlv_values[] = { 103210284Sjmallett { VTP_VLAN_SOURCE_ROUTING_RING_NUMBER, "Source-Routing Ring Number TLV"}, 104210284Sjmallett { VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER, "Source-Routing Bridge Number TLV"}, 105210284Sjmallett { VTP_VLAN_STP_TYPE, "STP type TLV"}, 106210284Sjmallett { VTP_VLAN_PARENT_VLAN, "Parent VLAN TLV"}, 107210284Sjmallett { VTP_VLAN_TRANS_BRIDGED_VLAN, "Translationally bridged VLANs TLV"}, 108210284Sjmallett { VTP_VLAN_PRUNING, "Pruning TLV"}, 109210284Sjmallett { VTP_VLAN_BRIDGE_TYPE, "Bridge Type TLV"}, 110210284Sjmallett { VTP_VLAN_ARP_HOP_COUNT, "Max ARP Hop Count TLV"}, 111210284Sjmallett { VTP_VLAN_STE_HOP_COUNT, "Max STE Hop Count TLV"}, 112210284Sjmallett { VTP_VLAN_BACKUP_CRF_MODE, "Backup CRF Mode TLV"}, 113210284Sjmallett { 0, NULL } 114210284Sjmallett}; 115210284Sjmallett 116210284Sjmallettstatic struct tok vtp_stp_type_values[] = { 117210284Sjmallett { 1, "SRT"}, 118210284Sjmallett { 2, "SRB"}, 119210284Sjmallett { 3, "Auto"}, 120210284Sjmallett { 0, NULL } 121210284Sjmallett}; 122210284Sjmallett 123210284Sjmallettvoid 124210284Sjmallettvtp_print (const u_char *pptr, u_int length) 125210284Sjmallett{ 126210284Sjmallett int type, len, tlv_len, tlv_value; 127210284Sjmallett const u_char *tptr; 128210284Sjmallett const struct vtp_vlan_ *vtp_vlan; 129210284Sjmallett 130210284Sjmallett if (length < VTP_HEADER_LEN) 131210284Sjmallett goto trunc; 132210284Sjmallett 133210284Sjmallett tptr = pptr; 134210284Sjmallett 135210284Sjmallett if (!TTEST2(*tptr, VTP_HEADER_LEN)) 136210284Sjmallett goto trunc; 137210284Sjmallett 138210284Sjmallett type = *(tptr+1); 139210284Sjmallett printf("VTPv%u, Message %s (0x%02x), length %u", 140210284Sjmallett *tptr, 141210284Sjmallett tok2str(vtp_message_type_values,"Unknown message type", type), 142210284Sjmallett *(tptr+1), 143210284Sjmallett length); 144210284Sjmallett 145210284Sjmallett /* In non-verbose mode, just print version and message type */ 146210284Sjmallett if (vflag < 1) { 147210284Sjmallett return; 148210284Sjmallett } 149210284Sjmallett 150210284Sjmallett /* verbose mode print all fields */ 151210284Sjmallett printf("\n\tDomain name: %s, %s: %u", 152210284Sjmallett (tptr+4), 153210284Sjmallett tok2str(vtp_header_values,"Unknown",*(tptr+1)), 154210284Sjmallett *(tptr+2)); 155210284Sjmallett 156210284Sjmallett tptr += VTP_HEADER_LEN; 157210284Sjmallett 158210284Sjmallett switch (type) { 159210284Sjmallett 160210284Sjmallett case VTP_SUMMARY_ADV: 161210284Sjmallett 162210284Sjmallett /* 163210284Sjmallett * SUMMARY ADVERTISEMENT 164210284Sjmallett * 165210284Sjmallett * 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 166210284Sjmallett * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 167210284Sjmallett * | Version | Code | Followers | MmgtD Len | 168210284Sjmallett * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 169210284Sjmallett * | Management Domain Name | 170210284Sjmallett * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 171210284Sjmallett * | Configuration revision number | 172210284Sjmallett * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 173210284Sjmallett * | Updater Identity IP address | 174210284Sjmallett * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 175210284Sjmallett * | Update Timestamp (12 bytes) | 176210284Sjmallett * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 177210284Sjmallett * | MD5 digest (16 bytes) | 178210284Sjmallett * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 179210284Sjmallett * 180210284Sjmallett */ 181210284Sjmallett 182210284Sjmallett printf("\n\t Config Rev %x, Updater %s", 183210284Sjmallett EXTRACT_32BITS(tptr), 184210284Sjmallett ipaddr_string(tptr+4)); 185210284Sjmallett tptr += 8; 186210284Sjmallett printf(", Timestamp 0x%08x 0x%08x 0x%08x", 187210284Sjmallett EXTRACT_32BITS(tptr), 188210284Sjmallett EXTRACT_32BITS(tptr + 4), 189210284Sjmallett EXTRACT_32BITS(tptr + 8)); 190210284Sjmallett tptr += VTP_UPDATE_TIMESTAMP_LEN; 191210284Sjmallett printf(", MD5 digest: %08x%08x%08x%08x", 192210284Sjmallett EXTRACT_32BITS(tptr), 193210284Sjmallett EXTRACT_32BITS(tptr + 4), 194210284Sjmallett EXTRACT_32BITS(tptr + 8), 195210284Sjmallett EXTRACT_32BITS(tptr + 12)); 196210284Sjmallett tptr += VTP_MD5_DIGEST_LEN; 197210284Sjmallett break; 198210284Sjmallett 199210284Sjmallett case VTP_SUBSET_ADV: 200210284Sjmallett 201210284Sjmallett /* 202210284Sjmallett * SUBSET ADVERTISEMENT 203210284Sjmallett * 204210284Sjmallett * 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 205210284Sjmallett * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 206210284Sjmallett * | Version | Code | Seq number | MmgtD Len | 207210284Sjmallett * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 208210284Sjmallett * | Management Domain Name | 209210284Sjmallett * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 210210284Sjmallett * | Configuration revision number | 211210284Sjmallett * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 212210284Sjmallett * | VLAN info field 1 | 213215990Sjmallett * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 214210284Sjmallett * | ................ | 215210284Sjmallett * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 216210284Sjmallett * | VLAN info field N | 217210284Sjmallett * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 218210284Sjmallett * 219210284Sjmallett */ 220210284Sjmallett 221210284Sjmallett printf(", Config Rev %x", EXTRACT_32BITS(tptr)); 222210284Sjmallett 223210284Sjmallett /* 224210284Sjmallett * VLAN INFORMATION 225210284Sjmallett * 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 226210284Sjmallett * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 227210284Sjmallett * | V info len | Status | VLAN type | VLAN name len | 228210284Sjmallett * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 229210284Sjmallett * | ISL vlan id | MTU size | 230210284Sjmallett * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 231210284Sjmallett * | 802.10 index (SAID) | 232210284Sjmallett * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 233210284Sjmallett * | VLAN name | 234210284Sjmallett * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 235210284Sjmallett * 236210284Sjmallett */ 237210284Sjmallett 238210284Sjmallett tptr += 4; 239210284Sjmallett while (tptr < (pptr+length)) { 240210284Sjmallett 241210284Sjmallett len = *tptr; 242210284Sjmallett if (len == 0) 243210284Sjmallett break; 244210284Sjmallett 245210284Sjmallett if (!TTEST2(*tptr, len)) 246210284Sjmallett goto trunc; 247210284Sjmallett 248210284Sjmallett vtp_vlan = (struct vtp_vlan_*)tptr; 249210284Sjmallett printf("\n\tVLAN info status %s, type %s, VLAN-id %u, MTU %u, SAID 0x%08x, Name %s", 250210284Sjmallett tok2str(vtp_vlan_status,"Unknown",vtp_vlan->status), 251210284Sjmallett tok2str(vtp_vlan_type_values,"Unknown",vtp_vlan->type), 252210284Sjmallett EXTRACT_16BITS(&vtp_vlan->vlanid), 253210284Sjmallett EXTRACT_16BITS(&vtp_vlan->mtu), 254210284Sjmallett EXTRACT_32BITS(&vtp_vlan->index), 255210284Sjmallett (tptr + VTP_VLAN_INFO_OFFSET)); 256210284Sjmallett 257210284Sjmallett /* 258210284Sjmallett * Vlan names are aligned to 32-bit boundaries. 259210284Sjmallett */ 260210284Sjmallett len -= VTP_VLAN_INFO_OFFSET + 4*((vtp_vlan->name_len + 3)/4); 261210284Sjmallett tptr += VTP_VLAN_INFO_OFFSET + 4*((vtp_vlan->name_len + 3)/4); 262210284Sjmallett 263210284Sjmallett /* TLV information follows */ 264210284Sjmallett 265210284Sjmallett while (len > 0) { 266210284Sjmallett 267210284Sjmallett /* 268210284Sjmallett * Cisco specs says 2 bytes for type + 2 bytes for length, take only 1 269210284Sjmallett * See: http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm 270210284Sjmallett */ 271210284Sjmallett type = *tptr; 272210284Sjmallett tlv_len = *(tptr+1); 273210284Sjmallett 274210284Sjmallett printf("\n\t\t%s (0x%04x) TLV", 275210284Sjmallett tok2str(vtp_vlan_tlv_values, "Unknown", type), 276210284Sjmallett type); 277210284Sjmallett 278210284Sjmallett /* 279210284Sjmallett * infinite loop check 280210284Sjmallett */ 281210284Sjmallett if (type == 0 || tlv_len == 0) { 282210284Sjmallett return; 283210284Sjmallett } 284210284Sjmallett 285210284Sjmallett if (!TTEST2(*tptr, tlv_len*2 +2)) 286210284Sjmallett goto trunc; 287210284Sjmallett 288210284Sjmallett tlv_value = EXTRACT_16BITS(tptr+2); 289210284Sjmallett 290210284Sjmallett switch (type) { 291210284Sjmallett case VTP_VLAN_STE_HOP_COUNT: 292210284Sjmallett printf(", %u", tlv_value); 293210284Sjmallett break; 294210284Sjmallett 295210284Sjmallett case VTP_VLAN_PRUNING: 296210284Sjmallett printf(", %s (%u)", 297210284Sjmallett tlv_value == 1 ? "Enabled" : "Disabled", 298210284Sjmallett tlv_value); 299210284Sjmallett break; 300210284Sjmallett 301210284Sjmallett case VTP_VLAN_STP_TYPE: 302210284Sjmallett printf(", %s (%u)", 303210284Sjmallett tok2str(vtp_stp_type_values, "Unknown", tlv_value), 304210284Sjmallett tlv_value); 305210284Sjmallett break; 306210284Sjmallett 307210284Sjmallett case VTP_VLAN_BRIDGE_TYPE: 308210284Sjmallett printf(", %s (%u)", 309210284Sjmallett tlv_value == 1 ? "SRB" : "SRT", 310210284Sjmallett tlv_value); 311210284Sjmallett break; 312210284Sjmallett 313210284Sjmallett case VTP_VLAN_BACKUP_CRF_MODE: 314210284Sjmallett printf(", %s (%u)", 315210284Sjmallett tlv_value == 1 ? "Backup" : "Not backup", 316210284Sjmallett tlv_value); 317215990Sjmallett break; 318210284Sjmallett 319210284Sjmallett /* 320210284Sjmallett * FIXME those are the defined TLVs that lack a decoder 321210284Sjmallett * you are welcome to contribute code ;-) 322210284Sjmallett */ 323210284Sjmallett 324210284Sjmallett case VTP_VLAN_SOURCE_ROUTING_RING_NUMBER: 325210284Sjmallett case VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER: 326210284Sjmallett case VTP_VLAN_PARENT_VLAN: 327210284Sjmallett case VTP_VLAN_TRANS_BRIDGED_VLAN: 328210284Sjmallett case VTP_VLAN_ARP_HOP_COUNT: 329210284Sjmallett default: 330210284Sjmallett print_unknown_data(tptr, "\n\t\t ", 2 + tlv_len*2); 331210284Sjmallett break; 332210284Sjmallett } 333210284Sjmallett len -= 2 + tlv_len*2; 334210284Sjmallett tptr += 2 + tlv_len*2; 335210284Sjmallett } 336210284Sjmallett } 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