#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <tcpdump-stdinc.h>
#include <stdio.h>
#include <string.h>
#include "interface.h"
#include "addrtoname.h"
#include "extract.h"
#include "nlpid.h"
#define VTP_HEADER_LEN 36
#define VTP_DOMAIN_NAME_LEN 32
#define VTP_MD5_DIGEST_LEN 16
#define VTP_UPDATE_TIMESTAMP_LEN 12
#define VTP_VLAN_INFO_OFFSET 12
#define VTP_SUMMARY_ADV 0x01
#define VTP_SUBSET_ADV 0x02
#define VTP_ADV_REQUEST 0x03
#define VTP_JOIN_MESSAGE 0x04
struct vtp_vlan_ {
u_int8_t len;
u_int8_t status;
u_int8_t type;
u_int8_t name_len;
u_int16_t vlanid;
u_int16_t mtu;
u_int32_t index;
};
static struct tok vtp_message_type_values[] = {
{ VTP_SUMMARY_ADV, "Summary advertisement"},
{ VTP_SUBSET_ADV, "Subset advertisement"},
{ VTP_ADV_REQUEST, "Advertisement request"},
{ VTP_JOIN_MESSAGE, "Join message"},
{ 0, NULL }
};
static struct tok vtp_header_values[] = {
{ 0x01, "Followers"},
{ 0x02, "Seq number"},
{ 0x03, "Rsvd"},
{ 0x04, "Rsvd"},
{ 0, NULL }
};
static struct tok vtp_vlan_type_values[] = {
{ 0x01, "Ethernet"},
{ 0x02, "FDDI"},
{ 0x03, "TrCRF"},
{ 0x04, "FDDI-net"},
{ 0x05, "TrBRF"},
{ 0, NULL }
};
static struct tok vtp_vlan_status[] = {
{ 0x00, "Operational"},
{ 0x01, "Suspended"},
{ 0, NULL }
};
#define VTP_VLAN_SOURCE_ROUTING_RING_NUMBER 0x01
#define VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER 0x02
#define VTP_VLAN_STP_TYPE 0x03
#define VTP_VLAN_PARENT_VLAN 0x04
#define VTP_VLAN_TRANS_BRIDGED_VLAN 0x05
#define VTP_VLAN_PRUNING 0x06
#define VTP_VLAN_BRIDGE_TYPE 0x07
#define VTP_VLAN_ARP_HOP_COUNT 0x08
#define VTP_VLAN_STE_HOP_COUNT 0x09
#define VTP_VLAN_BACKUP_CRF_MODE 0x0A
static struct tok vtp_vlan_tlv_values[] = {
{ VTP_VLAN_SOURCE_ROUTING_RING_NUMBER, "Source-Routing Ring Number TLV"},
{ VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER, "Source-Routing Bridge Number TLV"},
{ VTP_VLAN_STP_TYPE, "STP type TLV"},
{ VTP_VLAN_PARENT_VLAN, "Parent VLAN TLV"},
{ VTP_VLAN_TRANS_BRIDGED_VLAN, "Translationally bridged VLANs TLV"},
{ VTP_VLAN_PRUNING, "Pruning TLV"},
{ VTP_VLAN_BRIDGE_TYPE, "Bridge Type TLV"},
{ VTP_VLAN_ARP_HOP_COUNT, "Max ARP Hop Count TLV"},
{ VTP_VLAN_STE_HOP_COUNT, "Max STE Hop Count TLV"},
{ VTP_VLAN_BACKUP_CRF_MODE, "Backup CRF Mode TLV"},
{ 0, NULL }
};
static struct tok vtp_stp_type_values[] = {
{ 1, "SRT"},
{ 2, "SRB"},
{ 3, "Auto"},
{ 0, NULL }
};
void
vtp_print (const u_char *pptr, u_int length)
{
int type, len, tlv_len, tlv_value;
const u_char *tptr;
const struct vtp_vlan_ *vtp_vlan;
if (length < VTP_HEADER_LEN)
goto trunc;
tptr = pptr;
if (!TTEST2(*tptr, VTP_HEADER_LEN))
goto trunc;
type = *(tptr+1);
printf("VTPv%u, Message %s (0x%02x), length %u",
*tptr,
tok2str(vtp_message_type_values,"Unknown message type", type),
*(tptr+1),
length);
if (vflag < 1) {
return;
}
printf("\n\tDomain name: %s, %s: %u",
(tptr+4),
tok2str(vtp_header_values,"Unknown",*(tptr+1)),
*(tptr+2));
tptr += VTP_HEADER_LEN;
switch (type) {
case VTP_SUMMARY_ADV:
printf("\n\t Config Rev %x, Updater %s",
EXTRACT_32BITS(tptr),
ipaddr_string(tptr+4));
tptr += 8;
printf(", Timestamp 0x%08x 0x%08x 0x%08x",
EXTRACT_32BITS(tptr),
EXTRACT_32BITS(tptr + 4),
EXTRACT_32BITS(tptr + 8));
tptr += VTP_UPDATE_TIMESTAMP_LEN;
printf(", MD5 digest: %08x%08x%08x%08x",
EXTRACT_32BITS(tptr),
EXTRACT_32BITS(tptr + 4),
EXTRACT_32BITS(tptr + 8),
EXTRACT_32BITS(tptr + 12));
tptr += VTP_MD5_DIGEST_LEN;
break;
case VTP_SUBSET_ADV:
printf(", Config Rev %x", EXTRACT_32BITS(tptr));
tptr += 4;
while (tptr < (pptr+length)) {
len = *tptr;
if (len == 0)
break;
if (!TTEST2(*tptr, len))
goto trunc;
vtp_vlan = (struct vtp_vlan_*)tptr;
printf("\n\tVLAN info status %s, type %s, VLAN-id %u, MTU %u, SAID 0x%08x, Name %s",
tok2str(vtp_vlan_status,"Unknown",vtp_vlan->status),
tok2str(vtp_vlan_type_values,"Unknown",vtp_vlan->type),
EXTRACT_16BITS(&vtp_vlan->vlanid),
EXTRACT_16BITS(&vtp_vlan->mtu),
EXTRACT_32BITS(&vtp_vlan->index),
(tptr + VTP_VLAN_INFO_OFFSET));
len -= VTP_VLAN_INFO_OFFSET + 4*((vtp_vlan->name_len + 3)/4);
tptr += VTP_VLAN_INFO_OFFSET + 4*((vtp_vlan->name_len + 3)/4);
while (len > 0) {
type = *tptr;
tlv_len = *(tptr+1);
printf("\n\t\t%s (0x%04x) TLV",
tok2str(vtp_vlan_tlv_values, "Unknown", type),
type);
if (type == 0 || tlv_len == 0) {
return;
}
if (!TTEST2(*tptr, tlv_len*2 +2))
goto trunc;
tlv_value = EXTRACT_16BITS(tptr+2);
switch (type) {
case VTP_VLAN_STE_HOP_COUNT:
printf(", %u", tlv_value);
break;
case VTP_VLAN_PRUNING:
printf(", %s (%u)",
tlv_value == 1 ? "Enabled" : "Disabled",
tlv_value);
break;
case VTP_VLAN_STP_TYPE:
printf(", %s (%u)",
tok2str(vtp_stp_type_values, "Unknown", tlv_value),
tlv_value);
break;
case VTP_VLAN_BRIDGE_TYPE:
printf(", %s (%u)",
tlv_value == 1 ? "SRB" : "SRT",
tlv_value);
break;
case VTP_VLAN_BACKUP_CRF_MODE:
printf(", %s (%u)",
tlv_value == 1 ? "Backup" : "Not backup",
tlv_value);
break;
case VTP_VLAN_SOURCE_ROUTING_RING_NUMBER:
case VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER:
case VTP_VLAN_PARENT_VLAN:
case VTP_VLAN_TRANS_BRIDGED_VLAN:
case VTP_VLAN_ARP_HOP_COUNT:
default:
print_unknown_data(tptr, "\n\t\t ", 2 + tlv_len*2);
break;
}
len -= 2 + tlv_len*2;
tptr += 2 + tlv_len*2;
}
}
break;
case VTP_ADV_REQUEST:
printf("\n\tStart value: %u", EXTRACT_32BITS(tptr));
break;
case VTP_JOIN_MESSAGE:
break;
default:
break;
}
return;
trunc:
printf("[|vtp]");
}