blob: 98a7a97e7a5f04d71434001125fa0987ec024729 [file] [log] [blame]
# This file is part of Scapy
# Scapy is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# any later version.
#
# Scapy is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Scapy. If not, see <http://www.gnu.org/licenses/>.
# scapy.contrib.description = VLAN Trunking Protocol (VTP)
# scapy.contrib.status = loads
"""
VTP Scapy Extension
~~~~~~~~~~~~~~~~~~~~~
:version: 2009-02-15
:copyright: 2009 by Jochen Bartl
:e-mail: lobo@c3a.de / jochen.bartl@gmail.com
:license: GPL v2
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
:TODO
- Join messages
- RE MD5 hash calculation
- Have a closer look at 8 byte padding in summary adv.
"debug sw-vlan vtp packets" sais the TLV length is invalid,
when I change the values
b'\x00\x00\x00\x01\x06\x01\x00\x02'
* \x00\x00 ?
* \x00\x01 tlvtype?
* \x06 length?
* \x00\x02 value?
- h2i function for VTPTimeStampField
:References:
- Understanding VLAN Trunk Protocol (VTP)
http://www.cisco.com/en/US/tech/tk389/tk689/technologies_tech_note09186a0080094c52.shtml
"""
from scapy.packet import *
from scapy.fields import *
from scapy.layers.l2 import *
_VTP_VLAN_TYPE = {
1 : 'Ethernet',
2 : 'FDDI',
3 : 'TrCRF',
4 : 'FDDI-net',
5 : 'TrBRF'
}
_VTP_VLANINFO_TLV_TYPE = {
0x01 : 'Source-Routing Ring Number',
0x02 : 'Source-Routing Bridge Number',
0x03 : 'Spanning-Tree Protocol Type',
0x04 : 'Parent VLAN',
0x05 : 'Translationally Bridged VLANs',
0x06 : 'Pruning',
0x07 : 'Bridge Type',
0x08 : 'Max ARE Hop Count',
0x09 : 'Max STE Hop Count',
0x0A : 'Backup CRF Mode'
}
class VTPVlanInfoTlv(Packet):
name = "VTP VLAN Info TLV"
fields_desc = [
ByteEnumField("type", 0, _VTP_VLANINFO_TLV_TYPE),
ByteField("length", 0),
StrLenField("value", None, length_from=lambda pkt : pkt.length + 1)
]
def guess_payload_class(self, p):
return conf.padding_layer
class VTPVlanInfo(Packet):
name = "VTP VLAN Info"
fields_desc = [
ByteField("len", None), # FIXME: compute length
ByteEnumField("status", 0, {0 : "active", 1 : "suspended"}),
ByteEnumField("type", 1, _VTP_VLAN_TYPE),
FieldLenField("vlannamelen", None, "vlanname", "B"),
ShortField("vlanid", 1),
ShortField("mtu", 1500),
XIntField("dot10index", None),
StrLenField("vlanname", "default", length_from=lambda pkt:4 * ((pkt.vlannamelen + 3) / 4)),
ConditionalField(PacketListField("tlvlist", [], VTPVlanInfoTlv,
length_from=lambda pkt:pkt.len - 12 - (4 * ((pkt.vlannamelen + 3) / 4))),
lambda pkt:pkt.type not in [1, 2])
]
def post_build(self, p, pay):
vlannamelen = 4 * ((len(self.vlanname) + 3) / 4)
if self.len == None:
l = vlannamelen + 12
p = chr(l & 0xff) + p[1:]
# Pad vlan name with zeros if vlannamelen > len(vlanname)
l = vlannamelen - len(self.vlanname)
if l != 0:
p += b"\x00" * l
p += pay
return p
def guess_payload_class(self, p):
return conf.padding_layer
_VTP_Types = {
1 : 'Summary Advertisement',
2 : 'Subset Advertisements',
3 : 'Advertisement Request',
4 : 'Join'
}
class VTPTimeStampField(StrFixedLenField):
def __init__(self, name, default):
StrFixedLenField.__init__(self, name, default, 12)
def i2repr(self, pkt, x):
return "%s-%s-%s %s:%s:%s" % (x[:2], x[2:4], x[4:6], x[6:8], x[8:10], x[10:12])
class VTP(Packet):
name = "VTP"
fields_desc = [
ByteField("ver", 2),
ByteEnumField("code", 1, _VTP_Types),
ConditionalField(ByteField("followers", 1),
lambda pkt:pkt.code == 1),
ConditionalField(ByteField("seq", 1),
lambda pkt:pkt.code == 2),
ConditionalField(ByteField("reserved", 0),
lambda pkt:pkt.code == 3),
ByteField("domnamelen", None),
StrFixedLenField("domname", "manbearpig", 32),
ConditionalField(SignedIntField("rev", 0),
lambda pkt:pkt.code == 1 or
pkt.code == 2),
# updater identity
ConditionalField(IPField("uid", "192.168.0.1"),
lambda pkt:pkt.code == 1),
ConditionalField(VTPTimeStampField("timestamp", '930301000000'),
lambda pkt:pkt.code == 1),
ConditionalField(StrFixedLenField("md5", b"\x00" * 16, 16),
lambda pkt:pkt.code == 1),
ConditionalField(
PacketListField("vlaninfo", [], VTPVlanInfo),
lambda pkt: pkt.code == 2),
ConditionalField(ShortField("startvalue", 0),
lambda pkt:pkt.code == 3)
]
def post_build(self, p, pay):
if self.domnamelen == None:
domnamelen = len(self.domname.strip(b"\x00"))
p = p[:3] + chr(domnamelen & 0xff) + p[4:]
p += pay
return p
bind_layers(SNAP, VTP, code=0x2003)
if __name__ == '__main__':
from scapy.main import interact
interact(mydict=globals(), mybanner="VTP")