1 # This file is part of Scapy 2 # Scapy is free software: you can redistribute it and/or modify 3 # it under the terms of the GNU General Public License as published by 4 # the Free Software Foundation, either version 2 of the License, or 5 # any later version. 6 # 7 # Scapy is distributed in the hope that it will be useful, 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 # GNU General Public License for more details. 11 # 12 # You should have received a copy of the GNU General Public License 13 # along with Scapy. If not, see <http://www.gnu.org/licenses/>. 14 15 # scapy.contrib.description = VLAN Trunking Protocol (VTP) 16 # scapy.contrib.status = loads 17 18 """ 19 VTP Scapy Extension 20 ~~~~~~~~~~~~~~~~~~~~~ 21 22 :version: 2009-02-15 23 :copyright: 2009 by Jochen Bartl 24 :e-mail: lobo (at] c3a.de / jochen.bartl (at] gmail.com 25 :license: GPL v2 26 27 This program is free software; you can redistribute it and/or 28 modify it under the terms of the GNU General Public License 29 as published by the Free Software Foundation; either version 2 30 of the License, or (at your option) any later version. 31 32 This program is distributed in the hope that it will be useful, 33 but WITHOUT ANY WARRANTY; without even the implied warranty of 34 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 35 GNU General Public License for more details. 36 37 :TODO 38 39 - Join messages 40 - RE MD5 hash calculation 41 - Have a closer look at 8 byte padding in summary adv. 42 "debug sw-vlan vtp packets" sais the TLV length is invalid, 43 when I change the values 44 b'\x00\x00\x00\x01\x06\x01\x00\x02' 45 * \x00\x00 ? 46 * \x00\x01 tlvtype? 47 * \x06 length? 48 * \x00\x02 value? 49 - h2i function for VTPTimeStampField 50 51 :References: 52 53 - Understanding VLAN Trunk Protocol (VTP) 54 http://www.cisco.com/en/US/tech/tk389/tk689/technologies_tech_note09186a0080094c52.shtml 55 """ 56 57 from scapy.packet import * 58 from scapy.fields import * 59 from scapy.layers.l2 import * 60 61 _VTP_VLAN_TYPE = { 62 1 : 'Ethernet', 63 2 : 'FDDI', 64 3 : 'TrCRF', 65 4 : 'FDDI-net', 66 5 : 'TrBRF' 67 } 68 69 _VTP_VLANINFO_TLV_TYPE = { 70 0x01 : 'Source-Routing Ring Number', 71 0x02 : 'Source-Routing Bridge Number', 72 0x03 : 'Spanning-Tree Protocol Type', 73 0x04 : 'Parent VLAN', 74 0x05 : 'Translationally Bridged VLANs', 75 0x06 : 'Pruning', 76 0x07 : 'Bridge Type', 77 0x08 : 'Max ARE Hop Count', 78 0x09 : 'Max STE Hop Count', 79 0x0A : 'Backup CRF Mode' 80 } 81 82 83 class VTPVlanInfoTlv(Packet): 84 name = "VTP VLAN Info TLV" 85 fields_desc = [ 86 ByteEnumField("type", 0, _VTP_VLANINFO_TLV_TYPE), 87 ByteField("length", 0), 88 StrLenField("value", None, length_from=lambda pkt : pkt.length + 1) 89 ] 90 91 def guess_payload_class(self, p): 92 return conf.padding_layer 93 94 class VTPVlanInfo(Packet): 95 name = "VTP VLAN Info" 96 fields_desc = [ 97 ByteField("len", None), # FIXME: compute length 98 ByteEnumField("status", 0, {0 : "active", 1 : "suspended"}), 99 ByteEnumField("type", 1, _VTP_VLAN_TYPE), 100 FieldLenField("vlannamelen", None, "vlanname", "B"), 101 ShortField("vlanid", 1), 102 ShortField("mtu", 1500), 103 XIntField("dot10index", None), 104 StrLenField("vlanname", "default", length_from=lambda pkt:4 * ((pkt.vlannamelen + 3) / 4)), 105 ConditionalField(PacketListField("tlvlist", [], VTPVlanInfoTlv, 106 length_from=lambda pkt:pkt.len - 12 - (4 * ((pkt.vlannamelen + 3) / 4))), 107 lambda pkt:pkt.type not in [1, 2]) 108 ] 109 110 def post_build(self, p, pay): 111 vlannamelen = 4 * ((len(self.vlanname) + 3) / 4) 112 113 if self.len == None: 114 l = vlannamelen + 12 115 p = chr(l & 0xff) + p[1:] 116 117 # Pad vlan name with zeros if vlannamelen > len(vlanname) 118 l = vlannamelen - len(self.vlanname) 119 if l != 0: 120 p += b"\x00" * l 121 122 p += pay 123 124 return p 125 126 def guess_payload_class(self, p): 127 return conf.padding_layer 128 129 _VTP_Types = { 130 1 : 'Summary Advertisement', 131 2 : 'Subset Advertisements', 132 3 : 'Advertisement Request', 133 4 : 'Join' 134 } 135 136 class VTPTimeStampField(StrFixedLenField): 137 def __init__(self, name, default): 138 StrFixedLenField.__init__(self, name, default, 12) 139 140 def i2repr(self, pkt, x): 141 return "%s-%s-%s %s:%s:%s" % (x[:2], x[2:4], x[4:6], x[6:8], x[8:10], x[10:12]) 142 143 class VTP(Packet): 144 name = "VTP" 145 fields_desc = [ 146 ByteField("ver", 2), 147 ByteEnumField("code", 1, _VTP_Types), 148 ConditionalField(ByteField("followers", 1), 149 lambda pkt:pkt.code == 1), 150 ConditionalField(ByteField("seq", 1), 151 lambda pkt:pkt.code == 2), 152 ConditionalField(ByteField("reserved", 0), 153 lambda pkt:pkt.code == 3), 154 ByteField("domnamelen", None), 155 StrFixedLenField("domname", "manbearpig", 32), 156 ConditionalField(SignedIntField("rev", 0), 157 lambda pkt:pkt.code == 1 or 158 pkt.code == 2), 159 # updater identity 160 ConditionalField(IPField("uid", "192.168.0.1"), 161 lambda pkt:pkt.code == 1), 162 ConditionalField(VTPTimeStampField("timestamp", '930301000000'), 163 lambda pkt:pkt.code == 1), 164 ConditionalField(StrFixedLenField("md5", b"\x00" * 16, 16), 165 lambda pkt:pkt.code == 1), 166 ConditionalField( 167 PacketListField("vlaninfo", [], VTPVlanInfo), 168 lambda pkt: pkt.code == 2), 169 ConditionalField(ShortField("startvalue", 0), 170 lambda pkt:pkt.code == 3) 171 ] 172 173 def post_build(self, p, pay): 174 if self.domnamelen == None: 175 domnamelen = len(self.domname.strip(b"\x00")) 176 p = p[:3] + chr(domnamelen & 0xff) + p[4:] 177 178 p += pay 179 180 return p 181 182 bind_layers(SNAP, VTP, code=0x2003) 183 184 if __name__ == '__main__': 185 from scapy.main import interact 186 interact(mydict=globals(), mybanner="VTP") 187