]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: add open_netns_path() helper
authorLennart Poettering <lennart@poettering.net>
Thu, 7 Mar 2019 15:42:04 +0000 (16:42 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 7 Mar 2019 15:55:23 +0000 (16:55 +0100)
The new call allows us to open a netns from the file system, and store
it in a "storage fd pair". It's supposed to work with setup_netns() and
allows pre-population of the netns used with one opened from the file
system.

src/core/namespace.c
src/core/namespace.h

index 87e4a8a25fc62125ea71453d14753ace7dfc172f..02ac49d02cfbca9cb0ba0ab0203629a8f1eeeb45 100644 (file)
@@ -1703,6 +1703,59 @@ fail:
         return r;
 }
 
+int open_netns_path(int netns_storage_socket[static 2], const char *path) {
+        _cleanup_close_ int netns = -1;
+        int q, r;
+
+        assert(netns_storage_socket);
+        assert(netns_storage_socket[0] >= 0);
+        assert(netns_storage_socket[1] >= 0);
+        assert(path);
+
+        /* If the storage socket doesn't contain a netns fd yet, open one via the file system and store it in
+         * it. This is supposed to be called ahead of time, i.e. before setup_netns() which will allocate a
+         * new anonymous netns if needed. */
+
+        if (lockf(netns_storage_socket[0], F_LOCK, 0) < 0)
+                return -errno;
+
+        netns = receive_one_fd(netns_storage_socket[0], MSG_DONTWAIT);
+        if (netns == -EAGAIN) {
+                /* Nothing stored yet. Open the file from the file system. */
+
+                netns = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC);
+                if (netns < 0) {
+                        r = -errno;
+                        goto fail;
+                }
+
+                r = fd_is_network_ns(netns);
+                if (r == 0) { /* Not a netns? Refuse early. */
+                        r = -EINVAL;
+                        goto fail;
+                }
+                if (r < 0 && r != -EUCLEAN) /* EUCLEAN: we don't know */
+                        goto fail;
+
+                r = 1;
+
+        } else if (netns < 0) {
+                r = netns;
+                goto fail;
+        } else
+                r = 0; /* Already allocated */
+
+        q = send_one_fd(netns_storage_socket[1], netns, MSG_DONTWAIT);
+        if (q < 0) {
+                r = q;
+                goto fail;
+        }
+
+fail:
+        (void) lockf(netns_storage_socket[0], F_ULOCK, 0);
+        return r;
+}
+
 bool ns_type_supported(NamespaceType type) {
         const char *t, *ns_proc;
 
index ab3983f790c2213674f8c3a8f9ad86ecce595e42..cd1e8b77bb2de35875a624d725537553b4cfc393 100644 (file)
@@ -93,6 +93,7 @@ int setup_tmp_dirs(
                 char **var_tmp_dir);
 
 int setup_netns(int netns_storage_socket[static 2]);
+int open_netns_path(int netns_storage_socket[static 2], const char *path);
 
 const char* protect_home_to_string(ProtectHome p) _const_;
 ProtectHome protect_home_from_string(const char *s) _pure_;