Skip to content

Commit e658176

Browse files
author
ldx
committed
Allocate target backing buffer via libc.
Since a few target extensions (currently SNAT and DNAT) think it's a good idea to manage the memory allocated to xt_entry_target themselves, we can't rely on ctypes buffers for backing it. Use malloc()/free() the C way instead, so extensions doing a realloc() will keep working. This fixes #31.
1 parent 0819a24 commit e658176

File tree

1 file changed

+19
-7
lines changed

1 file changed

+19
-7
lines changed

iptc/ip4tc.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@
1919
_libc = ct.CDLL("libc.so.6")
2020
_get_errno_loc = _libc.__errno_location
2121
_get_errno_loc.restype = ct.POINTER(ct.c_int)
22+
_malloc = _libc.malloc
23+
_malloc.restype = ct.POINTER(ct.c_ubyte)
24+
_malloc.argtypes = [ct.c_size_t]
25+
_free = _libc.free
26+
_free.restype = None
27+
_free.argtypes = [ct.POINTER(ct.c_ubyte)]
2228

2329

2430
def is_table_available(name):
@@ -556,9 +562,11 @@ def __init__(self, rule, name=None, target=None, revision=None):
556562
else:
557563
self._revision = self._module.revision
558564

559-
self._target_buf = (ct.c_ubyte * self.size)()
565+
self._target_buf = _malloc(self.size)
566+
if self._target_buf is None:
567+
raise Exception("Can't allocate target buffer")
560568
if target:
561-
ct.memmove(ct.byref(self._target_buf), ct.byref(target), self.size)
569+
ct.memmove(self._target_buf, ct.byref(target), self.size)
562570
self._update_pointers()
563571
self._update_parameters()
564572
else:
@@ -567,6 +575,10 @@ def __init__(self, rule, name=None, target=None, revision=None):
567575
if is_standard_target:
568576
self.standard_target = name
569577

578+
def __del__(self):
579+
if getattr(self, "_target_buf", None) and self._target_buf is not None:
580+
_free(self._target_buf)
581+
570582
def __eq__(self, targ):
571583
basesz = ct.sizeof(xt_entry_target)
572584
if (self.target.u.target_size != targ.target.u.target_size or
@@ -594,6 +606,8 @@ def _final_check(self):
594606
def _parse(self, argv, inv, entry):
595607
self._xt.parse_target(argv, inv, self._module, entry,
596608
ct.cast(self._ptrptr, ct.POINTER(ct.c_void_p)))
609+
self._target_buf = ct.cast(self._module.t, ct.POINTER(ct.c_ubyte))
610+
self._update_pointers()
597611

598612
def _get_size(self):
599613
return xt_align(self._module.size + ct.sizeof(xt_entry_target))
@@ -620,16 +634,15 @@ def _set_standard_target(self, name):
620634
into."""
621635

622636
def _update_pointers(self):
623-
self._ptr = ct.cast(ct.byref(self._target_buf),
624-
ct.POINTER(xt_entry_target))
637+
self._ptr = ct.cast(self._target_buf, ct.POINTER(xt_entry_target))
625638
self._ptrptr = ct.cast(ct.pointer(self._ptr),
626639
ct.POINTER(ct.POINTER(xt_entry_target)))
627640
self._module.t = self._ptr
628641

629642
def reset(self):
630643
"""Reset the target. Parameters are set to their default values, any
631644
flags are cleared."""
632-
ct.memset(ct.byref(self._target_buf), 0, self.size)
645+
ct.memset(self._target_buf, 0, self.size)
633646
self._update_pointers()
634647
t = self._ptr[0]
635648
t.u.user.name = self.name
@@ -640,8 +653,7 @@ def reset(self):
640653
self._module.tflags = 0
641654

642655
def _get_target(self):
643-
return ct.cast(ct.byref(self.target_buf),
644-
ct.POINTER(xt_entry_target))[0]
656+
return self._ptr[0]
645657
target = property(_get_target)
646658
"""This is the C structure used by the extension."""
647659

0 commit comments

Comments
 (0)