chiark / gitweb /
Partially revert e62d8c394474
[elogind.git] / src / libsystemd-bus / sd-bus.c
index 08a218b7cccbf7174f16f5b2da789fa1a194ffc3..a71d7b5d77961df4ab58a777e70e95f758c31c50 100644 (file)
@@ -37,6 +37,7 @@
 #include "bus-message.h"
 #include "bus-type.h"
 #include "bus-socket.h"
+#include "bus-control.h"
 
 static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec);
 
@@ -52,7 +53,7 @@ static void bus_free(sd_bus *b) {
 
         free(b->rbuffer);
         free(b->unique_name);
-        free(b->auth_uid);
+        free(b->auth_buffer);
         free(b->address);
 
         free(b->exec_path);
@@ -84,6 +85,8 @@ static void bus_free(sd_bus *b) {
 
         hashmap_free(b->object_callbacks);
 
+        bus_match_free(&b->match_callbacks);
+
         free(b);
 }
 
@@ -197,6 +200,29 @@ int sd_bus_set_negotiate_fds(sd_bus *bus, int b) {
         return 0;
 }
 
+int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t server_id) {
+        if (!bus)
+                return -EINVAL;
+        if (!b && !sd_id128_equal(server_id, SD_ID128_NULL))
+                return -EINVAL;
+        if (bus->state != BUS_UNSET)
+                return -EPERM;
+
+        bus->is_server = !!b;
+        bus->server_id = server_id;
+        return 0;
+}
+
+int sd_bus_set_anonymous(sd_bus *bus, int b) {
+        if (!bus)
+                return -EINVAL;
+        if (bus->state != BUS_UNSET)
+                return -EPERM;
+
+        bus->anonymous_auth = !!b;
+        return 0;
+}
+
 static int hello_callback(sd_bus *bus, int error, sd_bus_message *reply, void *userdata) {
         const char *s;
         int r;
@@ -244,11 +270,7 @@ static int bus_send_hello(sd_bus *bus) {
         if (r < 0)
                 return r;
 
-        r = sd_bus_send_with_reply(bus, m, hello_callback, NULL, 0, NULL);
-        if (r < 0)
-                return r;
-
-        return r;
+        return sd_bus_send_with_reply(bus, m, hello_callback, NULL, 0, &bus->hello_serial);
 }
 
 int bus_start_running(sd_bus *bus) {
@@ -582,7 +604,7 @@ static void bus_reset_parsed_address(sd_bus *b) {
         free(b->exec_path);
         b->exec_path = NULL;
         b->exec_argv = NULL;
-        b->peer = SD_ID128_NULL;
+        b->server_id = SD_ID128_NULL;
 }
 
 static int bus_parse_next_address(sd_bus *b) {
@@ -642,7 +664,7 @@ static int bus_parse_next_address(sd_bus *b) {
         }
 
         if (guid) {
-                r = sd_id128_from_string(guid, &b->peer);
+                r = sd_id128_from_string(guid, &b->server_id);
                 if (r < 0)
                         return r;
         }
@@ -720,9 +742,12 @@ int sd_bus_start(sd_bus *bus) {
 
         bus->state = BUS_OPENING;
 
+        if (bus->is_server && bus->bus_client)
+                return -EINVAL;
+
         if (bus->fd >= 0)
                 r = bus_start_fd(bus);
-        else if (bus->address)
+        else if (bus->address || bus->sockaddr.sa.sa_family != AF_UNSPEC || bus->exec_path)
                 r = bus_start_address(bus);
         else
                 return -EINVAL;
@@ -882,19 +907,19 @@ int sd_bus_can_send(sd_bus *bus, char type) {
         return bus_type_is_valid(type);
 }
 
-int sd_bus_get_peer(sd_bus *bus, sd_id128_t *peer) {
+int sd_bus_get_server_id(sd_bus *bus, sd_id128_t *server_id) {
         int r;
 
         if (!bus)
                 return -EINVAL;
-        if (!peer)
+        if (!server_id)
                 return -EINVAL;
 
         r = bus_ensure_running(bus);
         if (r < 0)
                 return r;
 
-        *peer = bus->peer;
+        *server_id = bus->server_id;
         return 0;
 }
 
@@ -1092,7 +1117,7 @@ static int timeout_compare(const void *a, const void *b) {
 int sd_bus_send_with_reply(
                 sd_bus *bus,
                 sd_bus_message *m,
-                sd_message_handler_t callback,
+                sd_bus_message_handler_t callback,
                 void *userdata,
                 uint64_t usec,
                 uint64_t *serial) {
@@ -1354,7 +1379,7 @@ int sd_bus_get_events(sd_bus *bus) {
                 flags |= POLLOUT;
         else if (bus->state == BUS_AUTHENTICATING) {
 
-                if (bus->auth_index < ELEMENTSOF(bus->auth_iovec))
+                if (bus_socket_auth_needs_write(bus))
                         flags |= POLLOUT;
 
                 flags |= POLLIN;
@@ -1421,6 +1446,28 @@ static int process_timeout(sd_bus *bus) {
         return r < 0 ? r : 1;
 }
 
+static int process_hello(sd_bus *bus, sd_bus_message *m) {
+        assert(bus);
+        assert(m);
+
+        if (bus->state != BUS_HELLO)
+                return 0;
+
+        /* Let's make sure the first message on the bus is the HELLO
+         * reply. But note that we don't actually parse the message
+         * here (we leave that to the usual handling), we just verify
+         * we don't let any earlier msg through. */
+
+        if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_RETURN &&
+            m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
+                return -EIO;
+
+        if (m->reply_serial != bus->hello_serial)
+                return -EIO;
+
+        return 0;
+}
+
 static int process_reply(sd_bus *bus, sd_bus_message *m) {
         struct reply_callback *c;
         int r;
@@ -1449,6 +1496,9 @@ static int process_filter(sd_bus *bus, sd_bus_message *m) {
         struct filter_callback *l;
         int r;
 
+        assert(bus);
+        assert(m);
+
         LIST_FOREACH(callbacks, l, bus->filter_callbacks) {
                 r = l->callback(bus, 0, m, l->userdata);
                 if (r != 0)
@@ -1458,6 +1508,13 @@ static int process_filter(sd_bus *bus, sd_bus_message *m) {
         return 0;
 }
 
+static int process_match(sd_bus *bus, sd_bus_message *m) {
+        assert(bus);
+        assert(m);
+
+        return bus_match_run(bus, &bus->match_callbacks, 0, m);
+}
+
 static int process_builtin(sd_bus *bus, sd_bus_message *m) {
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         int r;
@@ -1675,6 +1732,10 @@ static int process_message(sd_bus *bus, sd_bus_message *m) {
         assert(bus);
         assert(m);
 
+        r = process_hello(bus, m);
+        if (r != 0)
+                return r;
+
         r = process_reply(bus, m);
         if (r != 0)
                 return r;
@@ -1683,6 +1744,10 @@ static int process_message(sd_bus *bus, sd_bus_message *m) {
         if (r != 0)
                 return r;
 
+        r = process_match(bus, m);
+        if (r != 0)
+                return r;
+
         r = process_builtin(bus, m);
         if (r != 0)
                 return r;
@@ -1881,7 +1946,7 @@ int sd_bus_flush(sd_bus *bus) {
         }
 }
 
-int sd_bus_add_filter(sd_bus *bus, sd_message_handler_t callback, void *userdata) {
+int sd_bus_add_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *userdata) {
         struct filter_callback *f;
 
         if (!bus)
@@ -1899,7 +1964,7 @@ int sd_bus_add_filter(sd_bus *bus, sd_message_handler_t callback, void *userdata
         return 0;
 }
 
-int sd_bus_remove_filter(sd_bus *bus, sd_message_handler_t callback, void *userdata) {
+int sd_bus_remove_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *userdata) {
         struct filter_callback *f;
 
         if (!bus)
@@ -1922,7 +1987,7 @@ static int bus_add_object(
                 sd_bus *bus,
                 bool fallback,
                 const char *path,
-                sd_message_handler_t callback,
+                sd_bus_message_handler_t callback,
                 void *userdata) {
 
         struct object_callback *c;
@@ -1967,7 +2032,7 @@ static int bus_remove_object(
                 sd_bus *bus,
                 bool fallback,
                 const char *path,
-                sd_message_handler_t callback,
+                sd_bus_message_handler_t callback,
                 void *userdata) {
 
         struct object_callback *c;
@@ -1994,18 +2059,63 @@ static int bus_remove_object(
         return 1;
 }
 
-int sd_bus_add_object(sd_bus *bus, const char *path, sd_message_handler_t callback, void *userdata) {
+int sd_bus_add_object(sd_bus *bus, const char *path, sd_bus_message_handler_t callback, void *userdata) {
         return bus_add_object(bus, false, path, callback, userdata);
 }
 
-int sd_bus_remove_object(sd_bus *bus, const char *path, sd_message_handler_t callback, void *userdata) {
+int sd_bus_remove_object(sd_bus *bus, const char *path, sd_bus_message_handler_t callback, void *userdata) {
         return bus_remove_object(bus, false, path, callback, userdata);
 }
 
-int sd_bus_add_fallback(sd_bus *bus, const char *prefix, sd_message_handler_t callback, void *userdata) {
+int sd_bus_add_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_t callback, void *userdata) {
         return bus_add_object(bus, true, prefix, callback, userdata);
 }
 
-int sd_bus_remove_fallback(sd_bus *bus, const char *prefix, sd_message_handler_t callback, void *userdata) {
+int sd_bus_remove_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_t callback, void *userdata) {
         return bus_remove_object(bus, true, prefix, callback, userdata);
 }
+
+int sd_bus_add_match(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata) {
+        int r = 0;
+
+        if (!bus)
+                return -EINVAL;
+        if (!match)
+                return -EINVAL;
+
+        if (bus->bus_client) {
+                r = bus_add_match_internal(bus, match);
+                if (r < 0)
+                        return r;
+        }
+
+        if (callback) {
+                r = bus_match_add(&bus->match_callbacks, match, callback, userdata, NULL);
+                if (r < 0) {
+
+                        if (bus->bus_client)
+                                bus_remove_match_internal(bus, match);
+                }
+        }
+
+        return r;
+}
+
+int sd_bus_remove_match(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata) {
+        int r = 0, q = 0;
+
+        if (!bus)
+                return -EINVAL;
+        if (!match)
+                return -EINVAL;
+
+        if (bus->bus_client)
+                r = bus_remove_match_internal(bus, match);
+
+        if (callback)
+                q = bus_match_remove(&bus->match_callbacks, match, callback, userdata);
+
+        if (r < 0)
+                return r;
+        return q;
+}