Skip to content

Commit

Permalink
Small addition to grafolean fix (comments, endianness hint)
Browse files Browse the repository at this point in the history
  • Loading branch information
bitkeks committed Jul 2, 2022
1 parent 92b221a commit 7ea24a9
Showing 1 changed file with 13 additions and 8 deletions.
21 changes: 13 additions & 8 deletions netflow/v9.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,15 @@

import ipaddress
import struct
import sys

from .ipfix import IPFIXFieldTypes, IPFIXDataTypes

__all__ = ["V9DataFlowSet", "V9DataRecord", "V9ExportPacket", "V9Header", "V9TemplateField",
"V9TemplateFlowSet", "V9TemplateNotRecognized", "V9TemplateRecord",
"V9OptionsTemplateFlowSet", "V9OptionsTemplateRecord", "V9OptionsDataRecord"]


FIELD_TYPES_CONTAINING_IP = [8, 12, 27, 28]

V9_FIELD_TYPES_CONTAINING_IP = [8, 12, 15, 18, 27, 28, 62, 63]

V9_FIELD_TYPES = {
0: 'UNKNOWN_FIELD_TYPE', # fallback for unknown field types
Expand Down Expand Up @@ -209,7 +208,8 @@ def __init__(self, data, template):
padding_size = 4 - (self.length % 4) # 4 Byte

# For performance reasons, we use struct.unpack to get individual values. Here
# we prepare the format string for parsing it:
# we prepare the format string for parsing it. The format string is based on the template fields and their
# lengths. The string can then be re-used for every data record in the data stream
struct_format = '!'
struct_len = 0
for field in template.fields:
Expand All @@ -226,6 +226,8 @@ def __init__(self, data, template):
struct_len += flen

while offset <= (self.length - padding_size):
# Here we actually unpack the values, the struct format string is used in every data record
# iteration, until the final offset reaches the end of the whole data stream
unpacked_values = struct.unpack(struct_format, data[offset:offset + struct_len])

new_record = V9DataRecord()
Expand All @@ -235,7 +237,7 @@ def __init__(self, data, template):

# Special handling of IP addresses to convert integers to strings to not lose precision in dump
# TODO: might only be needed for IPv6
if field.field_type in FIELD_TYPES_CONTAINING_IP:
if field.field_type in V9_FIELD_TYPES_CONTAINING_IP:
try:
ip = ipaddress.ip_address(value)
except ValueError:
Expand All @@ -247,6 +249,9 @@ def __init__(self, data, template):
new_record.data[fkey] = value
else:
# Caveat: this code assumes little-endian system (like x86)
if sys.byteorder != "little":
print("v9.py uses bit shifting for little endianness. Your processor is not little endian")

fdata = 0
for idx, byte in enumerate(reversed(bytearray(value))):
fdata += byte << (idx * 8)
Expand Down Expand Up @@ -394,7 +399,7 @@ def __init__(self, data: bytes, template: V9OptionsTemplateRecord):

for scope_type, length in template.scope_fields.items():
type_name = V9_SCOPE_TYPES.get(scope_type, scope_type) # Either name, or unknown int
value = int.from_bytes(data[offset:offset+length], 'big') # TODO: is this always integer?
value = int.from_bytes(data[offset:offset + length], 'big') # TODO: is this always integer?
new_options_record.scopes[type_name] = value
offset += length

Expand All @@ -413,9 +418,9 @@ def __init__(self, data: bytes, template: V9OptionsTemplateRecord):

value = None
if is_bytes:
value = data[offset:offset+length]
value = data[offset:offset + length]
else:
value = int.from_bytes(data[offset:offset+length], 'big')
value = int.from_bytes(data[offset:offset + length], 'big')

new_options_record.data[type_name] = value

Expand Down

0 comments on commit 7ea24a9

Please sign in to comment.