Commit 9cb1b14c authored by Léo-Paul Géneau's avatar Léo-Paul Géneau 👾

Fix: check mrule existence before deletion

Avoid message: "RTNETLINK answers: No such file or directory"
parent 56668000
......@@ -3,9 +3,11 @@ import socket
import struct
import ipaddress
import traceback
from socket import if_nametoindex
from socket import if_nametoindex, AF_INET, AF_INET6
from threading import RLock, Thread
from abc import abstractmethod, ABCMeta
from functools import partial
from pyroute2 import IPRoute
from pimdm import UnicastRouting, Main
from pimdm.rwlock.RWLock import RWLockWrite
......@@ -23,6 +25,10 @@ class Kernel(metaclass=ABCMeta):
# Max Number of Virtual Interfaces
MAXVIFS = 32
# Rtnetlink flags
RTNL_FAMILY_IPMR = 128
RTNL_FAMILY_IP6MR = RTNL_FAMILY_IPMR + 1
def __init__(self, kernel_socket):
# Kernel is running
self.running = True
......@@ -50,6 +56,12 @@ class Kernel(metaclass=ABCMeta):
self.interface_logger = Main.logger.getChild('KernelInterface')
self.tree_logger = Main.logger.getChild('KernelTree')
# netlink interfacing
self.ipr = IPRoute()
# unformatted mrule command
self.to_format_mrule = "ip {ip_version} mrule {cmd} {selector} {interface_name} lookup {table_id}".format
# receive signals from kernel with a background thread
handler_thread = Thread(target=self.handler)
handler_thread.daemon = True
......@@ -258,6 +270,32 @@ class Kernel(metaclass=ABCMeta):
for entry in groups_dict.values():
entry.new_or_reset_neighbor(vif_index, neighbor_ip)
def ex_partial_mrule(self, partial_mrule: partial, ip_family: int):
os.system(partial_mrule(ip_version='-6' if ip_family == AF_INET6 else ''))
def add_mrule(self, interface_name: str, table_id: int, ip_family=AF_INET):
partial_mrule = partial(self.to_format_mrule, cmd='add', interface_name=interface_name, table_id=table_id)
self.ex_partial_mrule(partial(partial_mrule, selector='iif'), ip_family)
self.ex_partial_mrule(partial(partial_mrule, selector='oif'), ip_family)
def delete_mrule(self, interface_name: str, table_id: int, ip_family=AF_INET):
partial_mrule = partial(self.to_format_mrule, cmd='del', interface_name=interface_name, table_id=table_id)
for rule in self.ipr.get_rules(
family=self.RTNL_FAMILY_IP6MR if ip_family == AF_INET6 else self.RTNL_FAMILY_IPMR,
table=table_id
):
for k,v in rule['attrs']:
if k == 'FRA_IIFNAME':
if v == interface_name:
self.ex_partial_mrule(partial(partial_mrule, selector='iif'), ip_family)
else:
break
elif k == 'FRA_OIFNAME':
if v == interface_name:
self.ex_partial_mrule(partial(partial_mrule, selector='oif'), ip_family)
else:
break
class Kernel4(Kernel):
# MRT
......@@ -329,11 +367,9 @@ class Kernel4(Kernel):
struct_mrt_add_vif = struct.pack("HBBI 4s 4s", index, flags, 1, 0, ip_interface,
socket.inet_aton("0.0.0.0"))
os.system("ip mrule del iif {}".format(interface_name))
os.system("ip mrule del oif {}".format(interface_name))
self.delete_mrule(interface_name, 0)
if pim_globals.MULTICAST_TABLE_ID != 0:
os.system("ip mrule add iif {} lookup {}".format(interface_name, pim_globals.MULTICAST_TABLE_ID))
os.system("ip mrule add oif {} lookup {}".format(interface_name, pim_globals.MULTICAST_TABLE_ID))
self.add_mrule(interface_name, pim_globals.MULTICAST_TABLE_ID)
with self.rwlock.genWlock():
self.socket.setsockopt(socket.IPPROTO_IP, self.MRT_ADD_VIF, struct_mrt_add_vif)
self.vif_index_to_name_dic[index] = interface_name
......@@ -350,8 +386,7 @@ class Kernel4(Kernel):
index = self.vif_name_to_index_dic.pop(interface_name)
struct_vifctl = struct.pack("HBBI 4s 4s", index, 0, 0, 0, socket.inet_aton("0.0.0.0"), socket.inet_aton("0.0.0.0"))
os.system("ip mrule del iif {}".format(interface_name))
os.system("ip mrule del oif {}".format(interface_name))
self.delete_mrule(interface_name, 0)
self.socket.setsockopt(socket.IPPROTO_IP, self.MRT_DEL_VIF, struct_vifctl)
self.stop_forwarding(index)
......@@ -563,11 +598,9 @@ class Kernel6(Kernel):
physical_if_index = if_nametoindex(interface_name)
struct_mrt_add_vif = struct.pack("HBBHI", index, flags, 1, physical_if_index, 0)
os.system("ip -6 mrule del iif {}".format(interface_name))
os.system("ip -6 mrule del oif {}".format(interface_name))
self.delete_mrule(interface_name, 0, AF_INET6)
if pim_globals.MULTICAST_TABLE_ID != 0:
os.system("ip -6 mrule add iif {} lookup {}".format(interface_name, pim_globals.MULTICAST_TABLE_ID))
os.system("ip -6 mrule add oif {} lookup {}".format(interface_name, pim_globals.MULTICAST_TABLE_ID))
self.add_mrule(interface_name, pim_globals.MULTICAST_TABLE_ID, AF_INET6)
with self.rwlock.genWlock():
self.socket.setsockopt(socket.IPPROTO_IPV6, self.MRT6_ADD_MIF, struct_mrt_add_vif)
......@@ -588,8 +621,7 @@ class Kernel6(Kernel):
struct_vifctl = struct.pack("HBBHI", mif_index, 0, 0, physical_if_index, 0)
self.socket.setsockopt(socket.IPPROTO_IPV6, self.MRT6_DEL_MIF, struct_vifctl)
os.system("ip -6 mrule del iif {}".format(interface_name))
os.system("ip -6 mrule del oif {}".format(interface_name))
self.delete_mrule(interface_name, 0)
self.stop_forwarding(mif_index)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment