]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
kernel-pfroute: Delete interfaces on RTM_IFANNOUNCE/IFAN_DEPARTURE events
authorTobias Brunner <tobias@strongswan.org>
Fri, 25 Jul 2014 16:07:08 +0000 (18:07 +0200)
committerTobias Brunner <tobias@strongswan.org>
Tue, 9 Sep 2014 08:56:15 +0000 (10:56 +0200)
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.

src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c

index 32157bbb4a581b7bb916212c2980892d3a878eab..8121969fd132b416abf2622a3cb5fdb18d6e5bba 100644 (file)
@@ -875,6 +875,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
  */
@@ -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);