| #!/usr/bin/env python |
| |
| # 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 = DTP |
| # scapy.contrib.status = loads |
| |
| """ |
| DTP Scapy Extension |
| ~~~~~~~~~~~~~~~~~~~ |
| |
| :version: 2008-12-22 |
| :author: Jochen Bartl <lobo@c3a.de> |
| |
| :Thanks: |
| |
| - TLV code derived from the CDP implementation of scapy. (Thanks to Nicolas Bareil and Arnaud Ebalard) |
| http://trac.secdev.org/scapy/ticket/18 |
| """ |
| |
| from __future__ import absolute_import |
| from __future__ import print_function |
| from scapy.packet import * |
| from scapy.fields import * |
| from scapy.layers.l2 import SNAP,Dot3,LLC |
| from scapy.sendrecv import sendp |
| |
| class DtpGenericTlv(Packet): |
| name = "DTP Generic TLV" |
| fields_desc = [ XShortField("type", 0x0001), |
| FieldLenField("length", None, length_of=lambda pkt:pkt.value + 4), |
| StrLenField("value", "", length_from=lambda pkt:pkt.length - 4) |
| ] |
| |
| def guess_payload_class(self, p): |
| return conf.padding_layer |
| |
| class RepeatedTlvListField(PacketListField): |
| def __init__(self, name, default, cls): |
| PacketField.__init__(self, name, default, cls) |
| |
| def getfield(self, pkt, s): |
| lst = [] |
| remain = s |
| while len(remain) > 0: |
| p = self.m2i(pkt,remain) |
| if conf.padding_layer in p: |
| pad = p[conf.padding_layer] |
| remain = pad.load |
| del(pad.underlayer.payload) |
| else: |
| remain = "" |
| lst.append(p) |
| return remain,lst |
| |
| def addfield(self, pkt, s, val): |
| return s + ''.join(str(v) for v in val) |
| |
| _DTP_TLV_CLS = { |
| 0x0001 : "DTPDomain", |
| 0x0002 : "DTPStatus", |
| 0x0003 : "DTPType", |
| 0x0004 : "DTPNeighbor" |
| } |
| |
| class DTPDomain(DtpGenericTlv): |
| name = "DTP Domain" |
| fields_desc = [ ShortField("type", 1), |
| FieldLenField("length", None, "domain", adjust=lambda pkt,x:x + 4), |
| StrLenField("domain", b"\x00", length_from=lambda pkt:pkt.length - 4) |
| ] |
| |
| class DTPStatus(DtpGenericTlv): |
| name = "DTP Status" |
| fields_desc = [ ShortField("type", 2), |
| FieldLenField("length", None, "status", adjust=lambda pkt,x:x + 4), |
| StrLenField("status", b"\x03", length_from=lambda pkt:pkt.length - 4) |
| ] |
| |
| class DTPType(DtpGenericTlv): |
| name = "DTP Type" |
| fields_desc = [ ShortField("type", 3), |
| FieldLenField("length", None, "dtptype", adjust=lambda pkt,x:x + 4), |
| StrLenField("dtptype", b"\xa5", length_from=lambda pkt:pkt.length - 4) |
| ] |
| |
| class DTPNeighbor(DtpGenericTlv): |
| name = "DTP Neighbor" |
| fields_desc = [ ShortField("type", 4), |
| #FieldLenField("length", None, "neighbor", adjust=lambda pkt,x:x + 4), |
| ShortField("len", 10), |
| MACField("neighbor", None) |
| ] |
| |
| def _DTPGuessPayloadClass(p, **kargs): |
| cls = conf.raw_layer |
| if len(p) >= 2: |
| t = struct.unpack("!H", p[:2])[0] |
| clsname = _DTP_TLV_CLS.get(t, "DtpGenericTlv") |
| cls = globals()[clsname] |
| return cls(p, **kargs) |
| |
| class DTP(Packet): |
| name = "DTP" |
| fields_desc = [ ByteField("ver", 1), |
| RepeatedTlvListField("tlvlist", [], _DTPGuessPayloadClass) |
| ] |
| |
| bind_layers(SNAP, DTP, code=0x2004, OUI=0xc) |
| |
| |
| def negotiate_trunk(iface=conf.iface, mymac=str(RandMAC())): |
| print("Trying to negotiate a trunk on interface %s" % iface) |
| p = Dot3(src=mymac, dst="01:00:0c:cc:cc:cc")/LLC()/SNAP()/DTP(tlvlist=[DTPDomain(),DTPStatus(),DTPType(),DTPNeighbor(neighbor=mymac)]) |
| sendp(p) |
| |
| if __name__ == "__main__": |
| from scapy.main import interact |
| interact(mydict=globals(), mybanner="DTP") |