1190203Srpaulo/* 2190203Srpaulo * Copyright (c) 1998-2007 The TCPDUMP project 3190203Srpaulo * 4190203Srpaulo * Redistribution and use in source and binary forms, with or without 5190203Srpaulo * modification, are permitted provided that: (1) source code 6190203Srpaulo * distributions retain the above copyright notice and this paragraph 7190203Srpaulo * in its entirety, and (2) distributions including binary code include 8190203Srpaulo * the above copyright notice and this paragraph in its entirety in 9190203Srpaulo * the documentation or other materials provided with the distribution. 10190203Srpaulo * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 11190203Srpaulo * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT 12190203Srpaulo * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 13190203Srpaulo * FOR A PARTICULAR PURPOSE. 14190203Srpaulo * 15190203Srpaulo * VLAN TRUNKING PROTOCOL (VTP) 16190203Srpaulo * 17190203Srpaulo * Reference documentation: 18190203Srpaulo * http://www.cisco.com/en/US/tech/tk389/tk689/technologies_tech_note09186a0080094c52.shtml 19190203Srpaulo * http://www.cisco.com/warp/public/473/21.html 20190203Srpaulo * http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm 21190203Srpaulo * 22190203Srpaulo * Original code ode by Carles Kishimoto <carles.kishimoto@gmail.com> 23190203Srpaulo */ 24190203Srpaulo 25190203Srpaulo#ifdef HAVE_CONFIG_H 26190203Srpaulo#include "config.h" 27190203Srpaulo#endif 28190203Srpaulo 29190203Srpaulo#include <tcpdump-stdinc.h> 30190203Srpaulo 31190203Srpaulo#include <stdio.h> 32190203Srpaulo#include <string.h> 33190203Srpaulo 34190203Srpaulo#include "interface.h" 35190203Srpaulo#include "addrtoname.h" 36190203Srpaulo#include "extract.h" 37190203Srpaulo#include "nlpid.h" 38190203Srpaulo 39190203Srpaulo#define VTP_HEADER_LEN 36 40190203Srpaulo#define VTP_DOMAIN_NAME_LEN 32 41190203Srpaulo#define VTP_MD5_DIGEST_LEN 16 42190203Srpaulo#define VTP_UPDATE_TIMESTAMP_LEN 12 43190203Srpaulo#define VTP_VLAN_INFO_OFFSET 12 44190203Srpaulo 45190203Srpaulo#define VTP_SUMMARY_ADV 0x01 46190203Srpaulo#define VTP_SUBSET_ADV 0x02 47190203Srpaulo#define VTP_ADV_REQUEST 0x03 48190203Srpaulo#define VTP_JOIN_MESSAGE 0x04 49190203Srpaulo 50190203Srpaulostruct vtp_vlan_ { 51190203Srpaulo u_int8_t len; 52190203Srpaulo u_int8_t status; 53190203Srpaulo u_int8_t type; 54190203Srpaulo u_int8_t name_len; 55190203Srpaulo u_int16_t vlanid; 56190203Srpaulo u_int16_t mtu; 57190203Srpaulo u_int32_t index; 58190203Srpaulo}; 59190203Srpaulo 60190203Srpaulostatic struct tok vtp_message_type_values[] = { 61190203Srpaulo { VTP_SUMMARY_ADV, "Summary advertisement"}, 62190203Srpaulo { VTP_SUBSET_ADV, "Subset advertisement"}, 63190203Srpaulo { VTP_ADV_REQUEST, "Advertisement request"}, 64190203Srpaulo { VTP_JOIN_MESSAGE, "Join message"}, 65190203Srpaulo { 0, NULL } 66190203Srpaulo}; 67190203Srpaulo 68190203Srpaulostatic struct tok vtp_header_values[] = { 69190203Srpaulo { 0x01, "Followers"}, /* On Summary advertisement, 3rd byte is Followers */ 70190203Srpaulo { 0x02, "Seq number"}, /* On Subset advertisement, 3rd byte is Sequence number */ 71190203Srpaulo { 0x03, "Rsvd"}, /* On Adver. requests 3rd byte is Rsvd */ 72190203Srpaulo { 0x04, "Rsvd"}, /* On Adver. requests 3rd byte is Rsvd */ 73190203Srpaulo { 0, NULL } 74190203Srpaulo}; 75190203Srpaulo 76190203Srpaulostatic struct tok vtp_vlan_type_values[] = { 77190203Srpaulo { 0x01, "Ethernet"}, 78190203Srpaulo { 0x02, "FDDI"}, 79190203Srpaulo { 0x03, "TrCRF"}, 80190203Srpaulo { 0x04, "FDDI-net"}, 81190203Srpaulo { 0x05, "TrBRF"}, 82190203Srpaulo { 0, NULL } 83190203Srpaulo}; 84190203Srpaulo 85190203Srpaulostatic struct tok vtp_vlan_status[] = { 86190203Srpaulo { 0x00, "Operational"}, 87190203Srpaulo { 0x01, "Suspended"}, 88190203Srpaulo { 0, NULL } 89190203Srpaulo}; 90190203Srpaulo 91190203Srpaulo#define VTP_VLAN_SOURCE_ROUTING_RING_NUMBER 0x01 92190203Srpaulo#define VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER 0x02 93190203Srpaulo#define VTP_VLAN_STP_TYPE 0x03 94190203Srpaulo#define VTP_VLAN_PARENT_VLAN 0x04 95190203Srpaulo#define VTP_VLAN_TRANS_BRIDGED_VLAN 0x05 96190203Srpaulo#define VTP_VLAN_PRUNING 0x06 97190203Srpaulo#define VTP_VLAN_BRIDGE_TYPE 0x07 98190203Srpaulo#define VTP_VLAN_ARP_HOP_COUNT 0x08 99190203Srpaulo#define VTP_VLAN_STE_HOP_COUNT 0x09 100190203Srpaulo#define VTP_VLAN_BACKUP_CRF_MODE 0x0A 101190203Srpaulo 102190203Srpaulostatic struct tok vtp_vlan_tlv_values[] = { 103190203Srpaulo { VTP_VLAN_SOURCE_ROUTING_RING_NUMBER, "Source-Routing Ring Number TLV"}, 104190203Srpaulo { VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER, "Source-Routing Bridge Number TLV"}, 105190203Srpaulo { VTP_VLAN_STP_TYPE, "STP type TLV"}, 106190203Srpaulo { VTP_VLAN_PARENT_VLAN, "Parent VLAN TLV"}, 107190203Srpaulo { VTP_VLAN_TRANS_BRIDGED_VLAN, "Translationally bridged VLANs TLV"}, 108190203Srpaulo { VTP_VLAN_PRUNING, "Pruning TLV"}, 109190203Srpaulo { VTP_VLAN_BRIDGE_TYPE, "Bridge Type TLV"}, 110190203Srpaulo { VTP_VLAN_ARP_HOP_COUNT, "Max ARP Hop Count TLV"}, 111190203Srpaulo { VTP_VLAN_STE_HOP_COUNT, "Max STE Hop Count TLV"}, 112190203Srpaulo { VTP_VLAN_BACKUP_CRF_MODE, "Backup CRF Mode TLV"}, 113190203Srpaulo { 0, NULL } 114190203Srpaulo}; 115190203Srpaulo 116190203Srpaulostatic struct tok vtp_stp_type_values[] = { 117190203Srpaulo { 1, "SRT"}, 118190203Srpaulo { 2, "SRB"}, 119190203Srpaulo { 3, "Auto"}, 120190203Srpaulo { 0, NULL } 121190203Srpaulo}; 122190203Srpaulo 123190203Srpaulovoid 124190203Srpaulovtp_print (const u_char *pptr, u_int length) 125190203Srpaulo{ 126190203Srpaulo int type, len, tlv_len, tlv_value; 127190203Srpaulo const u_char *tptr; 128190203Srpaulo const struct vtp_vlan_ *vtp_vlan; 129190203Srpaulo 130190203Srpaulo if (length < VTP_HEADER_LEN) 131190203Srpaulo goto trunc; 132190203Srpaulo 133190203Srpaulo tptr = pptr; 134190203Srpaulo 135190203Srpaulo if (!TTEST2(*tptr, VTP_HEADER_LEN)) 136190203Srpaulo goto trunc; 137190203Srpaulo 138190203Srpaulo type = *(tptr+1); 139190203Srpaulo printf("VTPv%u, Message %s (0x%02x), length %u", 140190203Srpaulo *tptr, 141190203Srpaulo tok2str(vtp_message_type_values,"Unknown message type", type), 142190203Srpaulo *(tptr+1), 143190203Srpaulo length); 144190203Srpaulo 145190203Srpaulo /* In non-verbose mode, just print version and message type */ 146190203Srpaulo if (vflag < 1) { 147190203Srpaulo return; 148190203Srpaulo } 149190203Srpaulo 150190203Srpaulo /* verbose mode print all fields */ 151190203Srpaulo printf("\n\tDomain name: %s, %s: %u", 152190203Srpaulo (tptr+4), 153190203Srpaulo tok2str(vtp_header_values,"Unknown",*(tptr+1)), 154190203Srpaulo *(tptr+2)); 155190203Srpaulo 156190203Srpaulo tptr += VTP_HEADER_LEN; 157190203Srpaulo 158190203Srpaulo switch (type) { 159190203Srpaulo 160190203Srpaulo case VTP_SUMMARY_ADV: 161190203Srpaulo 162190203Srpaulo /* 163190203Srpaulo * SUMMARY ADVERTISEMENT 164190203Srpaulo * 165190203Srpaulo * 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 166190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 167190203Srpaulo * | Version | Code | Followers | MmgtD Len | 168190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 169190203Srpaulo * | Management Domain Name | 170190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 171190203Srpaulo * | Configuration revision number | 172190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 173190203Srpaulo * | Updater Identity IP address | 174190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 175190203Srpaulo * | Update Timestamp (12 bytes) | 176190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 177190203Srpaulo * | MD5 digest (16 bytes) | 178190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 179190203Srpaulo * 180190203Srpaulo */ 181190203Srpaulo 182190203Srpaulo printf("\n\t Config Rev %x, Updater %s", 183190203Srpaulo EXTRACT_32BITS(tptr), 184190203Srpaulo ipaddr_string(tptr+4)); 185190203Srpaulo tptr += 8; 186190203Srpaulo printf(", Timestamp 0x%08x 0x%08x 0x%08x", 187190203Srpaulo EXTRACT_32BITS(tptr), 188190203Srpaulo EXTRACT_32BITS(tptr + 4), 189190203Srpaulo EXTRACT_32BITS(tptr + 8)); 190190203Srpaulo tptr += VTP_UPDATE_TIMESTAMP_LEN; 191190203Srpaulo printf(", MD5 digest: %08x%08x%08x%08x", 192190203Srpaulo EXTRACT_32BITS(tptr), 193190203Srpaulo EXTRACT_32BITS(tptr + 4), 194190203Srpaulo EXTRACT_32BITS(tptr + 8), 195190203Srpaulo EXTRACT_32BITS(tptr + 12)); 196190203Srpaulo tptr += VTP_MD5_DIGEST_LEN; 197190203Srpaulo break; 198190203Srpaulo 199190203Srpaulo case VTP_SUBSET_ADV: 200190203Srpaulo 201190203Srpaulo /* 202190203Srpaulo * SUBSET ADVERTISEMENT 203190203Srpaulo * 204190203Srpaulo * 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 205190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 206190203Srpaulo * | Version | Code | Seq number | MmgtD Len | 207190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 208190203Srpaulo * | Management Domain Name | 209190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 210190203Srpaulo * | Configuration revision number | 211190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 212190203Srpaulo * | VLAN info field 1 | 213190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 214190203Srpaulo * | ................ | 215190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 216190203Srpaulo * | VLAN info field N | 217190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 218190203Srpaulo * 219190203Srpaulo */ 220190203Srpaulo 221190203Srpaulo printf(", Config Rev %x", EXTRACT_32BITS(tptr)); 222190203Srpaulo 223190203Srpaulo /* 224190203Srpaulo * VLAN INFORMATION 225190203Srpaulo * 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 226190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 227190203Srpaulo * | V info len | Status | VLAN type | VLAN name len | 228190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 229190203Srpaulo * | ISL vlan id | MTU size | 230190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 231190203Srpaulo * | 802.10 index (SAID) | 232190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 233190203Srpaulo * | VLAN name | 234190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 235190203Srpaulo * 236190203Srpaulo */ 237190203Srpaulo 238190203Srpaulo tptr += 4; 239190203Srpaulo while (tptr < (pptr+length)) { 240190203Srpaulo 241190203Srpaulo len = *tptr; 242190203Srpaulo if (len == 0) 243190203Srpaulo break; 244190203Srpaulo 245190203Srpaulo if (!TTEST2(*tptr, len)) 246190203Srpaulo goto trunc; 247190203Srpaulo 248190203Srpaulo vtp_vlan = (struct vtp_vlan_*)tptr; 249190203Srpaulo printf("\n\tVLAN info status %s, type %s, VLAN-id %u, MTU %u, SAID 0x%08x, Name %s", 250190203Srpaulo tok2str(vtp_vlan_status,"Unknown",vtp_vlan->status), 251190203Srpaulo tok2str(vtp_vlan_type_values,"Unknown",vtp_vlan->type), 252190203Srpaulo EXTRACT_16BITS(&vtp_vlan->vlanid), 253190203Srpaulo EXTRACT_16BITS(&vtp_vlan->mtu), 254190203Srpaulo EXTRACT_32BITS(&vtp_vlan->index), 255190203Srpaulo (tptr + VTP_VLAN_INFO_OFFSET)); 256190203Srpaulo 257190203Srpaulo /* 258190203Srpaulo * Vlan names are aligned to 32-bit boundaries. 259190203Srpaulo */ 260190203Srpaulo len -= VTP_VLAN_INFO_OFFSET + 4*((vtp_vlan->name_len + 3)/4); 261190203Srpaulo tptr += VTP_VLAN_INFO_OFFSET + 4*((vtp_vlan->name_len + 3)/4); 262190203Srpaulo 263190203Srpaulo /* TLV information follows */ 264190203Srpaulo 265190203Srpaulo while (len > 0) { 266190203Srpaulo 267190203Srpaulo /* 268190203Srpaulo * Cisco specs says 2 bytes for type + 2 bytes for length, take only 1 269190203Srpaulo * See: http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm 270190203Srpaulo */ 271190203Srpaulo type = *tptr; 272190203Srpaulo tlv_len = *(tptr+1); 273190203Srpaulo 274190203Srpaulo printf("\n\t\t%s (0x%04x) TLV", 275190203Srpaulo tok2str(vtp_vlan_tlv_values, "Unknown", type), 276190203Srpaulo type); 277190203Srpaulo 278190203Srpaulo /* 279190203Srpaulo * infinite loop check 280190203Srpaulo */ 281190203Srpaulo if (type == 0 || tlv_len == 0) { 282190203Srpaulo return; 283190203Srpaulo } 284190203Srpaulo 285190203Srpaulo if (!TTEST2(*tptr, tlv_len*2 +2)) 286190203Srpaulo goto trunc; 287190203Srpaulo 288190203Srpaulo tlv_value = EXTRACT_16BITS(tptr+2); 289190203Srpaulo 290190203Srpaulo switch (type) { 291190203Srpaulo case VTP_VLAN_STE_HOP_COUNT: 292190203Srpaulo printf(", %u", tlv_value); 293190203Srpaulo break; 294190203Srpaulo 295190203Srpaulo case VTP_VLAN_PRUNING: 296190203Srpaulo printf(", %s (%u)", 297190203Srpaulo tlv_value == 1 ? "Enabled" : "Disabled", 298190203Srpaulo tlv_value); 299190203Srpaulo break; 300190203Srpaulo 301190203Srpaulo case VTP_VLAN_STP_TYPE: 302190203Srpaulo printf(", %s (%u)", 303190203Srpaulo tok2str(vtp_stp_type_values, "Unknown", tlv_value), 304190203Srpaulo tlv_value); 305190203Srpaulo break; 306190203Srpaulo 307190203Srpaulo case VTP_VLAN_BRIDGE_TYPE: 308190203Srpaulo printf(", %s (%u)", 309190203Srpaulo tlv_value == 1 ? "SRB" : "SRT", 310190203Srpaulo tlv_value); 311190203Srpaulo break; 312190203Srpaulo 313190203Srpaulo case VTP_VLAN_BACKUP_CRF_MODE: 314190203Srpaulo printf(", %s (%u)", 315190203Srpaulo tlv_value == 1 ? "Backup" : "Not backup", 316190203Srpaulo tlv_value); 317190203Srpaulo break; 318190203Srpaulo 319190203Srpaulo /* 320190203Srpaulo * FIXME those are the defined TLVs that lack a decoder 321190203Srpaulo * you are welcome to contribute code ;-) 322190203Srpaulo */ 323190203Srpaulo 324190203Srpaulo case VTP_VLAN_SOURCE_ROUTING_RING_NUMBER: 325190203Srpaulo case VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER: 326190203Srpaulo case VTP_VLAN_PARENT_VLAN: 327190203Srpaulo case VTP_VLAN_TRANS_BRIDGED_VLAN: 328190203Srpaulo case VTP_VLAN_ARP_HOP_COUNT: 329190203Srpaulo default: 330190203Srpaulo print_unknown_data(tptr, "\n\t\t ", 2 + tlv_len*2); 331190203Srpaulo break; 332190203Srpaulo } 333190203Srpaulo len -= 2 + tlv_len*2; 334190203Srpaulo tptr += 2 + tlv_len*2; 335190203Srpaulo } 336190203Srpaulo } 337190203Srpaulo break; 338190203Srpaulo 339190203Srpaulo case VTP_ADV_REQUEST: 340190203Srpaulo 341190203Srpaulo /* 342190203Srpaulo * ADVERTISEMENT REQUEST 343190203Srpaulo * 344190203Srpaulo * 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 345190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 346190203Srpaulo * | Version | Code | Reserved | MmgtD Len | 347190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 348190203Srpaulo * | Management Domain Name | 349190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 350190203Srpaulo * | Start value | 351190203Srpaulo * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 352190203Srpaulo * 353190203Srpaulo */ 354190203Srpaulo 355190203Srpaulo printf("\n\tStart value: %u", EXTRACT_32BITS(tptr)); 356190203Srpaulo break; 357190203Srpaulo 358190203Srpaulo case VTP_JOIN_MESSAGE: 359190203Srpaulo 360190203Srpaulo /* FIXME - Could not find message format */ 361190203Srpaulo break; 362190203Srpaulo 363190203Srpaulo default: 364190203Srpaulo break; 365190203Srpaulo } 366190203Srpaulo 367190203Srpaulo return; 368190203Srpaulo 369190203Srpaulo trunc: 370190203Srpaulo printf("[|vtp]"); 371190203Srpaulo} 372190203Srpaulo 373190203Srpaulo/* 374190203Srpaulo * Local Variables: 375190203Srpaulo * c-style: whitesmith 376190203Srpaulo * c-basic-offset: 4 377190203Srpaulo * End: 378190203Srpaulo */ 379