Skip to content

Commit 1b8ad56

Browse files
committed
Move PPI to new layer file
1 parent 9e9561d commit 1b8ad56

File tree

5 files changed

+106
-77
lines changed

5 files changed

+106
-77
lines changed

scapy/contrib/ppi_cace.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
from scapy.packet import *
2727
from scapy.fields import *
2828
from scapy.layers.l2 import Ether
29-
from scapy.layers.dot11 import *
29+
from scapy.layers.ppi import addPPIType
3030

3131
PPI_DOT11COMMON = 2
3232
PPI_DOT11NMAC = 3

scapy/contrib/ppi_geotag.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
import time
2727
from scapy.packet import *
2828
from scapy.fields import *
29-
from scapy.layers.dot11 import *
29+
from scapy.layers.ppi import addPPIType
3030
from scapy.error import warning
3131
import scapy.modules.six as six
3232
from scapy.modules.six.moves import range

scapy/layers/bluetooth4LE.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from scapy.data import MTU, DLT_BLUETOOTH_LE_LL
1515
from scapy.packet import *
1616
from scapy.fields import *
17-
from scapy.layers import dot11
17+
from scapy.layers.ppi import PPI
1818

1919
from scapy.modules.six.moves import range
2020

@@ -123,7 +123,7 @@ def pre_dissect(self, s):
123123
return s[:4] + s[-3:] + s[4:-3]
124124

125125
def post_dissection(self, pkt):
126-
if isinstance(pkt, dot11.PPI):
126+
if isinstance(pkt, PPI):
127127
pkt.notdecoded = PPI_FieldHeader(pkt.notdecoded)
128128

129129
def hashret(self):
@@ -261,5 +261,5 @@ class BTLE_CONNECT_REQ(Packet):
261261

262262
conf.l2types.register(DLT_BLUETOOTH_LE_LL, BTLE)
263263

264-
bind_layers(dot11.PPI, BTLE, dlt=147)
264+
bind_layers(PPI, BTLE, dlt=147)
265265
bind_layers(PPI_FieldHeader, BTLE_PPI, pfh_type=30006)

scapy/layers/dot11.py

Lines changed: 0 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
# along with Scapy. If not, see <http://www.gnu.org/licenses/>.
1515

1616
# Copyright (C) Philippe Biondi <[email protected]>
17-
# Original PPI author: <[email protected]>
1817

