Skip to content

Commit 73d61ba

Browse files
committed
use unpack_from
1 parent 78f153a commit 73d61ba

File tree

4 files changed

+19
-17
lines changed

4 files changed

+19
-17
lines changed

lib/ipflow/flowset.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@
66

77
def on_flowset_template(
88
line: bytes,
9+
pos: int,
10+
pos_end: int,
911
source: str,
1012
source_id: int,
1113
source_uptime: int,
1214
):
13-
pos = 0
14-
while pos < len(line):
15-
template_id, field_count = struct.unpack('>HH', line[pos:pos+4])
15+
while pos < pos_end:
16+
template_id, field_count = struct.unpack_from('>HH', line, pos)
1617
# rfc 3954 5.1
1718
# NetFlow Collectors SHOULD use the combination of the source IP
1819
# address and the Source ID field to separate different export
@@ -24,7 +25,7 @@ def on_flowset_template(
2425
continue
2526

2627
fields = [
27-
Field(*struct.unpack('>HH', line[i:i+4]))
28+
Field(*struct.unpack_from('>HH', line, i))
2829
for i in range(pos + 4, pos + 4 + field_count * 4, 4)
2930
]
3031

@@ -40,14 +41,15 @@ def on_flowset_template(
4041

4142
def on_flowset(
4243
line: bytes,
44+
pos: int,
45+
pos_end: int,
4346
flowset_id: int,
4447
source: str,
4548
source_id: int,
4649
):
4750
key = source, source_id, flowset_id
4851
template = flowset_templates.get(key)
4952
if template:
50-
fmt = template._fmt
51-
pad = len(line) % template.length
52-
for values in struct.iter_unpack(fmt, line[:-pad] if pad else line):
53-
yield Flow(template, values)
53+
# assume 3 padding
54+
for i in range(pos, pos_end - 3, template.length):
55+
yield Flow(template, template._fmt.unpack_from(line, i))

lib/ipflow/parser.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,31 +15,30 @@ def on_packet(line: bytes, source: str):
1515
unix_secs,
1616
sequence_number,
1717
source_id,
18-
) = struct.unpack(HEADER_FMT, line[:HEADER_SIZE])
18+
) = struct.unpack_from(HEADER_FMT, line)
1919

2020
# we don't use header.count because it includes the Options Template
2121
# FlowSets (FlowSet ID 1), which we ignore
2222
pos = HEADER_SIZE
2323
while pos + 4 < len(line):
24-
flowset_id, length = struct.unpack('>HH', line[pos:pos+4])
24+
flowset_id, length = struct.unpack_from('>HH', line, pos)
2525

2626
# prevent endless loop
2727
if length == 0:
2828
logging.error('failed to parse packet')
2929
break
3030

31-
flowset = line[pos+4:pos+length]
32-
pos += length
33-
3431
if flowset_id == 0:
3532
try:
36-
on_flowset_template(flowset, source, source_id, sysuptime)
33+
on_flowset_template(line, pos + 4, pos + length, source,
34+
source_id, sysuptime)
3735
except Exception:
3836
logging.error('failed to parse FlowSet template')
3937
break
4038
elif flowset_id > 255:
4139
try:
42-
for flow in on_flowset(flowset, flowset_id, source, source_id):
40+
for flow in on_flowset(line, pos + 4, pos + length, flowset_id,
41+
source, source_id):
4342
yield flow
4443
except Exception:
4544
logging.warning('failed to parse FlowSet')

lib/ipflow/template.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import struct
12
from typing import List
23
from .field import Field
34

@@ -13,7 +14,7 @@ class DataTemplate:
1314

1415
def __init__(self, fmt: str, length: int, fields: List[Field],
1516
index: List[int], source_uptime: int):
16-
self._fmt = fmt
17+
self._fmt = struct.Struct(fmt)
1718
self.fields = fields
1819
self.index = index
1920
self.length = length

lib/subscription.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66

77
class Subscription(NamedTuple):
8-
address: Union[IPv4Address, IPv4Address]
8+
address: Union[IPv4Address, IPv6Address]
99
result: List[Flow]
1010
timestamp: int
1111

0 commit comments

Comments
 (0)