diff options
Diffstat (limited to 'scripts/external_libs/scapy-2.3.1/scapy/contrib/cdp.py')
-rw-r--r-- | scripts/external_libs/scapy-2.3.1/scapy/contrib/cdp.py | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/scripts/external_libs/scapy-2.3.1/scapy/contrib/cdp.py b/scripts/external_libs/scapy-2.3.1/scapy/contrib/cdp.py new file mode 100644 index 00000000..12794c7b --- /dev/null +++ b/scripts/external_libs/scapy-2.3.1/scapy/contrib/cdp.py @@ -0,0 +1,306 @@ +#! /usr/bin/env python + +# scapy.contrib.description = Cisco Discovery Protocol +# scapy.contrib.status = loads + +############################################################################# +## ## +## cdp.py --- Cisco Discovery Protocol (CDP) extension for Scapy ## +## ## +## Copyright (C) 2006 Nicolas Bareil <nicolas.bareil AT eads DOT net> ## +## Arnaud Ebalard <arnaud.ebalard AT eads DOT net> ## +## EADS/CRC security team ## +## ## +## This program is free software; you can redistribute it and/or modify it ## +## under the terms of the GNU General Public License version 2 as ## +## published by the Free Software Foundation; version 2. ## +## ## +## 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. ## +## ## +############################################################################# + +from scapy.packet import * +from scapy.fields import * +from scapy.layers.inet6 import * + + +##################################################################### +# Helpers and constants +##################################################################### + +# CDP TLV classes keyed by type +_cdp_tlv_cls = { 0x0001: "CDPMsgDeviceID", + 0x0002: "CDPMsgAddr", + 0x0003: "CDPMsgPortID", + 0x0004: "CDPMsgCapabilities", + 0x0005: "CDPMsgSoftwareVersion", + 0x0006: "CDPMsgPlatform", + 0x0007: "CDPMsgIPPrefix", + 0x0008: "CDPMsgProtoHello", + 0x0009: "CDPMsgVTPMgmtDomain", # CDPv2 + 0x000a: "CDPMsgNativeVLAN", # CDPv2 + 0x000b: "CDPMsgDuplex", # +# 0x000c: "CDPMsgGeneric", +# 0x000d: "CDPMsgGeneric", + 0x000e: "CDPMsgVoIPVLANReply", + 0x000f: "CDPMsgVoIPVLANQuery", + 0x0010: "CDPMsgPower", + 0x0011: "CDPMsgMTU", +# 0x0012: "CDPMsgTrustBitmap", +# 0x0013: "CDPMsgUntrustedPortCoS", +# 0x0014: "CDPMsgSystemName", +# 0x0015: "CDPMsgSystemOID", + 0x0016: "CDPMsgMgmtAddr", +# 0x0017: "CDPMsgLocation", + 0x0019: "CDPMsgUnknown19", +# 0x001a: "CDPPowerAvailable" + } + +_cdp_tlv_types = { 0x0001: "Device ID", + 0x0002: "Addresses", + 0x0003: "Port ID", + 0x0004: "Capabilities", + 0x0005: "Software Version", + 0x0006: "Platform", + 0x0007: "IP Prefix", + 0x0008: "Protocol Hello", + 0x0009: "VTP Mangement Domain", # CDPv2 + 0x000a: "Native VLAN", # CDPv2 + 0x000b: "Duplex", # + 0x000c: "CDP Unknown command (send us a pcap file)", + 0x000d: "CDP Unknown command (send us a pcap file)", + 0x000e: "VoIP VLAN Reply", + 0x000f: "VoIP VLAN Query", + 0x0010: "Power", + 0x0011: "MTU", + 0x0012: "Trust Bitmap", + 0x0013: "Untrusted Port CoS", + 0x0014: "System Name", + 0x0015: "System OID", + 0x0016: "Management Address", + 0x0017: "Location", + 0x0018: "CDP Unknown command (send us a pcap file)", + 0x0019: "CDP Unknown command (send us a pcap file)", + 0x001a: "Power Available"} + +def _CDPGuessPayloadClass(p, **kargs): + cls = conf.raw_layer + if len(p) >= 2: + t = struct.unpack("!H", p[:2])[0] + clsname = _cdp_tlv_cls.get(t, "CDPMsgGeneric") + cls = globals()[clsname] + + return cls(p, **kargs) + +class CDPMsgGeneric(Packet): + name = "CDP Generic Message" + fields_desc = [ XShortEnumField("type", None, _cdp_tlv_types), + FieldLenField("len", None, "val", "!H"), + StrLenField("val", "", length_from=lambda x:x.len - 4) ] + + + def guess_payload_class(self, p): + return conf.padding_layer # _CDPGuessPayloadClass + +class CDPMsgDeviceID(CDPMsgGeneric): + name = "Device ID" + type = 0x0001 + +_cdp_addr_record_ptype = {0x01: "NLPID", 0x02: "802.2"} +_cdp_addrrecord_proto_ip = "\xcc" +_cdp_addrrecord_proto_ipv6 = "\xaa\xaa\x03\x00\x00\x00\x86\xdd" + +class CDPAddrRecord(Packet): + name = "CDP Address" + fields_desc = [ ByteEnumField("ptype", 0x01, _cdp_addr_record_ptype), + FieldLenField("plen", None, "proto", "B"), + StrLenField("proto", None, length_from=lambda x:x.plen), + FieldLenField("addrlen", None, length_of=lambda x:x.addr), + StrLenField("addr", None, length_from=lambda x:x.addrlen)] + + def guess_payload_class(self, p): + return conf.padding_layer + +class CDPAddrRecordIPv4(CDPAddrRecord): + name = "CDP Address IPv4" + fields_desc = [ ByteEnumField("ptype", 0x01, _cdp_addr_record_ptype), + FieldLenField("plen", 1, "proto", "B"), + StrLenField("proto", _cdp_addrrecord_proto_ip, length_from=lambda x:x.plen), + ShortField("addrlen", 4), + IPField("addr", "0.0.0.0")] + +class CDPAddrRecordIPv6(CDPAddrRecord): + name = "CDP Address IPv6" + fields_desc = [ ByteEnumField("ptype", 0x02, _cdp_addr_record_ptype), + FieldLenField("plen", 8, "proto", "B"), + StrLenField("proto", _cdp_addrrecord_proto_ipv6, length_from=lambda x:x.plen), + ShortField("addrlen", 16), + IP6Field("addr", "::1")] + +def _CDPGuessAddrRecord(p, **kargs): + cls = conf.raw_layer + if len(p) >= 2: + plen = struct.unpack("B", p[1])[0] + proto = ''.join(struct.unpack("s" * plen, p[2:plen + 2])[0:plen]) + + if proto == _cdp_addrrecord_proto_ip: + clsname = "CDPAddrRecordIPv4" + elif proto == _cdp_addrrecord_proto_ipv6: + clsname = "CDPAddrRecordIPv6" + else: + clsname = "CDPAddrRecord" + + cls = globals()[clsname] + + return cls(p, **kargs) + +class CDPMsgAddr(CDPMsgGeneric): + name = "Addresses" + fields_desc = [ XShortEnumField("type", 0x0002, _cdp_tlv_types), + ShortField("len", None), + FieldLenField("naddr", None, "addr", "!I"), + PacketListField("addr", [], _CDPGuessAddrRecord, count_from=lambda x:x.naddr) ] + + def post_build(self, pkt, pay): + if self.len is None: + l = 8 + len(self.addr) * 9 + pkt = pkt[:2] + struct.pack("!H", l) + pkt[4:] + p = pkt + pay + return p + +class CDPMsgPortID(CDPMsgGeneric): + name = "Port ID" + fields_desc = [ XShortEnumField("type", 0x0003, _cdp_tlv_types), + FieldLenField("len", None, "iface", "!H"), + StrLenField("iface", "Port 1", length_from=lambda x:x.len - 4) ] + + +_cdp_capabilities = [ "Router", + "TransparentBridge", + "SourceRouteBridge", + "Switch", + "Host", + "IGMPCapable", + "Repeater"] + map(lambda x: "Bit%d" % x, range(25,0,-1)) + + +class CDPMsgCapabilities(CDPMsgGeneric): + name = "Capabilities" + fields_desc = [ XShortEnumField("type", 0x0004, _cdp_tlv_types), + ShortField("len", 8), + FlagsField("cap", 0, 32, _cdp_capabilities) ] + + +class CDPMsgSoftwareVersion(CDPMsgGeneric): + name = "Software Version" + type = 0x0005 + + +class CDPMsgPlatform(CDPMsgGeneric): + name = "Platform" + type = 0x0006 + +_cdp_duplex = { 0x00: "Half", 0x01: "Full" } + +# ODR Routing +class CDPMsgIPPrefix(CDPMsgGeneric): + name = "IP Prefix" + type = 0x0007 + fields_desc = [ XShortEnumField("type", 0x0007, _cdp_tlv_types), + ShortField("len", 8), + IPField("defaultgw", "192.168.0.1") ] + +# TODO : Do me !!!!!! 0x0008 +class CDPMsgProtoHello(CDPMsgGeneric): + name = "Protocol Hello" + type = 0x0008 + +class CDPMsgVTPMgmtDomain(CDPMsgGeneric): + name = "VTP Management Domain" + type = 0x0009 + +class CDPMsgNativeVLAN(CDPMsgGeneric): + name = "Native VLAN" + fields_desc = [ XShortEnumField("type", 0x000a, _cdp_tlv_types), + ShortField("len", 6), + ShortField("vlan", 1) ] + +class CDPMsgDuplex(CDPMsgGeneric): + name = "Duplex" + fields_desc = [ XShortEnumField("type", 0x000b, _cdp_tlv_types), + ShortField("len", 5), + ByteEnumField("duplex", 0x00, _cdp_duplex) ] + +class CDPMsgVoIPVLANReply(CDPMsgGeneric): + name = "VoIP VLAN Reply" + fields_desc = [ XShortEnumField("type", 0x000e, _cdp_tlv_types), + ShortField("len", 7), + ByteField("status?", 1), + ShortField("vlan", 1)] + + +# TODO : Do me !!! 0x000F +class CDPMsgVoIPVLANQuery(CDPMsgGeneric): + name = "VoIP VLAN Query" + type = 0x000f + +# fields_desc = [XShortEnumField("type", 0x000f, _cdp_tlv_types), +# FieldLenField("len", None, "val", "!H") ] + + +class _CDPPowerField(ShortField): + def i2repr(self, pkt, x): + if x is None: + x = 0 + return "%d mW" % x + + +class CDPMsgPower(CDPMsgGeneric): + name = "Power" + # Check if field length is fixed (2 bytes) + fields_desc = [ XShortEnumField("type", 0x0010, _cdp_tlv_types), + ShortField("len", 6), + _CDPPowerField("power", 1337)] + + +class CDPMsgMTU(CDPMsgGeneric): + name = "MTU" + # Check if field length is fixed (2 bytes) + fields_desc = [ XShortEnumField("type", 0x0011, _cdp_tlv_types), + ShortField("len", 6), + ShortField("mtu", 1500)] + +class CDPMsgMgmtAddr(CDPMsgAddr): + name = "Management Address" + type = 0x0016 + +class CDPMsgUnknown19(CDPMsgGeneric): + name = "Unknown CDP Message" + type = 0x0019 + +class CDPMsg(CDPMsgGeneric): + name = "CDP " + fields_desc = [ XShortEnumField("type", None, _cdp_tlv_types), + FieldLenField("len", None, "val", "!H"), + StrLenField("val", "", length_from=lambda x:x.len - 4) ] + +class _CDPChecksum: + def post_build(self, pkt, pay): + p = pkt + pay + if self.cksum is None: + cksum = checksum(p) + p = p[:2] + struct.pack("!H", cksum) + p[4:] + return p + +class CDPv2_HDR(_CDPChecksum, CDPMsgGeneric): + name = "Cisco Discovery Protocol version 2" + fields_desc = [ ByteField("vers", 2), + ByteField("ttl", 180), + XShortField("cksum", None), + PacketListField("msg", [], _CDPGuessPayloadClass) ] + +bind_layers(SNAP, CDPv2_HDR, {"code": 0x2000, "OUI": 0xC}) + |