Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into debian-files-update
Browse files Browse the repository at this point in the history
  • Loading branch information
Dan Fuhry committed Feb 27, 2017
2 parents bd0928e + a71f64f commit d0fab0d
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 14 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
/.pybuild/
*.egg-info

# Debian build related files
/debian/python-iptables/
/debian/python3-iptables/
/debian/python-iptables-dbg/
Expand All @@ -31,3 +32,6 @@
/debian/*-stamp
/debian/*.substvars


# Added exclusion for PyCharm files
.idea/*
45 changes: 40 additions & 5 deletions iptc/ip4tc.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
except:
pass

# Add IPPROTO_SCTP to socket module if not available
if not hasattr(socket, 'IPPROTO_SCTP'):
setattr(socket, 'IPPROTO_SCTP', 132)

_IFNAMSIZ = 16

_libc = ct.CDLL("libc.so.6")
Expand Down Expand Up @@ -662,7 +666,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
Expand All @@ -672,6 +676,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")
Expand All @@ -682,6 +687,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
Expand Down Expand Up @@ -831,6 +858,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):
"""
Expand Down Expand Up @@ -905,6 +936,7 @@ class Rule(object):
socket.IPPROTO_RAW: "raw",
socket.IPPROTO_ROUTING: "routing",
socket.IPPROTO_RSVP: "rsvp",
socket.IPPROTO_SCTP: "sctp",
socket.IPPROTO_TCP: "tcp",
socket.IPPROTO_TP: "tp",
socket.IPPROTO_UDP: "udp",
Expand Down Expand Up @@ -960,11 +992,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

Expand Down Expand Up @@ -1207,7 +1239,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
Expand Down
18 changes: 9 additions & 9 deletions tests/test_iptc.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ def test_rule_interface(self):
def test_rule_protocol(self):
rule = iptc.Rule6()
for proto in ["tcp", "udp", "icmp", "AH", "ESP", "!TCP", "!UDP",
"!ICMP", "!ah", "!esp"]:
"!ICMP", "!ah", "!esp", "sctp", "!SCTP"]:
rule.protocol = proto
self.assertEquals(proto.lower(), rule.protocol)
for proto in ["", "asdf", "!"]:
Expand All @@ -447,10 +447,10 @@ def test_rule_protocol(self):

def test_rule_protocol_numeric(self):
rule = iptc.Rule6()
rule.protocol = 132
self.assertEquals(rule.protocol, '132')
rule.protocol = '!132'
self.assertEquals(rule.protocol, '!132')
rule.protocol = 33
self.assertEquals(rule.protocol, '33')
rule.protocol = '!33'
self.assertEquals(rule.protocol, '!33')

def test_rule_compare(self):
r1 = iptc.Rule6()
Expand Down Expand Up @@ -677,10 +677,10 @@ def test_rule_protocol(self):

def test_rule_protocol_numeric(self):
rule = iptc.Rule()
rule.protocol = 132
self.assertEquals(rule.protocol, '132')
rule.protocol = '!132'
self.assertEquals(rule.protocol, '!132')
rule.protocol = 33
self.assertEquals(rule.protocol, '33')
rule.protocol = '!33'
self.assertEquals(rule.protocol, '!33')

def test_rule_compare(self):
r1 = iptc.Rule()
Expand Down

0 comments on commit d0fab0d

Please sign in to comment.