Skip to content

Commit 242a4f0

Browse files
committed
Merge branch 'master' of https://github.com/ldx/python-iptables into issue230
2 parents 9446aa1 + 6f4ac9c commit 242a4f0

File tree

5 files changed

+39
-21
lines changed

5 files changed

+39
-21
lines changed

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ High level abstractions
141141
``python-iptables`` implements a low-level interface that tries to closely
142142
match the underlying C libraries. The module ``iptc.easy`` improves the
143143
usability of the library by providing a rich set of high-level functions
144-
designed to simplify the interaction with the library, for example::
144+
designed to simplify the interaction with the library, for example:
145145

146146
>>> import iptc
147147
>>> iptc.easy.dump_table('nat', ipv6=False)
@@ -160,6 +160,11 @@ designed to simplify the interaction with the library, for example::
160160
[{'protocol': 'tcp', 'target': 'ACCEPT', 'tcp': {'dport': '22'}}]
161161
>>> iptc.easy.delete_chain('filter', 'TestChain', flush=True)
162162

163+
>>> # Example of goto rule // iptables -A FORWARD -p gre -g TestChainGoto
164+
>>> iptc.easy.add_chain('filter', 'TestChainGoto')
165+
>>> rule_goto_d = {'protocol': 'gre', 'target': {'goto': 'TestChainGoto'}}
166+
>>> iptc.easy.insert_rule('filter', 'FORWARD', rule_goto_d)
167+
163168
Rules
164169
-----
165170

doc/examples.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ High level abstractions
77
``python-iptables`` implements a low-level interface that tries to closely
88
match the underlying C libraries. The module ``iptc.easy`` improves the
99
usability of the library by providing a rich set of high-level functions
10-
designed to simplify the interaction with the library, for example::
10+
designed to simplify the interaction with the library, for example:
1111

1212
>>> import iptc
1313
>>> iptc.easy.dump_table('nat', ipv6=False)
@@ -26,6 +26,11 @@ designed to simplify the interaction with the library, for example::
2626
[{'protocol': 'tcp', 'target': 'ACCEPT', 'tcp': {'dport': '22'}}]
2727
>>> iptc.easy.delete_chain('filter', 'TestChain', flush=True)
2828

29+
>>> # Example of goto rule // iptables -A FORWARD -p gre -g TestChainGoto
30+
>>> iptc.easy.add_chain('filter', 'TestChainGoto')
31+
>>> rule_goto_d = {'protocol': 'gre', 'target': {'goto': 'TestChainGoto'}}
32+
>>> iptc.easy.insert_rule('filter', 'FORWARD', rule_goto_d)
33+
2934
Rules
3035
-----
3136

iptc/easy.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,8 @@ def encode_iptc_rule(rule_d, ipv6=False):
295295
# Basic rule attributes
296296
rule_attr = ('src', 'dst', 'protocol', 'in-interface', 'out-interface', 'fragment')
297297
iptc_rule = Rule6() if ipv6 else Rule()
298+
# Set default target
299+
rule_d.setdefault('target', '')
298300
# Avoid issues with matches that require basic parameters to be configured first
299301
for name in rule_attr:
300302
if name in rule_d:
@@ -347,7 +349,10 @@ def decode_iptc_rule(iptc_rule, ipv6=False):
347349
name = iptc_rule.target.name.replace('-', '_')
348350
d['target'] = {name:iptc_rule.target.get_all_parameters()}
349351
elif iptc_rule.target and iptc_rule.target.name:
350-
d['target'] = iptc_rule.target.name
352+
if iptc_rule.target.goto:
353+
d['target'] = {'goto':iptc_rule.target.name}
354+
else:
355+
d['target'] = iptc_rule.target.name
351356
# Return a filtered dictionary
352357
return _filter_empty_field(d)
353358

