huangcm
2024-12-18 9d29be7f7249789d6ffd0440067187a9f040c2cd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/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")