diff --git a/.gitignore b/.gitignore index eeb8a34..739a2eb 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,6 @@ /Vagrantfile /.vagrant /tags + +# Added exclusion for PyCharm files +.idea/* diff --git a/iptc/ip4tc.py b/iptc/ip4tc.py index 3c6d42a..19599a9 100644 --- a/iptc/ip4tc.py +++ b/iptc/ip4tc.py @@ -662,7 +662,7 @@ class Target(IPTCModule): does not take any value in the iptables extension, an empty string i.e. "" should be used. """ - def __init__(self, rule, name=None, target=None, revision=None): + def __init__(self, rule, name=None, target=None, revision=None, goto=None): """ *rule* is the Rule object this match belongs to; it can be changed later via *set_rule()*. *name* is the name of the iptables target @@ -672,6 +672,7 @@ def __init__(self, rule, name=None, target=None, revision=None): should be used; different revisions use different structures in C and they usually only work with certain kernel versions. Python-iptables by default will use the latest revision available. + If goto is True, then it converts '-j' to '-g'. """ if name is None and target is None: raise ValueError("can't create target based on nothing") @@ -682,6 +683,28 @@ def __init__(self, rule, name=None, target=None, revision=None): self._orig_parse = None self._orig_options = None + # NOTE: + # get_ip() returns the 'ip' structure that contains (1)the 'flags' field, and + # (2)the value for the GOTO flag. + # We *must* use get_ip() because the actual name of the field containing the + # structure apparently differs between implementation + ipstruct = rule.get_ip() + f_goto_attrs = [a for a in dir(ipstruct) if a.endswith('_F_GOTO')] + if len(f_goto_attrs) == 0: + raise RuntimeError('What kind of struct is this? It does not have "*_F_GOTO" constant!') + _F_GOTO = getattr(ipstruct, f_goto_attrs[0]) + + if target is not None or goto is None: + # We are 'decoding' existing Target + self._goto = bool(ipstruct.flags & _F_GOTO) + if goto is not None: + assert isinstance(goto, bool) + self._goto = goto + if goto: + ipstruct.flags |= _F_GOTO + else: + ipstruct.flags &= ~_F_GOTO + self._xt = xtables(rule.nfproto) module = (self._is_standard_target() and @@ -831,6 +854,10 @@ def _get_target(self): target = property(_get_target) """This is the C structure used by the extension.""" + def _get_goto(self): + return self._goto + goto = property(_get_goto) + class Policy(object): """ @@ -960,11 +987,11 @@ def create_match(self, name, revision=None): self.add_match(match) return match - def create_target(self, name, revision=None): + def create_target(self, name, revision=None, goto=False): """Create a new *target*, and set it as this rule's target. *name* is the name of the target extension, *revision* is the revision to - use.""" - target = Target(self, name=name, revision=revision) + use. *goto* determines if target uses '-j' (default) or '-g'.""" + target = Target(self, name=name, revision=revision, goto=goto) self.target = target return target @@ -1207,7 +1234,10 @@ def get_fragment(self): def set_fragment(self, frag): self.entry.ip.invflags &= ~ipt_ip.IPT_INV_FRAG & ipt_ip.IPT_INV_MASK - self.entry.ip.flags = int(bool(frag)) + if frag: + self.entry.ip.flags |= ipt_ip.IPT_F_FRAG + else: + self.entry.ip.flags &= ~ipt_ip.IPT_F_FRAG fragment = property(get_fragment, set_fragment) """This means that the rule refers to the second and further fragments of