chiark / gitweb /
bus: add API call to create bus connection to the system bus of local containers
[elogind.git] / src / libsystemd-bus / sd-bus.c
index 383b035b7e99cec269c7d02e3294de3f168811eb..f42d5d0ee133fde80b7a6ba27f78795198c21e1f 100644 (file)
@@ -46,6 +46,7 @@
 #include "bus-signature.h"
 #include "bus-objects.h"
 #include "bus-util.h"
+#include "bus-container.h"
 
 static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec);
 
@@ -117,6 +118,7 @@ static void bus_free(sd_bus *b) {
         free(b->auth_buffer);
         free(b->address);
         free(b->kernel);
+        free(b->machine);
 
         free(b->exec_path);
         strv_free(b->exec_argv);
@@ -753,6 +755,45 @@ static int parse_kernel_address(sd_bus *b, const char **p, char **guid) {
         return 0;
 }
 
+static int parse_container_address(sd_bus *b, const char **p, char **guid) {
+        _cleanup_free_ char *machine = NULL;
+        int r;
+
+        assert(b);
+        assert(p);
+        assert(*p);
+        assert(guid);
+
+        while (**p != 0 && **p != ';') {
+                r = parse_address_key(p, "guid", guid);
+                if (r < 0)
+                        return r;
+                else if (r > 0)
+                        continue;
+
+                r = parse_address_key(p, "machine", &machine);
+                if (r < 0)
+                        return r;
+                else if (r > 0)
+                        continue;
+
+                skip_address_key(p);
+        }
+
+        if (!machine)
+                return -EINVAL;
+
+        free(b->machine);
+        b->machine = machine;
+        machine = NULL;
+
+        b->sockaddr.un.sun_family = AF_UNIX;
+        strncpy(b->sockaddr.un.sun_path, "/var/run/dbus/system_bus_socket", sizeof(b->sockaddr.un.sun_path));
+        b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + sizeof("/var/run/dbus/system_bus_socket") - 1;
+
+        return 0;
+}
+
 static void bus_reset_parsed_address(sd_bus *b) {
         assert(b);
 
@@ -765,6 +806,8 @@ static void bus_reset_parsed_address(sd_bus *b) {
         b->server_id = SD_ID128_NULL;
         free(b->kernel);
         b->kernel = NULL;
+        free(b->machine);
+        b->machine = NULL;
 }
 
 static int bus_parse_next_address(sd_bus *b) {
@@ -823,6 +866,14 @@ static int bus_parse_next_address(sd_bus *b) {
                         if (r < 0)
                                 return r;
 
+                        break;
+                } else if (startswith(a, "x-container:")) {
+
+                        a += 12;
+                        r = parse_container_address(b, &a, &guid);
+                        if (r < 0)
+                                return r;
+
                         break;
                 }
 
@@ -849,24 +900,32 @@ static int bus_start_address(sd_bus *b) {
         for (;;) {
                 sd_bus_close(b);
 
-                if (b->sockaddr.sa.sa_family != AF_UNSPEC) {
+                if (b->exec_path) {
 
-                        r = bus_socket_connect(b);
+                        r = bus_socket_exec(b);
                         if (r >= 0)
                                 return r;
 
                         b->last_connect_error = -r;
+                } else if (b->kernel) {
 
-                } else if (b->exec_path) {
+                        r = bus_kernel_connect(b);
+                        if (r >= 0)
+                                return r;
 
-                        r = bus_socket_exec(b);
+                        b->last_connect_error = -r;
+
+                } else if (b->machine) {
+
+                        r = bus_container_connect(b);
                         if (r >= 0)
                                 return r;
 
                         b->last_connect_error = -r;
-                } else if (b->kernel) {
 
-                        r = bus_kernel_connect(b);
+                } else if (b->sockaddr.sa.sa_family != AF_UNSPEC) {
+
+                        r = bus_socket_connect(b);
                         if (r >= 0)
                                 return r;
 
@@ -937,7 +996,7 @@ int sd_bus_start(sd_bus *bus) {
 
         if (bus->input_fd >= 0)
                 r = bus_start_fd(bus);
-        else if (bus->address || bus->sockaddr.sa.sa_family != AF_UNSPEC || bus->exec_path || bus->kernel)
+        else if (bus->address || bus->sockaddr.sa.sa_family != AF_UNSPEC || bus->exec_path || bus->kernel || bus->machine)
                 r = bus_start_address(bus);
         else
                 return -EINVAL;
@@ -1069,6 +1128,42 @@ int sd_bus_open_system_remote(const char *host, sd_bus **ret) {
         return 0;
 }
 
+int sd_bus_open_system_container(const char *machine, sd_bus **ret) {
+        _cleanup_free_ char *e = NULL;
+        sd_bus *bus;
+        char *p;
+        int r;
+
+        assert_return(machine, -EINVAL);
+        assert_return(ret, -EINVAL);
+
+        e = bus_address_escape(machine);
+        if (!e)
+                return -ENOMEM;
+
+        p = strjoin("x-container:machine=", e, NULL);
+        if (!p)
+                return -ENOMEM;
+
+        r = sd_bus_new(&bus);
+        if (r < 0) {
+                free(p);
+                return r;
+        }
+
+        bus->address = p;
+        bus->bus_client = true;
+
+        r = sd_bus_start(bus);
+        if (r < 0) {
+                bus_free(bus);
+                return r;
+        }
+
+        *ret = bus;
+        return 0;
+}
+
 void sd_bus_close(sd_bus *bus) {
         if (!bus)
                 return;