Open insecure opened 3 years ago
#!/usr/bin/env python3
import shlex
import subprocess
import pyroute2
def main():
netns_name = "pyroute2_del_rule_bug"
pyroute2.netns.create(netns_name)
pyroute2.netns.pushns(netns_name)
# Create rules with different priorities and specify dst IPs
rules_to_create = [
{"iif": "lo", "to": "1.2.3.5", "table": 666, "pref": 5000},
{"iif": "lo", "to": "1.2.3.6", "table": 666, "pref": 5000},
{"iif": "lo", "to": "1.2.3.7", "table": 666, "pref": 5000}
]
for rule_data in rules_to_create:
rule_command = (
f"ip rule add iif {rule_data['iif']} to {rule_data['to']} "
f"lookup {rule_data['table']} pref {rule_data['pref']}"
)
subprocess.call(shlex.split(rule_command))
print(" === ip rule show lookup 666 ===")
subprocess.call(shlex.split("ip rule show lookup 666"))
try:
with pyroute2.IPDB(nl=pyroute2.NetNS(netns_name)) as ipdb:
# Define the criteria for the rule you want to delete
delete_rule_criteria = {"dst": "1.2.3.7/32", "iifname": "lo", "priority": 5000}
# Find the rule that matches the criteria
matching_rule = None
for rule in ipdb.rules:
if all(rule.get(key) == value for key, value in delete_rule_criteria.items()):
matching_rule = rule
break
if matching_rule:
print(f"\n* deleting rule {matching_rule}")
matching_rule.remove()
else:
print("No matching rule found to delete.")
finally:
print("\n === ip rule show lookup 666 ===")
subprocess.call(shlex.split("ip rule show lookup 666"))
pyroute2.netns.popns()
pyroute2.netns.remove(netns_name)
if __name__ == '__main__':
main()
Deleting a routing policy (rule) fails if another rule with the same priority exists. If
pref
is not specified when creating the rules, the priorities are different and everything works fine.I have written an example demonstrating the behaviour. The NetNS code is only used so we do not accidentally screw up the current system. It is also reproducible without using a dedicated Linux network namespace.
When I run this code, I see:
I would expect to see that the rule with destination IP 1.2.3.7 has been deleted. Instead the rule with destination IP 1.2.3.5 is deleted.
I saw this behaviour with pyroute2 0.5.13 and also with 0.5.3 (without the netns code, of course).