Hi David, Sorry for the late response. I could recreate this issue. There are two things contributing to it:
* We currently don't handle RTM_IFANNOUNCE when interfaces are deleted * FreeBSD immediately reuses indices of deleted network devices We use the indices to match events received via PF_ROUTE to our cached interface objects. But we never remove these objects because we currently don't handle the RTM_IFANNOUNCE message. So if an interface is deleted and a new one is created with a previously used index the name of the cached object will not match the actual name of the interface: > 06[KNL] interface tun0 deactivated > ... > 08[KNL] 192.168.254.1 disappeared from tun1 > 07[IKE] installing new virtual IP 192.168.254.1 > 08[KNL] interface tun1 deactivated > 07[LIB] created TUN device: tun2 > 16[KNL] interface tun0 activated > 16[KNL] fe80::f2de:f1ff:fead:512f appeared on tun0 > 05[KNL] 192.168.254.1 appeared on tun0 As can be seen, the cache entry for tun0 was not removed even though it was deactivated and deleted a while ago. tun2 now uses the same index as tun0 did, so the kernel-pfroute plugin associates the following events with the cached entry for tun0. Of course, this causes problems later e.g. when installing routes via TUN device, as the cached name (tun0) will be used. The attached patch adds support for RTM_ANNOUNCE messages, so cached interfaces are properly deleted when they disappear from the system. As a workaround you can disable reauthentication with reauth=no. The IKE_SA will then be rekeyed inline without affecting virtual IPs and TUN devices. Regards, Tobias
>From f34d78001bb878ef8d006132af73cac07c366f3f Mon Sep 17 00:00:00 2001 From: Tobias Brunner <[email protected]> Date: Fri, 25 Jul 2014 18:07:08 +0200 Subject: [PATCH] kernel-pfroute: Delete interfaces on RTM_IFANNOUNCE/IFAN_DEPARTURE events We actually never deleted cached interfaces. So if the kernel reuses interface indices events for newly created interfaces could have been associated with interface objects of deactivated and deleted interfaces. Since we also didn't update the interface name when such an interface got reactivated we ended up using the old name e.g. to install routes. A trigger for this was the deletion and recreation of TUN devices during reauthentication of SAs that use virtual IPs. --- .../plugins/kernel_pfroute/kernel_pfroute_net.c | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c b/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c index c4e8664..afe368b 100644 --- a/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c +++ b/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c @@ -876,6 +876,37 @@ static void process_link(private_kernel_pfroute_net_t *this, } /** + * Process an RTM_IFANNOUNCE message from the kernel + */ +static void process_announce(private_kernel_pfroute_net_t *this, + struct if_announcemsghdr *msg) +{ + enumerator_t *enumerator; + iface_entry_t *iface; + + if (msg->ifan_what != IFAN_DEPARTURE) + { + /* we handle new interfaces in process_link() */ + return; + } + + this->lock->write_lock(this->lock); + enumerator = this->ifaces->create_enumerator(this->ifaces); + while (enumerator->enumerate(enumerator, &iface)) + { + if (iface->ifindex == msg->ifan_index) + { + DBG1(DBG_KNL, "interface %s disappeared", iface->ifname); + this->ifaces->remove_at(this->ifaces, enumerator); + iface_entry_destroy(iface); + break; + } + } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); +} + +/** * Process an RTM_*ROUTE message from the kernel */ static void process_route(private_kernel_pfroute_net_t *this, @@ -895,6 +926,7 @@ static bool receive_events(private_kernel_pfroute_net_t *this, int fd, struct rt_msghdr rtm; struct if_msghdr ifm; struct ifa_msghdr ifam; + struct if_announcemsghdr ifanm; }; char buf[sizeof(struct sockaddr_storage) * RTAX_MAX]; } msg; @@ -935,6 +967,9 @@ static bool receive_events(private_kernel_pfroute_net_t *this, int fd, case RTM_IFINFO: hdrlen = sizeof(msg.ifm); break; + case RTM_IFANNOUNCE: + hdrlen = sizeof(msg.ifanm); + break; case RTM_ADD: case RTM_DELETE: case RTM_GET: @@ -957,6 +992,9 @@ static bool receive_events(private_kernel_pfroute_net_t *this, int fd, case RTM_IFINFO: process_link(this, &msg.ifm); break; + case RTM_IFANNOUNCE: + process_announce(this, &msg.ifanm); + break; case RTM_ADD: case RTM_DELETE: process_route(this, &msg.rtm); -- 1.9.1
_______________________________________________ Dev mailing list [email protected] https://lists.strongswan.org/mailman/listinfo/dev
