1 #!/usr/bin/env python 2 3 # This file is part of Scapy 4 # Scapy is free software: you can redistribute it and/or modify 5 # it under the terms of the GNU General Public License as published by 6 # the Free Software Foundation, either version 2 of the License, or 7 # any later version. 8 # 9 # Scapy is distributed in the hope that it will be useful, 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 # GNU General Public License for more details. 13 # 14 # You should have received a copy of the GNU General Public License 15 # along with Scapy. If not, see <http://www.gnu.org/licenses/>. 16 17 # scapy.contrib.description = DTP 18 # scapy.contrib.status = loads 19 20 """ 21 DTP Scapy Extension 22 ~~~~~~~~~~~~~~~~~~~ 23 24 :version: 2008-12-22 25 :author: Jochen Bartl <lobo (at] c3a.de> 26 27 :Thanks: 28 29 - TLV code derived from the CDP implementation of scapy. (Thanks to Nicolas Bareil and Arnaud Ebalard) 30 http://trac.secdev.org/scapy/ticket/18 31 """ 32 33 from __future__ import absolute_import 34 from __future__ import print_function 35 from scapy.packet import * 36 from scapy.fields import * 37 from scapy.layers.l2 import SNAP,Dot3,LLC 38 from scapy.sendrecv import sendp 39 40 class DtpGenericTlv(Packet): 41 name = "DTP Generic TLV" 42 fields_desc = [ XShortField("type", 0x0001), 43 FieldLenField("length", None, length_of=lambda pkt:pkt.value + 4), 44 StrLenField("value", "", length_from=lambda pkt:pkt.length - 4) 45 ] 46 47 def guess_payload_class(self, p): 48 return conf.padding_layer 49 50 class RepeatedTlvListField(PacketListField): 51 def __init__(self, name, default, cls): 52 PacketField.__init__(self, name, default, cls) 53 54 def getfield(self, pkt, s): 55 lst = [] 56 remain = s 57 while len(remain) > 0: 58 p = self.m2i(pkt,remain) 59 if conf.padding_layer in p: 60 pad = p[conf.padding_layer] 61 remain = pad.load 62 del(pad.underlayer.payload) 63 else: 64 remain = "" 65 lst.append(p) 66 return remain,lst 67 68 def addfield(self, pkt, s, val): 69 return s + ''.join(str(v) for v in val) 70 71 _DTP_TLV_CLS = { 72 0x0001 : "DTPDomain", 73 0x0002 : "DTPStatus", 74 0x0003 : "DTPType", 75 0x0004 : "DTPNeighbor" 76 } 77 78 class DTPDomain(DtpGenericTlv): 79 name = "DTP Domain" 80 fields_desc = [ ShortField("type", 1), 81 FieldLenField("length", None, "domain", adjust=lambda pkt,x:x + 4), 82 StrLenField("domain", b"\x00", length_from=lambda pkt:pkt.length - 4) 83 ] 84 85 class DTPStatus(DtpGenericTlv): 86 name = "DTP Status" 87 fields_desc = [ ShortField("type", 2), 88 FieldLenField("length", None, "status", adjust=lambda pkt,x:x + 4), 89 StrLenField("status", b"\x03", length_from=lambda pkt:pkt.length - 4) 90 ] 91 92 class DTPType(DtpGenericTlv): 93 name = "DTP Type" 94 fields_desc = [ ShortField("type", 3), 95 FieldLenField("length", None, "dtptype", adjust=lambda pkt,x:x + 4), 96 StrLenField("dtptype", b"\xa5", length_from=lambda pkt:pkt.length - 4) 97 ] 98 99 class DTPNeighbor(DtpGenericTlv): 100 name = "DTP Neighbor" 101 fields_desc = [ ShortField("type", 4), 102 #FieldLenField("length", None, "neighbor", adjust=lambda pkt,x:x + 4), 103 ShortField("len", 10), 104 MACField("neighbor", None) 105 ] 106 107 def _DTPGuessPayloadClass(p, **kargs): 108 cls = conf.raw_layer 109 if len(p) >= 2: 110 t = struct.unpack("!H", p[:2])[0] 111 clsname = _DTP_TLV_CLS.get(t, "DtpGenericTlv") 112 cls = globals()[clsname] 113 return cls(p, **kargs) 114 115 class DTP(Packet): 116 name = "DTP" 117 fields_desc = [ ByteField("ver", 1), 118 RepeatedTlvListField("tlvlist", [], _DTPGuessPayloadClass) 119 ] 120 121 bind_layers(SNAP, DTP, code=0x2004, OUI=0xc) 122 123 124 def negotiate_trunk(iface=conf.iface, mymac=str(RandMAC())): 125 print("Trying to negotiate a trunk on interface %s" % iface) 126 p = Dot3(src=mymac, dst="01:00:0c:cc:cc:cc")/LLC()/SNAP()/DTP(tlvlist=[DTPDomain(),DTPStatus(),DTPType(),DTPNeighbor(neighbor=mymac)]) 127 sendp(p) 128 129 if __name__ == "__main__": 130 from scapy.main import interact 131 interact(mydict=globals(), mybanner="DTP") 132