@@ -412,10 +417,12 @@ def _iptc_setmatch(iptc_rule, name, value):
412417
def _iptc_settarget(iptc_rule, value):
413418
# Target is dictionary - Use only 1 pair key/value
414419
if isinstance(value, dict):
415-
for k, v in value.items():
416-
iptc_target = iptc_rule.create_target(k)
417-
_iptc_setattr_d(iptc_target, v)
418-
return
420+
t_name, t_value = next(iter(value.items()))
421+
if t_name == 'goto':
422+
iptc_target = iptc_rule.create_target(t_value, goto=True)
423+
else:
424+
iptc_target = iptc_rule.create_target(t_name)
425+
_iptc_setattr_d(iptc_target, t_value)
419426
# Simple target
420427
else:
421428
iptc_target = iptc_rule.create_target(value)

iptc/ip4tc.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,9 +1062,6 @@ def set_src(self, src):
10621062
saddr = _a_to_i(socket.inet_pton(socket.AF_INET, addr))
10631063
except socket.error:
10641064
raise ValueError("invalid address %s" % (addr))
1065-
ina = in_addr()
1066-
ina.s_addr = ct.c_uint32(saddr)
1067-
self.entry.ip.src = ina
10681065

10691066
if not netm.isdigit():
10701067
try:
@@ -1078,8 +1075,11 @@ def set_src(self, src):
10781075
nmask = socket.htonl((2 ** imask - 1) << (32 - imask))
10791076
neta = in_addr()
10801077
neta.s_addr = ct.c_uint32(nmask)
1081-
10821078
self.entry.ip.smsk = neta
1079+
# Apply subnet mask to IP address
1080+
ina = in_addr()
1081+
ina.s_addr = ct.c_uint32(saddr & nmask)
1082+
self.entry.ip.src = ina
10831083

10841084
src = property(get_src, set_src)
10851085
"""This is the source network address with an optional network mask in
@@ -1123,9 +1123,6 @@ def set_dst(self, dst):
11231123
daddr = _a_to_i(socket.inet_pton(socket.AF_INET, addr))
11241124
except socket.error:
11251125
raise ValueError("invalid address %s" % (addr))
1126-
ina = in_addr()
1127-
ina.s_addr = ct.c_uint32(daddr)
1128-
self.entry.ip.dst = ina
11291126

11301127
if not netm.isdigit():
11311128
try:
@@ -1140,6 +1137,10 @@ def set_dst(self, dst):
11401137
neta = in_addr()
11411138
neta.s_addr = ct.c_uint32(nmask)
11421139
self.entry.ip.dmsk = neta
1140+
# Apply subnet mask to IP address
1141+
ina = in_addr()
1142+
ina.s_addr = ct.c_uint32(daddr & nmask)
1143+
self.entry.ip.dst = ina
11431144

11441145
dst = property(get_dst, set_dst)
11451146
"""This is the destination network address with an optional network mask

tests/test_iptc.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -620,13 +620,13 @@ def tearDown(self):
620620
def test_rule_address(self):
621621
# valid addresses
622622
rule = iptc.Rule()
623-
for addr in [("127.0.0.1/255.255.255.0", "127.0.0.1/255.255.255.0"),
624-
("!127.0.0.1/255.255.255.0", "!127.0.0.1/255.255.255.0"),
625-
("127.0.0.1/255.255.128.0", "127.0.0.1/255.255.128.0"),
626-
("127.0.0.1/16", "127.0.0.1/255.255.0.0"),
627-
("127.0.0.1/24", "127.0.0.1/255.255.255.0"),
628-
("127.0.0.1/17", "127.0.0.1/255.255.128.0"),
629-
("!127.0.0.1/17", "!127.0.0.1/255.255.128.0")]:
623+
for addr in [("127.0.0.1/255.255.255.0", "127.0.0.0/255.255.255.0"),
624+
("!127.0.0.1/255.255.255.0", "!127.0.0.0/255.255.255.0"),
625+
("127.0.0.1/255.255.128.0", "127.0.0.0/255.255.128.0"),
626+
("127.0.0.1/16", "127.0.0.0/255.255.0.0"),
627+
("127.0.0.1/24", "127.0.0.0/255.255.255.0"),
628+
("127.0.0.1/17", "127.0.0.0/255.255.128.0"),
629+
("!127.0.0.1/17", "!127.0.0.0/255.255.128.0")]:
630630
rule.src = addr[0]
631631
self.assertEquals(rule.src, addr[1])
632632
rule.dst = addr[0]

0 commit comments

Comments
 (0)