]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
nspawn: explicitly remove veth links after use (#3111)
authorLennart Poettering <lennart@poettering.net>
Mon, 25 Apr 2016 15:36:51 +0000 (17:36 +0200)
committerDaniel Mack <github@zonque.org>
Mon, 25 Apr 2016 15:36:51 +0000 (17:36 +0200)
* sd-netlink: permit RTM_DELLINK messages with no ifindex

This is useful for removing network interfaces by name.

* nspawn: explicitly remove veth links we created after use

Sometimes the kernel keeps veth links pinned after the namespace they have been
joined to died. Let's hence explicitly remove veth links after use.

Fixes: #2173
src/libsystemd/sd-netlink/rtnl-message.c
src/nspawn/nspawn-network.c
src/nspawn/nspawn-network.h
src/nspawn/nspawn.c

index 255526bf32d1bddd5558938ff722d7021fa8b8b3..f251536a891b2d064b9fff29810166f0f0863fa6 100644 (file)
@@ -402,7 +402,6 @@ int sd_rtnl_message_new_link(sd_netlink *rtnl, sd_netlink_message **ret,
         int r;
 
         assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
-        assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
         assert_return(ret, -EINVAL);
 
         r = message_new(rtnl, ret, nlmsg_type);
index 74a0ae865b40f929c36865d5917b9bcf20da9747..f2b7e4dd797ccfb1ec638a27bb3b15d5fb65c781 100644 (file)
@@ -538,3 +538,50 @@ int veth_extra_parse(char ***l, const char *p) {
         a = b = NULL;
         return 0;
 }
+
+static int remove_one_veth_link(sd_netlink *rtnl, const char *name) {
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
+        int r;
+
+        if (isempty(name))
+                return 0;
+
+        r = sd_rtnl_message_new_link(rtnl, &m, RTM_DELLINK, 0);
+        if (r < 0)
+                return log_error_errno(r, "Failed to allocate netlink message: %m");
+
+        r = sd_netlink_message_append_string(m, IFLA_IFNAME, name);
+        if (r < 0)
+                return log_error_errno(r, "Failed to add netlink interface name: %m");
+
+        r = sd_netlink_call(rtnl, m, 0, NULL);
+        if (r == -ENODEV) /* Already gone */
+                return 0;
+        if (r < 0)
+                return log_error_errno(r, "Failed to remove veth interface %s: %m", name);
+
+        return 1;
+}
+
+int remove_veth_links(const char *primary, char **pairs) {
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
+        char **a, **b;
+        int r;
+
+        /* In some cases the kernel might pin the veth links between host and container even after the namespace
+         * died. Hence, let's better remove them explicitly too. */
+
+        if (isempty(primary) && strv_isempty(pairs))
+                return 0;
+
+        r = sd_netlink_open(&rtnl);
+        if (r < 0)
+                return log_error_errno(r, "Failed to connect to netlink: %m");
+
+        remove_one_veth_link(rtnl, primary);
+
+        STRV_FOREACH_PAIR(a, b, pairs)
+                remove_one_veth_link(rtnl, *a);
+
+        return 0;
+}
index 9ab1606d1c5a8ae67c54eb4ffd24b4a400eb5522..c5036ab470e2dea5558f718b665f4a9cef39959c 100644 (file)
@@ -34,3 +34,5 @@ int setup_ipvlan(const char *machine_name, pid_t pid, char **ifaces);
 int move_network_interfaces(pid_t pid, char **ifaces);
 
 int veth_extra_parse(char ***l, const char *p);
+
+int remove_veth_links(const char *primary, char **pairs);
index e1d37d383a2eaa09554688e2be748496ebe72955..d687df8a091231727de30925a31e982fe4ce702b 100644 (file)
@@ -3713,6 +3713,7 @@ int main(int argc, char *argv[]) {
                 }
 
                 expose_port_flush(arg_expose_ports, &exposed);
+                (void) remove_veth_links(veth_name, arg_network_veth_extra);
         }
 
 finish:
@@ -3745,6 +3746,7 @@ finish:
         }
 
         expose_port_flush(arg_expose_ports, &exposed);
+        (void) remove_veth_links(veth_name, arg_network_veth_extra);
 
         free(arg_directory);
         free(arg_template);