assert_return(bus->state == BUS_UNSET, -EPERM);
assert_return(!bus_pid_changed(bus), -ECHILD);
- SET_FLAG(bus->attach_flags, KDBUS_ATTACH_CREDS,
- !!(mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID)));
-
- SET_FLAG(bus->attach_flags, KDBUS_ATTACH_COMM,
- !!(mask & (SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM)));
-
- SET_FLAG(bus->attach_flags, KDBUS_ATTACH_EXE,
- !!(mask & SD_BUS_CREDS_EXE));
-
- SET_FLAG(bus->attach_flags, KDBUS_ATTACH_CMDLINE,
- !!(mask & SD_BUS_CREDS_CMDLINE));
-
- SET_FLAG(bus->attach_flags, KDBUS_ATTACH_CGROUP,
- !!(mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID)));
-
- SET_FLAG(bus->attach_flags, KDBUS_ATTACH_CAPS,
- !!(mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)));
-
- SET_FLAG(bus->attach_flags, KDBUS_ATTACH_SECLABEL,
- !!(mask & SD_BUS_CREDS_SELINUX_CONTEXT));
-
- SET_FLAG(bus->attach_flags, KDBUS_ATTACH_AUDIT,
- !!(mask & (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)));
-
- bus->creds_mask = mask;
-
- return 0;
+ return kdbus_translate_attach_flags(mask, &bus->creds_mask);
}
_public_ int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t server_id) {
}
static int bus_seal_message(sd_bus *b, sd_bus_message *m) {
+ assert(b);
assert(m);
if (m->header->version > b->message_version)
return bus_message_seal(m, ++b->serial);
}
+int bus_seal_synthetic_message(sd_bus *b, sd_bus_message *m) {
+ assert(b);
+ assert(m);
+
+ if (m->header->version > b->message_version)
+ return -EPERM;
+
+ /* The bus specification says the serial number cannot be 0,
+ * hence let's fill something in for synthetic messages. Since
+ * synthetic messages might have a fake sender and we don't
+ * want to interfere with the real sender's serial numbers we
+ * pick a fixed, artifical one. We use (uint32_t) -1 rather
+ * than (uint64_t) -1 since dbus1 only had 32bit identifiers,
+ * even though kdbus can do 64bit. */
+
+ return bus_message_seal(m, 0xFFFFFFFFULL);
+}
+
static int bus_write_message(sd_bus *bus, sd_bus_message *message, size_t *idx) {
int r;
return ret;
}
-static int bus_read_message(sd_bus *bus, sd_bus_message **m) {
- int r;
-
+static int bus_read_message(sd_bus *bus) {
assert(bus);
- assert(m);
if (bus->is_kernel)
- r = bus_kernel_read_message(bus, m);
+ return bus_kernel_read_message(bus);
else
- r = bus_socket_read_message(bus, m);
+ return bus_socket_read_message(bus);
+}
- return r;
+int bus_rqueue_make_room(sd_bus *bus) {
+ sd_bus_message **q;
+ unsigned x;
+
+ x = bus->rqueue_size + 1;
+
+ if (bus->rqueue_allocated >= x)
+ return 0;
+
+ if (x > BUS_RQUEUE_MAX)
+ return -ENOBUFS;
+
+ q = realloc(bus->rqueue, x * sizeof(sd_bus_message*));
+ if (!q)
+ return -ENOMEM;
+
+ bus->rqueue = q;
+ bus->rqueue_allocated = x;
+
+ return 0;
}
static int dispatch_rqueue(sd_bus *bus, sd_bus_message **m) {
- sd_bus_message *z = NULL;
int r, ret = 0;
assert(bus);
assert(m);
assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
- if (bus->rqueue_size > 0) {
- /* Dispatch a queued message */
+ for (;;) {
+ if (bus->rqueue_size > 0) {
+ /* Dispatch a queued message */
- *m = bus->rqueue[0];
- bus->rqueue_size --;
- memmove(bus->rqueue, bus->rqueue + 1, sizeof(sd_bus_message*) * bus->rqueue_size);
- return 1;
- }
+ *m = bus->rqueue[0];
+ bus->rqueue_size --;
+ memmove(bus->rqueue, bus->rqueue + 1, sizeof(sd_bus_message*) * bus->rqueue_size);
+ return 1;
+ }
- /* Try to read a new message */
- do {
- r = bus_read_message(bus, &z);
+ /* Try to read a new message */
+ r = bus_read_message(bus);
if (r < 0)
return r;
if (r == 0)
return ret;
ret = 1;
- } while (!z);
-
- *m = z;
- return ret;
+ }
}
_public_ int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial) {
sd_bus_error *error,
sd_bus_message **reply) {
- int r;
usec_t timeout;
uint64_t serial;
- bool room = false;
+ unsigned i;
+ int r;
assert_return(bus, -EINVAL);
assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
return r;
timeout = calc_elapse(usec);
+ i = bus->rqueue_size;
for (;;) {
usec_t left;
- sd_bus_message *incoming = NULL;
-
- if (!room) {
- sd_bus_message **q;
-
- if (bus->rqueue_size >= BUS_RQUEUE_MAX)
- return -ENOBUFS;
- /* Make sure there's room for queuing this
- * locally, before we read the message */
-
- q = realloc(bus->rqueue, (bus->rqueue_size + 1) * sizeof(sd_bus_message*));
- if (!q)
- return -ENOMEM;
-
- bus->rqueue = q;
- room = true;
- }
-
- r = bus_read_message(bus, &incoming);
+ r = bus_read_message(bus);
if (r < 0)
return r;
- if (incoming) {
+ while (i < bus->rqueue_size) {
+ sd_bus_message *incoming = NULL;
+
+ incoming = bus->rqueue[i];
if (incoming->reply_serial == serial) {
/* Found a match! */
+ memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1));
+ bus->rqueue_size--;
+
if (incoming->header->type == SD_BUS_MESSAGE_METHOD_RETURN) {
if (reply)
incoming->sender &&
streq(bus->unique_name, incoming->sender)) {
+ memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1));
+ bus->rqueue_size--;
+
/* Our own message? Somebody is trying
* to send its own client a message,
* let's not dead-lock, let's fail
return -ELOOP;
}
- /* There's already guaranteed to be room for
- * this, so need to resize things here */
- bus->rqueue[bus->rqueue_size ++] = incoming;
- room = false;
-
/* Try to read more, right-away */
- continue;
+ i++;
}
- if (r != 0)
+
+ if (r > 0)
continue;
if (timeout > 0) {
if (r < 0)
return r;
- r = bus_seal_message(bus, m);
+ m->sender = "org.freedesktop.DBus";
+
+ r = bus_seal_synthetic_message(bus, m);
if (r < 0)
return r;
if (r < 0)
return r;
- r = bus_seal_message(bus, m);
+ r = bus_seal_synthetic_message(bus, m);
if (r < 0)
return r;
if (r < 0)
return r;
- r = bus_seal_message(bus, m);
+ m->sender = "org.freedesktop.DBus.Local";
+
+ r = bus_seal_synthetic_message(bus, m);
if (r < 0)
return r;