Home | History | Annotate | Download | only in tcpdump
      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 (at) 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 const 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 const 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 const 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 const 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 const 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 const 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