chiark / gitweb /
libsystemd-bus: catch up with latest kdbus changes
authorDaniel Mack <zonque@gmail.com>
Sat, 30 Nov 2013 12:31:04 +0000 (13:31 +0100)
committerDaniel Mack <zonque@gmail.com>
Sat, 30 Nov 2013 12:31:04 +0000 (13:31 +0100)
The name list and query functions now work differently in kdbus, as the
result is stored in the connection's pool, rather than being copied back
through the ioctl buffer. That also safes us some logic, as we don't
have to resize the communication buffer in a loop with growing buffer
sizes.

Due to this, KDBUS_CMD_MSG_RELEASE was renamed to KDBUS_CMD_FREE, as it
is now used outside the message logic as well.

src/libsystemd-bus/bus-control.c
src/libsystemd-bus/bus-kernel.c
src/libsystemd-bus/bus-message.c
src/libsystemd-bus/kdbus.h
src/libsystemd-bus/sd-bus.c

index a0eeb30..1d1f6d0 100644 (file)
@@ -174,36 +174,23 @@ _public_ int sd_bus_list_names(sd_bus *bus, char ***l) {
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
         if (bus->is_kernel) {
-                _cleanup_free_ struct kdbus_cmd_names *names = NULL;
+                _cleanup_free_ struct kdbus_cmd_name_list *cmd = NULL;
+                struct kdbus_name_list *name_list;
                 struct kdbus_cmd_name *name;
-                size_t size;
 
-                /* assume 8k size first. If that doesn't suffice, kdbus will tell us
-                 * how big the buffer needs to be.  */
-                size = 8192;
-
-                for(;;) {
-                        names = realloc(names, size);
-                        if (!names)
-                                return -ENOMEM;
-
-                        names->size = size;
-                        names->flags = KDBUS_NAME_LIST_UNIQUE_NAMES;
+                cmd = malloc0(sizeof(struct kdbus_cmd_name_list *));
+                if (!cmd)
+                        return -ENOMEM;
 
-                        r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_LIST, names);
-                        if (r < 0) {
-                                if (errno == ENOBUFS && size != names->size) {
-                                        size = names->size;
-                                        continue;
-                                }
+                cmd->flags = KDBUS_NAME_LIST_UNIQUE_NAMES;
 
-                                return -errno;
-                        }
+                r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_LIST, cmd);
+                if (r < 0)
+                        return -errno;
 
-                        break;
-                }
+                name_list = (struct kdbus_name_list *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
 
-                KDBUS_PART_FOREACH(name, names, names) {
+                KDBUS_PART_FOREACH(name, name_list, names) {
                         char *n;
 
                         if (name->size > sizeof(*name))
@@ -216,6 +203,10 @@ _public_ int sd_bus_list_names(sd_bus *bus, char ***l) {
                                 return -ENOMEM;
                 }
 
+                r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_FREE, &cmd->offset);
+                if (r < 0)
+                        return -errno;
+
                 *l = x;
         } else {
                 r = sd_bus_call_method(
@@ -587,7 +578,7 @@ static int add_name_change_match(sd_bus *bus,
         return 0;
 }
 
-static int kdbus_name_query(
+static int kdbus_name_info(
                 sd_bus *bus,
                 const char *name,
                 uint64_t mask,
@@ -596,52 +587,32 @@ static int kdbus_name_query(
 
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
+        _cleanup_free_ struct kdbus_cmd_name_info *cmd = NULL;
         _cleanup_free_ char *unique = NULL;
-        struct kdbus_cmd_name_info *name_info = NULL;
+        struct kdbus_name_info *name_info;
         struct kdbus_item *item;
         uint64_t attach_flags, m;
-        size_t slen, size;
+        size_t size;
         int r;
 
         r = kdbus_translate_attach_flags(mask, &attach_flags);
         if (r < 0)
                 return r;
 
-        slen = strlen(name) + 1;
-
-        /*
-         * The structure is used for both directions. Start with 8k buffer size and
-         * expand to the size kdbus reports in case we fail.
-         */
-        size = slen + 8192;
-
-        for(;;) {
-                name_info = realloc(name_info, size);
-                if (!name_info)
-                        return -ENOMEM;
-
-                memset(name_info, 0, size);
-
-                name_info->size = size;
-                name_info->attach_flags = attach_flags;
-
-                item = name_info->items;
-                item->type = KDBUS_NAME_INFO_ITEM_NAME;
-                item->size = KDBUS_ITEM_SIZE(slen);
-                strcpy(item->str, name);
+        size = sizeof(struct kdbus_cmd_name_info) + strlen(name) + 1;
+        cmd = malloc0(size);
+        if (!cmd)
+                return -ENOMEM;
 
-                r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_QUERY, name_info);
-                if (r < 0) {
-                        if (errno == ENOBUFS && size != name_info->size) {
-                                size = name_info->size;
-                                continue;
-                        }
+        cmd ->size = size;
+        cmd->attach_flags = attach_flags;
+        strcpy(cmd->name, name);
 
-                        return -errno;
-                }
+        r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_INFO, cmd);
+        if (r < 0)
+                return -errno;
 
-                break;
-        }
+        name_info = (struct kdbus_name_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
 
         asprintf(&unique, ":1.%llu", (unsigned long long) name_info->id);
 
@@ -756,6 +727,10 @@ static int kdbus_name_query(
                 }
         }
 
+        r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_FREE, &cmd->offset);
+        if (r < 0)
+                return -errno;
+
         if (creds) {
                 *creds = c;
                 c = NULL;
@@ -784,7 +759,7 @@ _public_ int sd_bus_get_owner(
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
         if (bus->is_kernel)
-                return kdbus_name_query(bus, name, mask, owner, creds);
+                return kdbus_name_info(bus, name, mask, owner, creds);
 
         return sd_bus_get_owner_dbus(bus, name, mask, owner, creds);
 }
index 1cab254..b63fe56 100644 (file)
@@ -459,7 +459,7 @@ static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
         assert(k);
 
         off = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer;
-        ioctl(bus->input_fd, KDBUS_CMD_MSG_RELEASE, &off);
+        ioctl(bus->input_fd, KDBUS_CMD_FREE, &off);
 
         KDBUS_PART_FOREACH(d, k, items) {
 
index 920488d..56bf88c 100644 (file)
@@ -129,7 +129,7 @@ static void message_free(sd_bus_message *m) {
                 uint64_t off;
 
                 off = (uint8_t *)m->kdbus - (uint8_t *)m->bus->kdbus_buffer;
-                ioctl(m->bus->input_fd, KDBUS_CMD_MSG_RELEASE, &off);
+                ioctl(m->bus->input_fd, KDBUS_CMD_FREE, &off);
         }
 
         if (m->bus)
index bfd299b..3dafece 100644 (file)
@@ -297,6 +297,11 @@ enum {
 enum {
        _KDBUS_MAKE_NULL,
        KDBUS_MAKE_NAME,
+       KDBUS_MAKE_CRED,        /* allow translator services which connect
+                                * to the bus on behalf of somebody else,
+                                * allow specifying the credentials of the
+                                * client to connect on behalf on. Needs
+                                * privileges */
 };
 
 struct kdbus_cmd_bus_make {
@@ -345,7 +350,7 @@ enum {
        KDBUS_NAME_IN_QUEUE                     = 1 << 16,
 };
 
-/* We allow (de)regestration of names of other peers */
+/* We allow (de)registration of names of other peers */
 struct kdbus_cmd_name {
        __u64 size;
        __u64 flags;
@@ -354,32 +359,39 @@ struct kdbus_cmd_name {
        char name[0];
 };
 
+/* KDBUS_CMD_NAME_LIST */
 enum {
        KDBUS_NAME_LIST_UNIQUE_NAMES            = 1 <<  0,
 };
 
-struct kdbus_cmd_names {
-       __u64 size;
+struct kdbus_cmd_name_list {
        __u64 flags;
-       struct kdbus_cmd_name names[0];
+       __u64 offset;                   /* returned offset in the caller's buffer */
 };
 
-enum {
-       _KDBUS_NAME_INFO_ITEM_NULL,
-       KDBUS_NAME_INFO_ITEM_NAME,      /* userspace → kernel */
-       KDBUS_NAME_INFO_ITEM_SECLABEL,  /* kernel → userspace */
-       KDBUS_NAME_INFO_ITEM_AUDIT,     /* kernel → userspace */
+struct kdbus_name_list {
+       __u64 size;
+       struct kdbus_cmd_name names[0];
 };
 
+/* KDBUS_CMD_NAME_INFO */
 struct kdbus_cmd_name_info {
-       __u64 size;                     /* overall size of info */
+       __u64 size;
        __u64 flags;                    /* query flags */
        __u64 attach_flags;             /* which meta data payload to attach */
-       __u64 id;                       /* either ID, or 0 and _ITEM_NAME follows */
-       struct kdbus_creds creds;
+       __u64 id;                       /* either ID, or 0 and name follows */
+       __u64 offset;                   /* returned offset in the caller's buffer */
+       char name[0];
+};
+
+struct kdbus_name_info {
+       __u64 size;
+       __u64 id;
+       __u64 flags;                    /* connection flags */
        struct kdbus_item items[0];     /* list of item records */
 };
 
+/* KDBUS_CMD_MATCH_ADD/REMOVE */
 enum {
        _KDBUS_MATCH_NULL,
        KDBUS_MATCH_BLOOM,              /* Matches a mask blob against KDBUS_MSG_BLOOM */
@@ -399,22 +411,13 @@ struct kdbus_cmd_match {
        struct kdbus_item items[0];
 };
 
+/* KDBUS_CMD_MONITOR */
 struct kdbus_cmd_monitor {
        __u64 id;               /* We allow setting the monitor flag of other peers */
        unsigned int enable;    /* A boolean to enable/disable monitoring */
        __u32 __pad;
 };
 
-/* FD states:
- * control nodes: unset
- *   bus owner  (via KDBUS_CMD_BUS_MAKE)
- *   ns owner   (via KDBUS_CMD_NS_MAKE)
- *
- * ep nodes: unset
- *   connected  (via KDBUS_CMD_HELLO)
- *   starter    (via KDBUS_CMD_HELLO with KDBUS_CMD_HELLO_STARTER)
- *   ep owner   (via KDBUS_CMD_EP_MAKE)
- */
 enum {
        /* kdbus control node commands: require unset state */
        KDBUS_CMD_BUS_MAKE =            _IOW(KDBUS_IOC_MAGIC, 0x00, struct kdbus_cmd_bus_make),
@@ -427,12 +430,12 @@ enum {
        /* kdbus ep node commands: require connected state */
        KDBUS_CMD_MSG_SEND =            _IOW(KDBUS_IOC_MAGIC, 0x40, struct kdbus_msg),
        KDBUS_CMD_MSG_RECV =            _IOR(KDBUS_IOC_MAGIC, 0x41, __u64 *),
-       KDBUS_CMD_MSG_RELEASE =         _IOW(KDBUS_IOC_MAGIC, 0x42, __u64 *),
+       KDBUS_CMD_FREE =                _IOW(KDBUS_IOC_MAGIC, 0x42, __u64 *),
 
        KDBUS_CMD_NAME_ACQUIRE =        _IOWR(KDBUS_IOC_MAGIC, 0x50, struct kdbus_cmd_name),
        KDBUS_CMD_NAME_RELEASE =        _IOW(KDBUS_IOC_MAGIC, 0x51, struct kdbus_cmd_name),
-       KDBUS_CMD_NAME_LIST =           _IOWR(KDBUS_IOC_MAGIC, 0x52, struct kdbus_cmd_names),
-       KDBUS_CMD_NAME_QUERY =          _IOWR(KDBUS_IOC_MAGIC, 0x53, struct kdbus_cmd_name_info),
+       KDBUS_CMD_NAME_LIST =           _IOWR(KDBUS_IOC_MAGIC, 0x52, struct kdbus_cmd_name_list),
+       KDBUS_CMD_NAME_INFO =           _IOWR(KDBUS_IOC_MAGIC, 0x53, struct kdbus_cmd_name_info),
 
        KDBUS_CMD_MATCH_ADD =           _IOW(KDBUS_IOC_MAGIC, 0x60, struct kdbus_cmd_match),
        KDBUS_CMD_MATCH_REMOVE =        _IOW(KDBUS_IOC_MAGIC, 0x61, struct kdbus_cmd_match),
index 0d5deb6..37b6fed 100644 (file)
@@ -1153,9 +1153,8 @@ _public_ void sd_bus_close(sd_bus *bus) {
 
         /* We'll leave the fd open in case this is a kernel bus, since
          * there might still be memblocks around that reference this
-         * bus, and they might need to invoke the
-         * KDBUS_CMD_MSG_RELEASE ioctl on the fd when they are
-         * freed. */
+         * bus, and they might need to invoke the * KDBUS_CMD_FREE
+         * ioctl on the fd when they are freed. */
 }
 
 static void bus_enter_closing(sd_bus *bus) {