aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2014-07-25 18:07:08 +0200
committerTobias Brunner <tobias@strongswan.org>2014-09-09 10:56:15 +0200
commitf80093e2ee65f6b536a9df83da795fd2f91d77f8 (patch)
tree09c8372fb81a7d903595be707df0d552462468d5
parentf8613abc8a89e26ccf33298cbdf8a5e8c4009d1f (diff)
downloadstrongswan-f80093e2ee65f6b536a9df83da795fd2f91d77f8.tar.bz2
strongswan-f80093e2ee65f6b536a9df83da795fd2f91d77f8.tar.xz
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.
-rw-r--r--src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c b/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c
index 32157bbb4..8121969fd 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);