Features:
+* libsystemd-bus:
+ - default policy (allow uid == 0 and our own uid)
+ - enforce alignment of pointers passed in
+ - negotiation for attach attributes
+ - verify that the PID doesn't change for existing busses
+ - when kdbus doesn't take our message without memfds, try again with memfds
+ - kdbus: generate correct bloom filter for matches
+ - implement translator service
+ - port systemd to new library
+ - implement busname unit type in systemd
+ - move to gvariant
+ - minimal locking around the memfd cache
+ - keep the connection fds around as long as the bus is open
+ - make ref counting atomic
+ - merge busctl into systemctl or so?
+
* in the final killing spree, detect processes from the root directory, and
complain loudly if they have argv[0][0] == '@' set.
https://bugzilla.redhat.com/show_bug.cgi?id=961044
/* Better replce this with a gperf table */
+ if (!e)
+ return -EIO;
+
if (!e->name)
return -EIO;
streq(e->name, "org.freedesktop.DBus.Error.AccessDenied"))
return -EPERM;
+ if (streq(e->name, "org.freedesktop.DBus.Error.InvalidArgs"))
+ return -EINVAL;
+
+ if (streq(e->name, "org.freedesktop.DBus.Error.UnixProcessIdUnknown"))
+ return -ESRCH;
+
+ if (streq(e->name, "org.freedesktop.DBus.Error.FileNotFound"))
+ return -ENOENT;
+
+ if (streq(e->name, "org.freedesktop.DBus.Error.FileExists"))
+ return -EEXIST;
+
+ if (streq(e->name, "org.freedesktop.DBus.Error.Timeout"))
+ return -ETIMEDOUT;
+
+ if (streq(e->name, "org.freedesktop.DBus.Error.IOError"))
+ return -EIO;
+
+ if (streq(e->name, "org.freedesktop.DBus.Error.Disconnected"))
+ return -ECONNRESET;
+
+ if (streq(e->name, "org.freedesktop.DBus.Error.NotSupported"))
+ return -ENOTSUP;
+
return -EIO;
}
if (!e)
return error;
- if (error == -ENOMEM)
- sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.NoMemory", strerror(-error));
- else if (error == -EPERM || error == -EACCES)
- sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.AccessDenied", strerror(-error));
- else
- sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.Failed", "Operation failed");
+ switch (error) {
+
+ case -ENOMEM:
+ sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.NoMemory", "Out of memory");
+ break;
+
+ case -EPERM:
+ case -EACCES:
+ sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.AccessDenied", "Access denied");
+ break;
+
+ case -EINVAL:
+ sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid argument");
+ break;
+
+ case -ESRCH:
+ sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.UnixProcessIdUnknown", "No such process");
+ break;
+
+ case -ENOENT:
+ sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.FileNotFound", "File not found");
+ break;
+
+ case -EEXIST:
+ sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.FileExists", "File exists");
+ break;
+
+ case -ETIMEDOUT:
+ case -ETIME:
+ sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.Timeout", "Timed out");
+ break;
+
+ case -EIO:
+ sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.IOError", "Input/output error");
+ break;
+
+ case -ENETRESET:
+ case -ECONNABORTED:
+ case -ECONNRESET:
+ sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.Disconnected", "Disconnected");
+ break;
+
+ case -ENOTSUP:
+ sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.NotSupported", "Not supported");
+ break;
+ }
+ sd_bus_error_set_const(e, "org.freedesktop.DBus.Error.Failed", "Operation failed");
return error;
}
int bus_match_run(
sd_bus *bus,
struct bus_match_node *node,
- int ret,
sd_bus_message *m) {
* we won't call any. The children of the root node
* are compares or leaves, they will automatically
* call their siblings. */
- return bus_match_run(bus, node->child, ret, m);
+ return bus_match_run(bus, node->child, m);
case BUS_MATCH_VALUE:
* automatically call their siblings */
assert(node->child);
- return bus_match_run(bus, node->child, ret, m);
+ return bus_match_run(bus, node->child, m);
case BUS_MATCH_LEAF:
/* Run the callback. And then invoke siblings. */
assert(node->leaf.callback);
- r = node->leaf.callback(bus, ret, m, node->leaf.userdata);
+ r = node->leaf.callback(bus, m, node->leaf.userdata);
if (r != 0)
return r;
- return bus_match_run(bus, node->next, ret, m);
+ return bus_match_run(bus, node->next, m);
case BUS_MATCH_MESSAGE_TYPE:
test_u8 = m->header->type;
found = NULL;
if (found) {
- r = bus_match_run(bus, found, ret, m);
+ r = bus_match_run(bus, found, m);
if (r != 0)
return r;
}
if (!value_node_test(c, node->type, test_u8, test_str))
continue;
- r = bus_match_run(bus, c, ret, m);
+ r = bus_match_run(bus, c, m);
if (r != 0)
return r;
}
return 0;
/* And now, let's invoke our siblings */
- return bus_match_run(bus, node->next, ret, m);
+ return bus_match_run(bus, node->next, m);
}
static int bus_match_add_compare_value(
};
};
-int bus_match_run(sd_bus *bus, struct bus_match_node *root, int ret, sd_bus_message *m);
+int bus_match_run(sd_bus *bus, struct bus_match_node *root, sd_bus_message *m);
int bus_match_add(struct bus_match_node *root, const char *match, sd_bus_message_handler_t callback, void *userdata, struct bus_match_node **ret);
int bus_match_remove(struct bus_match_node *root, const char *match, sd_bus_message_handler_t callback, void *userdata);
return r;
}
+int bus_message_new_synthetic_error(
+ sd_bus *bus,
+ uint64_t serial,
+ const sd_bus_error *e,
+ sd_bus_message **m) {
+
+ sd_bus_message *t;
+ int r;
+
+ assert(sd_bus_error_is_set(e));
+ assert(m);
+
+ t = message_new(bus, SD_BUS_MESSAGE_TYPE_METHOD_ERROR);
+ if (!t)
+ return -ENOMEM;
+
+ t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
+ t->reply_serial = serial;
+
+ r = message_append_field_uint32(t, SD_BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial);
+ if (r < 0)
+ goto fail;
+
+ if (bus && bus->unique_name) {
+ r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
+ if (r < 0)
+ goto fail;
+ }
+
+ *m = t;
+ return 0;
+
+fail:
+ message_free(t);
+ return r;
+}
+
sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
if (!m)
return NULL;
*sum = sizeof(struct bus_header) + ALIGN8(fs) + bs;
return 0;
}
+
+int bus_message_to_errno(sd_bus_message *m) {
+ assert(m);
+
+ if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
+ return 0;
+
+ return bus_error_to_errno(&m->error);
+}
int bus_body_part_map(struct bus_body_part *part);
void bus_body_part_unmap(struct bus_body_part *part);
+
+int bus_message_to_errno(sd_bus_message *m);
+
+int bus_message_new_synthetic_error(sd_bus *bus, uint64_t serial, const sd_bus_error *e, sd_bus_message **m);
return 0;
}
-static int hello_callback(sd_bus *bus, int error, sd_bus_message *reply, void *userdata) {
+static int hello_callback(sd_bus *bus, sd_bus_message *reply, void *userdata) {
const char *s;
int r;
assert(bus);
assert(bus->state == BUS_HELLO);
-
- if (error != 0)
- return -error;
-
assert(reply);
+ r = bus_message_to_errno(reply);
+ if (r < 0)
+ return r;
+
r = sd_bus_message_read(reply, "s", &s);
if (r < 0)
return r;
}
static int process_timeout(sd_bus *bus) {
+ _cleanup_bus_message_unref_ sd_bus_message* m = NULL;
struct reply_callback *c;
usec_t n;
int r;
if (c->timeout > n)
return 0;
+ r = bus_message_new_synthetic_error(
+ bus,
+ c->serial,
+ &SD_BUS_ERROR_MAKE("org.freedesktop.DBus.Error.Timeout", "Timed out"),
+ &m);
+ if (r < 0)
+ return r;
+
assert_se(prioq_pop(bus->reply_callbacks_prioq) == c);
hashmap_remove(bus->reply_callbacks, &c->serial);
- r = c->callback(bus, ETIMEDOUT, NULL, c->userdata);
+ r = c->callback(bus, m, c->userdata);
free(c);
return r < 0 ? r : 1;
if (r < 0)
return r;
- r = c->callback(bus, 0, m, c->userdata);
+ r = c->callback(bus, m, c->userdata);
free(c);
return r;
if (r < 0)
return r;
- r = l->callback(bus, 0, m, l->userdata);
+ r = l->callback(bus, m, l->userdata);
if (r != 0)
return r;
do {
bus->match_callbacks_modified = false;
- r = bus_match_run(bus, &bus->match_callbacks, 0, m);
+ r = bus_match_run(bus, &bus->match_callbacks, m);
if (r != 0)
return r;
if (r < 0)
return r;
- r = c->callback(bus, 0, m, c->userdata);
+ r = c->callback(bus, m, c->userdata);
if (r != 0)
return r;
if (r < 0)
return r;
- r = c->callback(bus, 0, m, c->userdata);
+ r = c->callback(bus, m, c->userdata);
if (r != 0)
return r;
#include "bus-match.h"
#include "bus-internal.h"
-static int match_callback(sd_bus *bus, int error, sd_bus_message *m, void *userdata) {
+static int match_callback(sd_bus *bus, sd_bus_message *m, void *userdata) {
log_info("Match triggered! interface=%s member=%s", strna(sd_bus_message_get_interface(m)), strna(sd_bus_message_get_member(m)));
return 0;
}
-static int object_callback(sd_bus *bus, int error, sd_bus_message *m, void *userdata) {
+static int object_callback(sd_bus *bus, sd_bus_message *m, void *userdata) {
int r;
assert(bus);
- if (error != 0)
+ if (sd_bus_message_is_method_error(m, NULL))
return 0;
if (sd_bus_message_is_method_call(m, "org.object.test", "Foobar")) {
return INT_TO_PTR(r);
}
-static int quit_callback(sd_bus *b, int ret, sd_bus_message *m, void *userdata) {
+static int quit_callback(sd_bus *b, sd_bus_message *m, void *userdata) {
bool *x = userdata;
- log_error("Quit callback: %s", strerror(ret));
+ log_error("Quit callback: %s", strerror(bus_message_to_errno(m)));
*x = 1;
return 1;
static bool mask[32];
-static int filter(sd_bus *b, int ret, sd_bus_message *m, void *userdata) {
+static int filter(sd_bus *b, sd_bus_message *m, void *userdata) {
log_info("Ran %i", PTR_TO_INT(userdata));
mask[PTR_TO_INT(userdata)] = true;
return 0;
assert_se(bus_message_seal(m, 1) >= 0);
zero(mask);
- assert_se(bus_match_run(NULL, &root, 0, m) == 0);
+ assert_se(bus_match_run(NULL, &root, m) == 0);
assert_se(mask_contains((unsigned[]) { 9, 8, 7, 5, 10, 12, 13, 14 }, 8));
assert_se(bus_match_remove(&root, "member='waldo',path='/foo/bar'", filter, INT_TO_PTR(8)) > 0);
bus_match_dump(&root, 0);
zero(mask);
- assert_se(bus_match_run(NULL, &root, 0, m) == 0);
+ assert_se(bus_match_run(NULL, &root, m) == 0);
assert_se(mask_contains((unsigned[]) { 9, 5, 10, 12, 14, 7 }, 6));
for (i = 0; i < _BUS_MATCH_NODE_TYPE_MAX; i++) {
# endif
#endif
-/* TODO:
- * - merge busctl into systemctl or so?
- * - default policy (allow uid == 0 and our own uid)
- * - enforce alignment of pointers passed in
- * - negotiation for attach attributes
- */
-
typedef struct sd_bus sd_bus;
typedef struct sd_bus_message sd_bus_message;
int need_free;
} sd_bus_error;
-typedef int (*sd_bus_message_handler_t)(sd_bus *bus, int ret, sd_bus_message *m, void *userdata);
+typedef int (*sd_bus_message_handler_t)(sd_bus *bus, sd_bus_message *m, void *userdata);
/* Connections */