]> www.infradead.org Git - users/sagi/libnvme.git/commitdiff
MI: switch from libsdbus to libdbus
authorJeremy Kerr <jk@codeconstruct.com.au>
Mon, 21 Nov 2022 08:35:38 +0000 (16:35 +0800)
committerJeremy Kerr <jk@codeconstruct.com.au>
Wed, 23 Nov 2022 07:59:41 +0000 (15:59 +0800)
libsystemd is not generally available as a static library, and we would
like to produce a static nvme-cli. This change switches to libdbus
instead.

This requires slightly more boilerplate code for the dbus
marshalling/unmarshalling as part of the MCTP endpoint scan, but means
we have a simpler upstream lib dependency.

Fixes: https://github.com/linux-nvme/nvme-cli/issues/1734
Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
examples/meson.build
examples/mi-conf.c
meson.build
src/meson.build
src/nvme/mi-mctp.c

index 31d05d711aea20bdf363573bae3a21a3d2c5afe3..3139311a041fc5903e27149de78eab66f5fce4e8 100644 (file)
@@ -40,11 +40,11 @@ executable(
     include_directories: [incdir, internal_incdir]
 )
 
-if libsystemd_dep.found()
+if libdbus_dep.found()
     executable(
         'mi-conf',
         ['mi-conf.c'],
-        dependencies: [libnvme_mi_dep, libsystemd_dep],
+        dependencies: [libnvme_mi_dep, libdbus_dep],
         include_directories: [incdir, internal_incdir]
     )
 endif
index 90d590eac22109c328eaf0cff3005e66279e0c63..4fdd4055348d81a4d6018855a101b820e754f488 100644 (file)
@@ -23,7 +23,7 @@
 #include <ccan/array_size/array_size.h>
 #include <ccan/endian/endian.h>
 
-#include <systemd/sd-bus.h>
+#include <dbus/dbus.h>
 
 #define MCTP_DBUS_NAME "xyz.openbmc_project.MCTP"
 #define MCTP_DBUS_PATH "/xyz/openbmc_project/mctp"
@@ -79,10 +79,11 @@ int find_port(nvme_mi_ep_t ep, uint8_t *portp, uint16_t *mtup)
        return found ? 0 : 1;
 }
 
