esp32_bluetooth_classic_sni.../libs/scapy/contrib/vtp.py
Matheus Eduardo Garbelini 86890704fd initial commit
todo: add documentation & wireshark dissector
2021-08-31 19:51:03 +08:00

204 lines
6.6 KiB
Python
Executable file

# 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
r"""
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" says 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 # noqa: E501
"""
from scapy.packet import Packet, bind_layers
from scapy.fields import ByteEnumField, ByteField, ConditionalField, \
FieldLenField, IPField, PacketListField, ShortField, SignedIntField, \
StrFixedLenField, StrLenField, XIntField
from scapy.layers.l2 import SNAP
from scapy.compat import chb
from scapy.config import conf
_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),
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)) # noqa: E501
),
lambda pkt:pkt.type not in [1, 2]
)
]
def post_build(self, p, pay):
vlannamelen = 4 * ((len(self.vlanname) + 3) // 4)
if self.len is None:
tmp_len = vlannamelen + 12
p = chb(tmp_len & 0xff) + p[1:]
# Pad vlan name with zeros if vlannamelen > len(vlanname)
tmp_len = vlannamelen - len(self.vlanname)
if tmp_len != 0:
p += b"\x00" * tmp_len
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]) # noqa: E501
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 is None:
domnamelen = len(self.domname.strip(b"\x00"))
p = p[:3] + chb(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")