Skip to content

Commit

Permalink
netlink: support complex structs in nlmsg.fields
Browse files Browse the repository at this point in the history
  • Loading branch information
svinota committed May 22, 2024
1 parent 8bea802 commit 5a8ebbb
Showing 1 changed file with 51 additions and 27 deletions.
78 changes: 51 additions & 27 deletions pyroute2/netlink/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1635,27 +1635,48 @@ def decode_nlas(self, offset):
# NLMSG fields codecs, mixin classes
#
class nlmsg_decoder_generic(object):
def ft_decode(self, offset):
@staticmethod
def ft_decode_field(fmt, data, offset):
global cache_fmt
##
# ~~ size = struct.calcsize(efmt)
#
# The use of the cache gives here a tiny performance
# improvement, but it is an improvement anyways
#
size = (
cache_fmt.get(fmt, None)
or cache_fmt.__setitem__(fmt, struct.calcsize(fmt))
or cache_fmt[fmt]
)
##
value = struct.unpack_from(fmt, data, offset)
offset += size
if len(value) == 1:
return value[0], offset
else:
return value, offset

@staticmethod
def ft_decode_str(data, offset):
(length,) = struct.unpack_from('H', data, offset)
(value,) = struct.unpack_from(f'{length}s', data, offset + 2)
offset += length + 2
return value.decode('utf-8'), offset

def ft_decode(self, offset):
for name, fmt in self.fields:
##
# ~~ size = struct.calcsize(efmt)
#
# The use of the cache gives here a tiny performance
# improvement, but it is an improvement anyways
#
size = (
cache_fmt.get(fmt, None)
or cache_fmt.__setitem__(fmt, struct.calcsize(fmt))
or cache_fmt[fmt]
)
##
value = struct.unpack_from(fmt, self.data, offset)
offset += size
if len(value) == 1:
self[name] = value[0]
else:
self[name] = value
if isinstance(fmt, str):
self[name], offset = self.ft_decode_field(
fmt, self.data, offset
)
elif fmt is str:
self[name], offset = self.ft_decode_str(self.data, offset)
elif isinstance(fmt, dict):
self[name] = fmt['struct'].decode(
self.data[offset : offset + fmt['length']]
)
offset += fmt['length']
# read NLA chain
if self.nla_map:
offset = (offset + 4 - 1) & ~(4 - 1)
Expand Down Expand Up @@ -1722,14 +1743,10 @@ def ft_encode(self, offset):
self.data.extend([0] * length)

# in python3 we should force it
if sys.version[0] == '3':
if isinstance(value, str):
value = bytes(value, 'utf-8')
elif isinstance(value, float):
value = int(value)
elif sys.version[0] == '2':
if isinstance(value, unicode):
value = value.encode('utf-8')
if isinstance(value, str):
value = bytes(value, 'utf-8')
elif isinstance(value, float):
value = int(value)

try:
if fmt[-1] == 'x':
Expand All @@ -1746,6 +1763,13 @@ def ft_encode(self, offset):

offset += length

for name in self.string_fields:
value = self[name]
length = len(value or '')
self.data.extend([0] * (length + 2))
struct.pack_into(f'H{length}s', self.data, offset, (length, value))
offset += length + 2

diff = ((offset + 4 - 1) & ~(4 - 1)) - offset
offset += diff
self.data.extend([0] * diff)
Expand Down

0 comments on commit 5a8ebbb

Please sign in to comment.