summaryrefslogtreecommitdiffstats
path: root/scripts/external_libs/scapy-2.3.1/scapy/contrib/cdp.py
diff options
context:
space:
mode:
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.py306
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})
+