1918
"""
2019
Wireless LAN according to IEEE 802.11.
@@ -218,74 +217,6 @@ def post_build(self, p, pay):
218217
return p + pay
219218

220219

221-
# Dictionary to map the TLV type to the class name of a sub-packet
222-
_ppi_types = {}
223-
224-
225-
def addPPIType(id, value):
226-
_ppi_types[id] = value
227-
228-
229-
def getPPIType(id, default="default"):
230-
return _ppi_types.get(id, _ppi_types.get(default, None))
231-
232-
233-
# Default PPI Field Header
234-
class PPIGenericFldHdr(Packet):
235-
name = "PPI Field Header"
236-
fields_desc = [LEShortField('pfh_type', 0),
237-
FieldLenField('pfh_length', None, length_of="value", fmt='<H', adjust=lambda p, x:x + 4),
238-
StrLenField("value", "", length_from=lambda p:p.pfh_length)]
239-
240-
def extract_padding(self, p):
241-
return b"", p
242-
243-
244-
def _PPIGuessPayloadClass(p, **kargs):
245-
""" This function tells the PacketListField how it should extract the
246-
TLVs from the payload. We pass cls only the length string
247-
pfh_len says it needs. If a payload is returned, that means
248-
part of the sting was unused. This converts to a Raw layer, and
249-
the remainder of p is added as Raw's payload. If there is no
250-
payload, the remainder of p is added as out's payload.
251-
"""
252-
if len(p) >= 4:
253-
t, pfh_len = struct.unpack("<HH", p[:4])
254-
# Find out if the value t is in the dict _ppi_types.
255-
# If not, return the default TLV class
256-
cls = getPPIType(t, "default")
257-
pfh_len += 4
258-
out = cls(p[:pfh_len], **kargs)
259-
if (out.payload):
260-
out.payload = conf.raw_layer(out.payload.load)
261-
out.payload.underlayer = out
262-
if (len(p) > pfh_len):
263-
out.payload.payload = conf.padding_layer(p[pfh_len:])
264-
out.payload.payload.underlayer = out.payload
265-
elif (len(p) > pfh_len):
266-
out.payload = conf.padding_layer(p[pfh_len:])
267-
out.payload.underlayer = out
268-
else:
269-
out = conf.raw_layer(p, **kargs)
270-
return out
271-
272-
273-
class PPI(Packet):
274-
name = "Per-Packet Information header (PPI)"
275-
fields_desc = [ByteField('version', 0),
276-
ByteField('flags', 0),
277-
FieldLenField('len', None, length_of="PPIFieldHeaders", fmt="<H", adjust=lambda p, x: x + 8),
278-
LEIntField('dlt', 1),
279-
PacketListField("PPIFieldHeaders", [], _PPIGuessPayloadClass, length_from=lambda p: p.len - 8,)]
280-
281-
def guess_payload_class(self, payload):
282-
return conf.l2types.get(self.dlt, Packet.guess_payload_class(self, payload))
283-
284-
285-
# Register PPI
286-
addPPIType("default", PPIGenericFldHdr)
287-
288-
289220
class Dot11(Packet):
290221
name = "802.11"
291222
fields_desc = [
@@ -764,8 +695,6 @@ class Dot11Ack(Packet):
764695

765696

766697
bind_layers(PrismHeader, Dot11,)
767-
bind_layers(PPI, Dot11, dlt=DLT_IEEE802_11)
768-
bind_layers(PPI, Ether, dlt=DLT_EN10MB)
769698
bind_layers(Dot11, LLC, type=2)
770699
bind_layers(Dot11QoS, LLC,)
771700
bind_layers(Dot11, Dot11AssoReq, subtype=0, type=0)
@@ -797,7 +726,6 @@ class Dot11Ack(Packet):
797726
conf.l2types.register_num2layer(802, PrismHeader)
798727
conf.l2types.register(DLT_IEEE802_11_RADIO, RadioTap)
799728
conf.l2types.register_num2layer(803, RadioTap)
800-
conf.l2types.register(DLT_PPI, PPI)
801729

802730

803731
class WiFi_am(AnsweringMachine):

scapy/layers/ppi.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# This file is part of Scapy
2+
# See http://www.secdev.org/projects/scapy for more informations
3+
# Scapy is free software: you can redistribute it and/or modify
4+
# it under the terms of the GNU General Public License as published by
5+
# the Free Software Foundation, either version 2 of the License, or
6+
# any later version.
7+
#
8+
# Scapy is distributed in the hope that it will be useful,
9+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
# GNU General Public License for more details.
12+
#
13+
# You should have received a copy of the GNU General Public License
14+
# along with Scapy. If not, see <http://www.gnu.org/licenses/>.
15+
16+
# Original PPI author: <[email protected]>
17+
18+
"""
19+
Per-Packet Information (PPI) Protocol
20+
"""
21+
22+
import struct
23+
24+
from scapy.config import conf
25+
from scapy.data import DLT_EN10MB, DLT_IEEE802_11, DLT_PPI
26+
from scapy.packet import bind_layers, Packet
27+
from scapy.fields import *
28+
from scapy.layers.l2 import Ether
29+
from scapy.layers.dot11 import Dot11
30+
31+
# Dictionary to map the TLV type to the class name of a sub-packet
32+
_ppi_types = {}
33+
34+
35+
def addPPIType(id, value):
36+
_ppi_types[id] = value
37+
38+
39+
def getPPIType(id, default="default"):
40+
return _ppi_types.get(id, _ppi_types.get(default, None))
41+
42+
43+
# Default PPI Field Header
44+
class PPIGenericFldHdr(Packet):
45+
name = "PPI Field Header"
46+
fields_desc = [LEShortField('pfh_type', 0),
47+
FieldLenField('pfh_length', None, length_of="value", fmt='<H', adjust=lambda p, x:x + 4),
48+
StrLenField("value", "", length_from=lambda p:p.pfh_length)]
49+
50+
def extract_padding(self, p):
51+
return b"", p
52+
53+
54+
def _PPIGuessPayloadClass(p, **kargs):
55+
""" This function tells the PacketListField how it should extract the
56+
TLVs from the payload. We pass cls only the length string
57+
pfh_len says it needs. If a payload is returned, that means
58+
part of the sting was unused. This converts to a Raw layer, and
59+
the remainder of p is added as Raw's payload. If there is no
60+
payload, the remainder of p is added as out's payload.
61+
"""
62+
if len(p) >= 4:
63+
t, pfh_len = struct.unpack("<HH", p[:4])
64+
# Find out if the value t is in the dict _ppi_types.
65+
# If not, return the default TLV class
66+
cls = getPPIType(t, "default")
67+
pfh_len += 4
68+
out = cls(p[:pfh_len], **kargs)
69+
if (out.payload):
70+
out.payload = conf.raw_layer(out.payload.load)
71+
out.payload.underlayer = out
72+
if (len(p) > pfh_len):
73+
out.payload.payload = conf.padding_layer(p[pfh_len:])
74+
out.payload.payload.underlayer = out.payload
75+
elif (len(p) > pfh_len):
76+
out.payload = conf.padding_layer(p[pfh_len:])
77+
out.payload.underlayer = out
78+
else:
79+
out = conf.raw_layer(p, **kargs)
80+
return out
81+
82+
83+
class PPI(Packet):
84+
name = "Per-Packet Information header (PPI)"
85+
fields_desc = [ByteField('version', 0),
86+
ByteField('flags', 0),
87+
FieldLenField('len', None, length_of="PPIFieldHeaders", fmt="<H", adjust=lambda p, x: x + 8),
88+
LEIntField('dlt', 1),
89+
PacketListField("PPIFieldHeaders", [], _PPIGuessPayloadClass, length_from=lambda p: p.len - 8,)]
90+
91+
def guess_payload_class(self, payload):
92+
return conf.l2types.get(self.dlt, Packet.guess_payload_class(self, payload))
93+
94+
95+
# Register PPI
96+
addPPIType("default", PPIGenericFldHdr)
97+
98+
conf.l2types.register(DLT_PPI, PPI)
99+
100+
bind_layers(PPI, Dot11, dlt=DLT_IEEE802_11)
101+
bind_layers(PPI, Ether, dlt=DLT_EN10MB)

0 commit comments

Comments
 (0)