Skip to content

Commit 9715d38

Browse files
committed
revised dpkt engine workflow
1 parent 49e57bb commit 9715d38

File tree

1 file changed

+56
-39
lines changed

1 file changed

+56
-39
lines changed

pcapkit/foundation/engines/dpkt.py

Lines changed: 56 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,15 @@
2020
__all__ = ['DPKT']
2121

2222
if TYPE_CHECKING:
23-
from typing import Iterator
23+
from typing import Type, Union, Optional
2424

2525
from dpkt.dpkt import Packet as DPKTPacket
26+
from dpkt.pcap import Reader as PCAPReader
27+
from dpkt.pcapng import Reader as PCAPNGReader
2628

2729
from pcapkit.foundation.extraction import Extractor
28-
from pcapkit.protocols.misc.pcap.header import Header
30+
31+
Reader = Union[PCAPReader, PCAPNGReader]
2932

3033

3134
class DPKT(Engine['DPKTPacket']):
@@ -36,12 +39,6 @@ class DPKT(Engine['DPKTPacket']):
3639
3740
"""
3841

39-
if TYPE_CHECKING:
40-
#: Global header.
41-
_gbhdr: 'Header'
42-
#: Data link layer protocol.
43-
_dlink: 'Enum_LinkType'
44-
4542
##########################################################################
4643
# Properties.
4744
##########################################################################
@@ -64,7 +61,7 @@ def __init__(self, extractor: 'Extractor') -> 'None':
6461
import dpkt # isort:skip
6562

6663
self._expkg = dpkt
67-
self._extmp = cast('Iterator[tuple[float, DPKTPacket]]', None)
64+
self._extmp = cast('Reader', None)
6865

6966
super().__init__(extractor)
7067

@@ -112,34 +109,8 @@ def run(self) -> 'None':
112109
reader = dpkt.pcapng.Reader(ext._ifile)
113110
else:
114111
raise FormatError(f'unsupported file format: {ext.magic_number!r}')
115-
self._dlink = Enum_LinkType.get(reader.datalink())
116-
117-
if self._dlink == Enum_LinkType.ETHERNET:
118-
pkg = dpkt.ethernet.Ethernet
119-
elif self._dlink.value == Enum_LinkType.IPV4:
120-
pkg = dpkt.ip.IP
121-
elif self._dlink.value == Enum_LinkType.IPV6:
122-
pkg = dpkt.ip6.IP6
123-
else:
124-
warn('unrecognised link layer protocol; all analysis functions ignored',
125-
DPKTWarning, stacklevel=stacklevel())
126-
127-
class RawPacket(dpkt.dpkt.Packet): # type: ignore[name-defined]
128-
"""Raw packet."""
129-
130-
def __len__(ext) -> 'int':
131-
return len(ext.data)
132-
133-
def __bytes__(ext) -> 'bytes':
134-
return ext.data
135-
136-
def unpack(ext, buf: 'bytes') -> 'None':
137-
ext.data = buf
138-
139-
pkg = RawPacket
140112

141113
# extract & analyse file
142-
self._expkg = pkg
143114
self._extmp = reader
144115

145116
def read_frame(self) -> 'DPKTPacket':
@@ -156,9 +127,13 @@ def read_frame(self) -> 'DPKTPacket':
156127
tcp_reassembly, tcp_traceflow)
157128
ext = self._extractor
158129

130+
reader = self._extmp
131+
linktype = Enum_LinkType.get(reader.datalink())
132+
159133
# fetch DPKT packet
160-
timestamp, pkt = cast('tuple[float, bytes]', next(self._extmp))
161-
packet = self._expkg(pkt) # type: DPKTPacket
134+
timestamp, pkt = cast('tuple[float, bytes]', next(reader))
135+
protocol = self._get_protocol(linktype)
136+
packet = protocol(pkt) # type: DPKTPacket
162137

163138
# verbose output
164139
ext._frnum += 1
@@ -167,7 +142,7 @@ def read_frame(self) -> 'DPKTPacket':
167142
# write plist
168143
frnum = f'Frame {ext._frnum}'
169144
if not ext._flag_q:
170-
info = packet2dict(packet, timestamp, data_link=self._dlink)
145+
info = packet2dict(packet, timestamp, data_link=linktype)
171146
if ext._flag_f:
172147
ofile = ext._ofile(f'{ext._ofnm}/{frnum}.{ext._fext}')
173148
ofile(info, name=frnum)
@@ -194,7 +169,7 @@ def read_frame(self) -> 'DPKTPacket':
194169
# trace flows
195170
if ext._flag_t:
196171
if ext._tcp:
197-
data_tf_tcp = tcp_traceflow(packet, timestamp, data_link=self._dlink, count=ext._frnum)
172+
data_tf_tcp = tcp_traceflow(packet, timestamp, data_link=linktype, count=ext._frnum)
198173
if data_tf_tcp is not None:
199174
ext._trace.tcp(data_tf_tcp)
200175

@@ -206,3 +181,45 @@ def read_frame(self) -> 'DPKTPacket':
206181

207182
# return frame record
208183
return packet
184+
185+
##########################################################################
186+
# Utilities.
187+
##########################################################################
188+
189+
def _get_protocol(self, linktype: 'Optional[Enum_LinkType]' = None) -> 'Type[DPKTPacket]':
190+
"""Returns the protocol for parsing the current packet.
191+
192+
Args:
193+
linktype: Link type code.
194+
195+
"""
196+
dpkt = self._expkg
197+
reader = self._extmp
198+
199+
if linktype is None:
200+
linktype = Enum_LinkType.get(reader.datalink())
201+
202+
if linktype == Enum_LinkType.ETHERNET:
203+
pkg = dpkt.ethernet.Ethernet
204+
elif linktype.value == Enum_LinkType.IPV4:
205+
pkg = dpkt.ip.IP
206+
elif linktype.value == Enum_LinkType.IPV6:
207+
pkg = dpkt.ip6.IP6
208+
else:
209+
warn('unrecognised link layer protocol; all analysis functions ignored',
210+
DPKTWarning, stacklevel=stacklevel())
211+
212+
class RawPacket(dpkt.dpkt.Packet): # type: ignore[name-defined]
213+
"""Raw packet."""
214+
215+
def __len__(ext) -> 'int':
216+
return len(ext.data)
217+
218+
def __bytes__(ext) -> 'bytes':
219+
return ext.data
220+
221+
def unpack(ext, buf: 'bytes') -> 'None':
222+
ext.data = buf
223+
224+
pkg = RawPacket
225+
return pkg

0 commit comments

Comments
 (0)