-int set_local_mtu(sd_bus *bus, unsigned int net, uint8_t eid, uint32_t mtu)
+int set_local_mtu(DBusConnection *bus, unsigned int net, uint8_t eid,
+                 uint32_t mtu)
 {
-       sd_bus_error err = SD_BUS_ERROR_NULL;
-       sd_bus_message *resp;
+       DBusMessage *msg, *resp;
+       DBusError berr;
        char *ep_path;
        int rc;
 
@@ -99,26 +100,50 @@ int set_local_mtu(sd_bus *bus, unsigned int net, uint8_t eid, uint32_t mtu)
         */
        mtu += 4;
 
-       rc = sd_bus_call_method(bus, MCTP_DBUS_NAME, ep_path,
-                               MCTP_DBUS_EP_IFACE, "SetMTU", &err, &resp,
-                               "u", mtu);
-       if (rc < 0) {
-               warnx("Failed to set local MTU: %s", strerror(-rc));
-               return -1;
+       rc = -1;
+       dbus_error_init(&berr);
+       msg = dbus_message_new_method_call(MCTP_DBUS_NAME, ep_path,
+                                          MCTP_DBUS_EP_IFACE, "SetMTU");
+       if (!msg) {
+               warnx("Can't create D-Bus message");
+               goto out;
        }
 
-       return 0;
+       rc = dbus_message_append_args(msg,
+                                     DBUS_TYPE_UINT32, &mtu,
+                                     DBUS_TYPE_INVALID);
+       if (!rc) {
+               warnx("Can't construct D-Bus message arguments");
+               goto out_free_msg;
+       }
+
+       resp = dbus_connection_send_with_reply_and_block(bus, msg,
+                                                        2000, &berr);
+       if (!resp) {
+               warnx("Failed to set local MTU: %s (%s)", berr.message,
+                     berr.name);
+       } else {
+               dbus_message_unref(resp);
+               rc = 0;
+       }
+
+out_free_msg:
+       dbus_message_unref(msg);
+out:
+       dbus_error_free(&berr);
+       return rc;
 }
 
 int main(int argc, char **argv)
 {
        uint16_t cur_mtu, mtu;
+       DBusConnection *bus;
        const char *devstr;
        uint8_t eid, port;
        nvme_root_t root;
        unsigned int net;
        nvme_mi_ep_t ep;
-       sd_bus *bus;
+       DBusError berr;
        int rc;
 
        if (argc != 2) {
@@ -141,10 +166,13 @@ int main(int argc, char **argv)
                goto out_free_root;
        }
 
-       rc = sd_bus_default_system(&bus);
-       if (rc < 0) {
+       dbus_error_init(&berr);
+       bus = dbus_bus_get(DBUS_BUS_SYSTEM, &berr);
+       if (!bus) {
+               warnx("Failed opening D-Bus: %s (%s)\n",
+                     berr.message, berr.name);
+               rc = -1;
                goto out_close_ep;
-               warnx("Failed opening D-Bus: %s\n", strerror(-rc));
        }
 
        rc = find_port(ep, &port, &mtu);
@@ -185,8 +213,9 @@ int main(int argc, char **argv)
        }
 
 out_close_bus:
-       sd_bus_close(bus);
+       dbus_connection_unref(bus);
 out_close_ep:
+       dbus_error_free(&berr);
        nvme_mi_close(ep);
 out_free_root:
        nvme_mi_free_root(root);
index c7b0c59ad1f25f42858add4b29348d5ec55757e9..674ef4b0a1e43831e629c00fe658124b73c8bb5b 100644 (file)
@@ -89,24 +89,9 @@ if openssl_dep.found()
            description: 'OpenSSL/LibreSSL API version @0@'.format(api_version))
 endif
 
-# Check for libsystemd availability. Optional, only required for MCTP dbus scan
-libsystemd_dep = dependency('libsystemd', version: '>219', required: false)
-if libsystemd_dep.found()
-  # When the user has CFLAGS=-static environment variable set
-  # dependency() will find the shared library libsystemd Thus double
-  # check if we are able to link
-  if not cc.links('''#include <systemd/sd-bus.h>
-                     int main(void) {
-                         struct sd_bus *ret;
-                         return sd_bus_default(&ret);
-                   }
-                   ''',
-                   dependencies: libsystemd_dep,
-                   name: 'libsystemd')
-       libsystemd_dep = declare_dependency()
-  endif
-  conf.set('CONFIG_LIBSYSTEMD', libsystemd_dep.found(), description: 'Is libsystemd(>219) available?')
-endif
+# Check for libdus availability. Optional, only required for MCTP dbus scan
+libdbus_dep = dependency('dbus-1', required: false)
+conf.set('CONFIG_DBUS', libdbus_dep.found(), description: 'Enable dbus support?')
 
 # local (cross-compilable) implementations of ccan configure steps
 conf.set10(
index 9e49a077d8889c623cc953bac6393dc15d649702..1186e81f30637796408ac7181cc3a5824e8d86d7 100644 (file)
@@ -33,7 +33,7 @@ deps = [
 ]
 
 mi_deps = [
-    libsystemd_dep,
+    libdbus_dep,
 ]
 
 source_dir = meson.current_source_dir()
index b3239ccbf27afbbd7dee6bd0121b88573e105a67..0c5972a5677c4bebda2ddd343aebeaf2b12f74c3 100644 (file)
 
 #include <ccan/endian/endian.h>
 
-#ifdef CONFIG_LIBSYSTEMD
-#include <systemd/sd-event.h>
-#include <systemd/sd-bus.h>
-#include <systemd/sd-id128.h>
+#ifdef CONFIG_DBUS
+#include <dbus/dbus.h>
 
 #define MCTP_DBUS_PATH "/xyz/openbmc_project/mctp"
 #define MCTP_DBUS_IFACE "xyz.openbmc_project.MCTP"
@@ -522,19 +520,7 @@ err_free_ep:
        return NULL;
 }
 
-#ifdef CONFIG_LIBSYSTEMD
-
-/* helper for handling dbus errors: D-Bus API returns a negtive errno on
- * failure; set errno and log.
- */
-static void _dbus_err(nvme_root_t root, int rc, int line)
-{
-       nvme_msg(root, LOG_ERR, "MCTP D-Bus failed line %d: %s %d\n",
-               line, strerror(-rc), rc);
-       errno = -rc;
-}
-
-#define dbus_err(r, rc) _dbus_err(r, rc, __LINE__)
+#ifdef CONFIG_DBUS
 
 static int nvme_mi_mctp_add(nvme_root_t root, unsigned int netid, __u8 eid)
 {
@@ -558,84 +544,99 @@ static int nvme_mi_mctp_add(nvme_root_t root, unsigned int netid, __u8 eid)
        return 0;
 }
 
-/* We can't rely on sd_bus_message_enter_container() == 0 at the end of
-   a dictionary (it returns -ENXIO) so we test separately */
-static bool container_end(sd_bus_message *m)
+static bool dbus_object_is_type(DBusMessageIter *obj, int type)
+{
+       return dbus_message_iter_get_arg_type(obj) == type;
+}
+
+static bool dbus_object_is_dict(DBusMessageIter *obj)
+{
+       return dbus_object_is_type(obj, DBUS_TYPE_ARRAY) &&
+               dbus_message_iter_get_element_type(obj) == DBUS_TYPE_DICT_ENTRY;
+}
+
+static int read_variant_basic(DBusMessageIter *var, int type, void *val)
 {
-       return sd_bus_message_peek_type(m, NULL, NULL) == 0;
+       if (!dbus_object_is_type(var, type))
+               return -1;
+
+       dbus_message_iter_get_basic(var, val);
+
+       return 0;
+}
+
+static bool has_message_type(DBusMessageIter *prop, uint8_t type)
+{
+       DBusMessageIter inner;
+       uint8_t *types;
+       int i, n;
+
+       if (!dbus_object_is_type(prop, DBUS_TYPE_ARRAY) ||
+           dbus_message_iter_get_element_type(prop) != DBUS_TYPE_BYTE)
+               return false;
+
+       dbus_message_iter_recurse(prop, &inner);
+
+       dbus_message_iter_get_fixed_array(&inner, &types, &n);
+
+       for (i = 0; i < n; i++) {
+               if (types[i] == type)
+                       return true;
+       }
+
+       return false;
 }
 
 static int handle_mctp_endpoint(nvme_root_t root, const char* objpath,
-       sd_bus_message *m)
+       DBusMessageIter *props)
 {
        bool have_eid = false, have_net = false, have_nvmemi = false;
        mctp_eid_t eid;
        int net;
        int rc;
 
-       /* Iterate properties on this interface */
-       while (!container_end(m)) {
-               /* Enter property dict */
-               rc = sd_bus_message_enter_container(m, 'a', "{sv}");
-               if (rc < 0) {
-                       dbus_err(root, rc);
+       /* for each property */
+       for (;;) {
+               DBusMessageIter prop, val;
+               const char *propname;
+
+               dbus_message_iter_recurse(props, &prop);
+
+               if (!dbus_object_is_type(&prop, DBUS_TYPE_STRING)) {
+                       nvme_msg(root, LOG_ERR,
+                                "error unmashalling object (propname)\n");
                        return -1;
                }
 
-               while (!container_end(m)) {
-                       char *propname = NULL;
-                       size_t sz;
-                       const uint8_t *types = NULL;
-                       /* Enter property item */
-                       rc = sd_bus_message_enter_container(m, 'e', "sv");
-                       if (rc < 0) {
-                               dbus_err(root, rc);
-                               return -1;
-                       }
-
-                       rc = sd_bus_message_read(m, "s", &propname);
-                       if (rc < 0) {
-                               dbus_err(root, rc);
-                               return -1;
-                       }
-
-                       if (strcmp(propname, "EID") == 0) {
-                               rc = sd_bus_message_read(m, "v", "y", &eid);
-                               have_eid = true;
-                       } else if (strcmp(propname, "NetworkId") == 0) {
-                               rc = sd_bus_message_read(m, "v", "i", &net);
-                               have_net = true;
-                       } else if (strcmp(propname, "SupportedMessageTypes") == 0) {
-                               sd_bus_message_enter_container(m, 'v', "ay");
-                               rc = sd_bus_message_read_array(m, 'y', (const void**)&types, &sz);
-                               if (rc >= 0)
-                                       for (size_t s = 0; s < sz; s++)
-                                               if (types[s] == MCTP_TYPE_NVME)
-                                                       have_nvmemi = true;
-                               sd_bus_message_exit_container(m);
-                       } else {
-                               rc = sd_bus_message_skip(m, "v");
-                       }
-
-                       if (rc < 0) {
-                               dbus_err(root, rc);
-                               return -1;
-                       }
-
-                       /* Exit prop item */
-                       rc = sd_bus_message_exit_container(m);
-                       if (rc < 0) {
-                               dbus_err(root, rc);
-                               return -1;
-                       }
-               }
+               dbus_message_iter_get_basic(&prop, &propname);
 
-               /* Exit property dict */
-               rc = sd_bus_message_exit_container(m);
-               if (rc < 0) {
-                       dbus_err(root, rc);
+               dbus_message_iter_next(&prop);
+
+               if (!dbus_object_is_type(&prop, DBUS_TYPE_VARIANT)) {
+                       nvme_msg(root, LOG_ERR,
+                                "error unmashalling object (propval)\n");
                        return -1;
                }
+
+               dbus_message_iter_recurse(&prop, &val);
+
+               if (!strcmp(propname, "EID")) {
+                       rc = read_variant_basic(&val, DBUS_TYPE_BYTE, &eid);
+                       have_eid = true;
+
+               } else if (!strcmp(propname, "NetworkId")) {
+                       rc = read_variant_basic(&val, DBUS_TYPE_INT32, &net);
+                       have_net = true;
+
+               } else if (!strcmp(propname, "SupportedMessageTypes")) {
+                       have_nvmemi = has_message_type(&val, MCTP_TYPE_NVME);
+               }
+
+               if (rc)
+                       return rc;
+
+               if (!dbus_message_iter_next(props))
+                       break;
        }
 
        if (have_nvmemi) {
@@ -659,70 +660,61 @@ static int handle_mctp_endpoint(nvme_root_t root, const char* objpath,
        return rc;
 }
 
-static int handle_mctp_obj(nvme_root_t root, sd_bus_message *m)
+/* obj is an array of (object path, interfaces) dict entries - ie., dbus type
+ *   a{oa{sa{sv}}}
+ */
+static int handle_mctp_obj(nvme_root_t root, DBusMessageIter *obj)
 {
-       char *objpath = NULL;
-       char *ifname = NULL;
-       int rc;
+       const char *objpath = NULL;
+       DBusMessageIter intfs;
 
-       rc = sd_bus_message_read(m, "o", &objpath);
-       if (rc < 0) {
-               dbus_err(root, rc);
+       if (!dbus_object_is_type(obj, DBUS_TYPE_OBJECT_PATH)) {
+               nvme_msg(root, LOG_ERR, "error unmashalling object (path)\n");
                return -1;
        }
 
-       /* Enter response object: our array of (string, property dict)
-        * values */
-       rc = sd_bus_message_enter_container(m, 'a', "{sa{sv}}");
-       if (rc < 0) {
-               dbus_err(root, rc);
+       dbus_message_iter_get_basic(obj, &objpath);
+
+       dbus_message_iter_next(obj);
+
+       if (!dbus_object_is_dict(obj)) {
+               nvme_msg(root, LOG_ERR, "error unmashalling object (intfs)\n");
                return -1;
        }
 
+       dbus_message_iter_recurse(obj, &intfs);
 
        /* for each interface */
-       while (!container_end(m)) {
-               /* Enter interface item */
-               rc = sd_bus_message_enter_container(m, 'e', "sa{sv}");
-               if (rc < 0) {
-                       dbus_err(root, rc);
-                       return -1;
-               }
+       for (;;) {
+               DBusMessageIter props, intf;
+               const char *intfname;
 
-               rc = sd_bus_message_read(m, "s", &ifname);
-               if (rc < 0) {
-                       dbus_err(root, rc);
+               dbus_message_iter_recurse(&intfs, &intf);
+
+               if (!dbus_object_is_type(&intf, DBUS_TYPE_STRING)) {
+                       nvme_msg(root, LOG_ERR,
+                                "error unmashalling object (intf)\n");
                        return -1;
                }
 
-               if (!strcmp(ifname, MCTP_DBUS_IFACE_ENDPOINT)) {
-
-                       rc = handle_mctp_endpoint(root, objpath, m);
-                       if (rc < 0) {
-                               /* continue to next object */
-                       }
-               } else {
-                       /* skip the interfaces we don't care about */
-                       rc = sd_bus_message_skip(m, "a{sv}");
-                       if (rc < 0) {
-                               dbus_err(root, rc);
-                               return -1;
-                       }
+               dbus_message_iter_get_basic(&intf, &intfname);
+
+               if (strcmp(intfname, MCTP_DBUS_IFACE_ENDPOINT)) {
+                       if (!dbus_message_iter_next(&intfs))
+                               break;
+                       continue;
                }
 
-               /* Exit interface item */
-               rc = sd_bus_message_exit_container(m);
-               if (rc < 0) {
-                       dbus_err(root, rc);
+               dbus_message_iter_next(&intf);
+
+               if (!dbus_object_is_dict(&intf)) {
+                       nvme_msg(root, LOG_ERR,
+                                "error unmarshalling object (props)\n");
                        return -1;
                }
-       }
 
-       /* Exit response object */
-       rc = sd_bus_message_exit_container(m);
-       if (rc < 0) {
-               dbus_err(root, rc);
-               return -1;
+               dbus_message_iter_recurse(&intf, &props);
+               return handle_mctp_endpoint(root, objpath, &props);
        }
 
        return 0;
@@ -730,85 +722,85 @@ static int handle_mctp_obj(nvme_root_t root, sd_bus_message *m)
 
 nvme_root_t nvme_mi_scan_mctp(void)
 {
-       sd_bus *bus = NULL;
-       sd_bus_message *resp = NULL;
-       sd_bus_error berr = SD_BUS_ERROR_NULL;
-       int rc, errno_save;
+       DBusMessage *msg, *resp = NULL;
+       DBusConnection *bus = NULL;
+       DBusMessageIter args, objs;
+       int errno_save, rc = -1;
        nvme_root_t root;
+       dbus_bool_t drc;
+       DBusError berr;
 
        root = nvme_mi_create_root(NULL, DEFAULT_LOGLEVEL);
        if (!root) {
                errno = ENOMEM;
-               rc = -1;
+               return NULL;
+       }
+
+       dbus_error_init(&berr);
+
+       bus = dbus_bus_get(DBUS_BUS_SYSTEM, &berr);
+       if (!bus) {
+               nvme_msg(root, LOG_ERR, "Failed connecting to D-Bus: %s (%s)\n",
+                        berr.message, berr.name);
                goto out;
        }
 
-       rc = sd_bus_default_system(&bus);
-       if (rc < 0) {
-               nvme_msg(root, LOG_ERR, "Failed opening D-Bus: %s\n",
-                        strerror(-rc));
-               errno = -rc;
-               rc = -1;
+       msg = dbus_message_new_method_call(MCTP_DBUS_IFACE,
+                                          MCTP_DBUS_PATH,
+                                          "org.freedesktop.DBus.ObjectManager",
+                                          "GetManagedObjects");
+       if (!msg) {
+               nvme_msg(root, LOG_ERR, "Failed creating call message\n");
                goto out;
        }
 
-       rc = sd_bus_call_method(bus,
-                              MCTP_DBUS_IFACE,
-                              MCTP_DBUS_PATH,
-                              "org.freedesktop.DBus.ObjectManager",
-                              "GetManagedObjects",
-                              &berr,
-                              &resp,
-                              "");
-       if (rc < 0) {
+       resp = dbus_connection_send_with_reply_and_block(bus, msg,
+                                                        DBUS_TIMEOUT_USE_DEFAULT,
+                                                        &berr);
+       dbus_message_unref(msg);
+       if (!resp) {
                nvme_msg(root, LOG_ERR, "Failed querying MCTP D-Bus: %s (%s)\n",
                         berr.message, berr.name);
-               errno = -rc;
-               rc = -1;
                goto out;
        }
 
-       rc = sd_bus_message_enter_container(resp, 'a', "{oa{sa{sv}}}");
-       if (rc != 1) {
-               dbus_err(root, rc);
-               if (rc == 0)
-                       errno = EPROTO;
-               rc = -1;
+       /* argument container */
+       drc = dbus_message_iter_init(resp, &args);
+       if (!drc) {
+               nvme_msg(root, LOG_ERR, "can't read dbus reply args\n");
                goto out;
        }
 
-       /* Iterate over all managed objects */
-       while (!container_end(resp)) {
-               rc = sd_bus_message_enter_container(resp, 'e', "oa{sa{sv}}");
-               if (rc < 0) {
-                       dbus_err(root, rc);
-                       rc = -1;
-                       goto out;
-               }
+       if (!dbus_object_is_dict(&args)) {
+               nvme_msg(root, LOG_ERR, "error unmashalling args\n");
+               goto out;
+       }
 
-               handle_mctp_obj(root, resp);
+       /* objects container */
+       dbus_message_iter_recurse(&args, &objs);
 
-               rc = sd_bus_message_exit_container(resp);
-               if (rc < 0) {
-                       dbus_err(root, rc);
-                       rc = -1;
-                       goto out;
-               }
-       }
+       rc = 0;
 
-       rc = sd_bus_message_exit_container(resp);
-       if (rc < 0) {
-               dbus_err(root, rc);
-               rc = -1;
-               goto out;
+       for (;;) {
+               DBusMessageIter ent;
+
+               dbus_message_iter_recurse(&objs, &ent);
+
+               rc = handle_mctp_obj(root, &ent);
+               if (rc)
+                       break;
+
+               if (!dbus_message_iter_next(&objs))
+                       break;
        }
-       rc = 0;
 
 out:
        errno_save = errno;
-       sd_bus_error_free(&berr);
-       sd_bus_message_unref(resp);
-       sd_bus_unref(bus);
+       if (resp)
+               dbus_message_unref(resp);
+       if (bus)
+               dbus_connection_unref(bus);
+       dbus_error_free(&berr);
 
        if (rc < 0) {
                if (root) {
@@ -820,11 +812,11 @@ out:
        return root;
 }
 
-#else /* CONFIG_LIBSYSTEMD */
+#else /* CONFIG_DBUS */
 
 nvme_root_t nvme_mi_scan_mctp(void)
 {
        return NULL;
 }
 
-#endif /* CONFIG_LIBSYSTEMD */
+#endif /* CONFIG_DBUS */