[SSSD] [PATCH] Implement org.freedesktop.DBus.Properties.GetAll for primitive types

Jakub Hrozek jhrozek at redhat.com
Mon May 26 13:53:26 UTC 2014


On Sat, May 24, 2014 at 02:13:28PM +0200, Lukas Slebodnik wrote:
> On (23/05/14 17:39), Jakub Hrozek wrote:
> >On Fri, May 23, 2014 at 11:56:32AM +0200, Jakub Hrozek wrote:
> >> On Fri, May 23, 2014 at 08:31:49AM +0200, Lukas Slebodnik wrote:
> >> > On (21/05/14 22:53), Jakub Hrozek wrote:
> >> > >Hi,
> >> > >
> >> > >the attached patches implement the
> >> > >org.freedesktop.DBus.Properties.GetAll method for retrieving primitive
> >> > >types and their arrays.
> >> > >
> >> > >The patchset build on the previous set (currently still on review) that
> >> > >implements the .Get method. The GetAll handler simply walks through the
> >> > >existing getters and retrieves the results, storing them in a single
> >> > >variant.
> >> > >
> >> > >The patches include a unit test that tests all currently supported
> >> > >combinations of primitive types and array of primitive types.
> >> > 
> >> > >From fc4b278c0914b2c7001393e471f4f6f0b532ba54 Mon Sep 17 00:00:00 2001
> >> > >From: Jakub Hrozek <jhrozek at redhat.com>
> >> > >Date: Wed, 21 May 2014 16:48:45 +0200
> >> > >Subject: [PATCH 1/5] SBUS: Add utility function sbus_add_variant_to_dict
> >> > >
> >> > >---
> >> > > src/sbus/sssd_dbus.h            |   5 ++
> >> > > src/sbus/sssd_dbus_properties.c | 116 ++++++++++++++++++++++++++++++++++++++++
> >> > > 2 files changed, 121 insertions(+)
> >> > >
> >> > src/sbus/sssd_dbus_properties.c:287:41: error: no member named 'invoker_get_all' in
> >> >       'struct sbus_interface_meta'
> >> >                                   meta->invoker_get_all);
> >> >                                   ~~~~  ^
> >> > It is introduced in 4th aptch
> >> > "SBUS: Implement org.freedesktop.DBus.Properties.GetAll for primitive types"
> >> > 
> >> > >From 32d84445012991dba38ee5b60f5614aca70b889d Mon Sep 17 00:00:00 2001
> >> > >From: Jakub Hrozek <jhrozek at redhat.com>
> >> > >Date: Wed, 21 May 2014 20:10:23 +0200
> >> > >Subject: [PATCH 5/5] SBUS: Add org.freedesktop.DBus.Properties.GetAll to
> >> > > Introspection
> >> > 
> >> > FAIL: sbus_tests
> >> > 
> >> > sbys_tests.log file is attached.
> >> > 
> >> > LS
> >> 
> >> Ah, I didn't amend the test to include GetAll in introspection like I
> >> did with Get, thanks. I'll prepare a new set.
> >
> >Hi,
> >
> >new patches are attached, but only the Introspection patch had changed
> >-- I added the GetAll XML to the unit test.
> 
> >From 9511be0f60affc2909ec2388f0d1ab5cc8487647 Mon Sep 17 00:00:00 2001
> >From: Jakub Hrozek <jhrozek at redhat.com>
> >Date: Wed, 21 May 2014 21:29:15 +0200
> >Subject: [PATCH 4/5] SBUS: Implement org.freedesktop.DBus.Properties.GetAll
> > for primitive types
> >
> >This patch implements the GetAll method of the
> >org.freedesktop.DBus.Properties interface by iterating over the
> >available getters and putting all the results into a single getter.
> >
> >The patch includes a unit test that exercies all currently supported
> >array types.
> >---
> > src/monitor/monitor_iface_generated.c         |   2 +
> > src/providers/data_provider_iface_generated.c |   2 +
> > src/responder/ifp/ifp_iface_generated.c       |   1 +
> > src/sbus/sbus_codegen                         |  96 +++++-
> > src/sbus/sssd_dbus_meta.h                     |   1 +
> > src/tests/sbus_codegen_tests.c                | 299 +++++++++++++++++++
> > src/tests/sbus_codegen_tests_generated.c      | 415 +++++++++++++++++++++++++-
> > 7 files changed, 806 insertions(+), 10 deletions(-)
> >
> 
> //snip
> 
> >diff --git a/src/sbus/sssd_dbus_meta.h b/src/sbus/sssd_dbus_meta.h
> >index f25b1ac28abf1b1ef53fa54a090fa84ef868ab77..2cb9e95e3e12da55b1f101e076a0e05203984215 100644
> >--- a/src/sbus/sssd_dbus_meta.h
> >+++ b/src/sbus/sssd_dbus_meta.h
> >@@ -80,6 +80,7 @@ struct sbus_interface_meta {
> >     const struct sbus_method_meta *methods;
> >     const struct sbus_signal_meta *signals;
> >     const struct sbus_property_meta *properties;
> >+    sbus_method_invoker_fn invoker_get_all;
> > };
> >
> Move this change to the 1st patch.

Fixed.

> 
> There is little problem with introspection.
> 
> sh# gdbus introspect --system --dest org.freedesktop.sssd.infopipe --object-path / --recurse
> 
> ==11539== Jump to the invalid address stated on the next line
> ==11539==    at 0x0: ???
> ==11539==    by 0x7C3E25C: sbus_request_invoke_or_finish (sssd_dbus_request.c:69)
> ==11539==    by 0x7C3DC47: sbus_properties_dispatch (sssd_dbus_properties.c:361)
> ==11539==    by 0x7C3BD87: sbus_handler_got_caller_id (sssd_dbus_connection.c:524)
> ==11539==    by 0x4C2D753: tevent_common_loop_immediate (tevent_immediate.c:135)
> ==11539==    by 0x4C31FBD: epoll_event_loop_once (tevent_epoll.c:908)
> ==11539==    by 0x4C306B6: std_event_loop_once (tevent_standard.c:112)
> ==11539==    by 0x4C2CF2C: _tevent_loop_once (tevent.c:530)
> ==11539==    by 0x4C2D0CA: tevent_common_loop_wait (tevent.c:634)
> ==11539==    by 0x4C30656: std_event_loop_wait (tevent_standard.c:138)
> ==11539==    by 0x7C42C12: server_loop (server.c:587)
> ==11539==    by 0x10C571: main (ifpsrv.c:397)
> ==11539==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
> ==11539== 
> ==11539== 
> ==11539== Process terminating with default action of signal 11 (SIGSEGV)
> ==11539==  Bad permissions for mapped region at address 0x0
> ==11539==    at 0x0: ???
> ==11539==    by 0x7C3E25C: sbus_request_invoke_or_finish (sssd_dbus_request.c:69)
> ==11539==    by 0x7C3DC47: sbus_properties_dispatch (sssd_dbus_properties.c:361)
> ==11539==    by 0x7C3BD87: sbus_handler_got_caller_id (sssd_dbus_connection.c:524)
> ==11539==    by 0x4C2D753: tevent_common_loop_immediate (tevent_immediate.c:135)
> ==11539==    by 0x4C31FBD: epoll_event_loop_once (tevent_epoll.c:908)
> ==11539==    by 0x4C306B6: std_event_loop_once (tevent_standard.c:112)
> ==11539==    by 0x4C2CF2C: _tevent_loop_once (tevent.c:530)
> ==11539==    by 0x4C2D0CA: tevent_common_loop_wait (tevent.c:634)
> ==11539==    by 0x4C30656: std_event_loop_wait (tevent_standard.c:138)
> ==11539==    by 0x7C42C12: server_loop (server.c:587)
> ==11539==    by 0x10C571: main (ifpsrv.c:397)
> ==11539== 
> ==11539== HEAP SUMMARY:
> ==11539==     in use at exit: 93,205 bytes in 449 blocks
> ==11539==   total heap usage: 3,296 allocs, 2,847 frees, 440,463 bytes allocated
> 

Thanks, I didn't see this earlier because I never used --recurse.

I modified the codegen a bit so than an invoker is called even if there
are no properties. The invoker creates an empty array, adds nothing (the
property getters would be inserted here by codegen) and returns.

The other way I was considering was checking for properties in the
getall_handler in sssd, but I prefer to let the generated code do as
much work as possible.
-------------- next part --------------
>From a9e011634a403a51612075d3a180de0d15c32905 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Wed, 21 May 2014 16:48:45 +0200
Subject: [PATCH 1/5] SBUS: Add utility function sbus_add_variant_to_dict

---
 src/sbus/sssd_dbus.h            |   5 ++
 src/sbus/sssd_dbus_meta.h       |   1 +
 src/sbus/sssd_dbus_properties.c | 116 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 122 insertions(+)

diff --git a/src/sbus/sssd_dbus.h b/src/sbus/sssd_dbus.h
index 4ae64f054cdcf0e4005d99d907b878abb85c7137..9bd5019ecbd393eaef83b95c9e5fec5480b947af 100644
--- a/src/sbus/sssd_dbus.h
+++ b/src/sbus/sssd_dbus.h
@@ -269,6 +269,11 @@ int sbus_request_return_and_finish(struct sbus_request *dbus_req,
                                    int first_arg_type,
                                    ...);
 
+int sbus_add_variant_to_dict(DBusMessageIter *iter_dict,
+                             const char *key,
+                             int type,
+                             const void *value);
+
 int sbus_request_return_as_variant(struct sbus_request *dbus_req,
                                    int type,
                                    const void *value);
diff --git a/src/sbus/sssd_dbus_meta.h b/src/sbus/sssd_dbus_meta.h
index 4e170b7d6ce5fb8f68109e496ab96cfdf889d864..89f11224b9e077e5e9b2ce6b34fc5f93702a2dd4 100644
--- a/src/sbus/sssd_dbus_meta.h
+++ b/src/sbus/sssd_dbus_meta.h
@@ -76,6 +76,7 @@ struct sbus_interface_meta {
     const struct sbus_method_meta *methods;
     const struct sbus_signal_meta *signals;
     const struct sbus_property_meta *properties;
+    sbus_method_invoker_fn invoker_get_all;
 };
 
 const struct sbus_method_meta *
diff --git a/src/sbus/sssd_dbus_properties.c b/src/sbus/sssd_dbus_properties.c
index bdd5b432fe57ca66a4d06f98720578b3a175a65c..07b33297b13782354cbcf812f129443a14c5d319 100644
--- a/src/sbus/sssd_dbus_properties.c
+++ b/src/sbus/sssd_dbus_properties.c
@@ -23,6 +23,74 @@
 #include "sbus/sssd_dbus_meta.h"
 #include "sbus/sssd_dbus_private.h"
 
+static char *
+type_to_string(char type, char *str)
+{
+    int l;
+
+    l = snprintf(str, 2, "%c", type);
+    if (l != 1) {
+        return NULL;
+    }
+
+    return str;
+}
+
+int sbus_add_variant_to_dict(DBusMessageIter *iter_dict,
+                             const char *key,
+                             int type,
+                             const void *value)
+{
+    DBusMessageIter iter_dict_entry;
+    DBusMessageIter iter_dict_val;
+    dbus_bool_t dbret;
+    char strtype[2];
+
+    type_to_string(type, strtype);
+
+    dbret = dbus_message_iter_open_container(iter_dict,
+                                             DBUS_TYPE_DICT_ENTRY, NULL,
+                                             &iter_dict_entry);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    /* Start by appending the key */
+    dbret = dbus_message_iter_append_basic(&iter_dict_entry,
+                                           DBUS_TYPE_STRING, &key);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    dbret = dbus_message_iter_open_container(&iter_dict_entry,
+                                             DBUS_TYPE_VARIANT,
+                                             strtype,
+                                             &iter_dict_val);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    /* Now add the value */
+    dbret = dbus_message_iter_append_basic(&iter_dict_val, type, value);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    dbret = dbus_message_iter_close_container(&iter_dict_entry,
+                                              &iter_dict_val);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    dbret = dbus_message_iter_close_container(iter_dict,
+                                              &iter_dict_entry);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    return EOK;
+}
+
 static int
 dispatch_properties_set(struct sbus_connection *conn,
                         struct sbus_interface *intf,
@@ -176,6 +244,50 @@ dispatch_properties_get(struct sbus_connection *conn,
     return EOK;
 }
 
+static int
+dispatch_properties_get_all(struct sbus_connection *conn,
+                            struct sbus_interface *intf,
+                            DBusMessage *message)
+{
+    struct sbus_request *req;
+    const char *signature;
+    const struct sbus_interface_meta *meta;
+    const char *interface_name;
+    DBusMessageIter iter;
+
+    req = sbus_new_request(conn, intf, message);
+    if (req == NULL) {
+        return ENOMEM;
+    }
+
+    meta = intf->vtable->meta;
+
+    signature = dbus_message_get_signature(message);
+    /* Interface name */
+    if (strcmp(signature, "s") != 0) {
+        return sbus_request_fail_and_finish(req,
+                    sbus_error_new(req,
+                                   DBUS_ERROR_INVALID_ARGS,
+                                   "Invalid argument types passed " \
+                                   "to Set method"));
+    }
+
+    dbus_message_iter_init(message, &iter);
+    dbus_message_iter_get_basic(&iter, &interface_name);
+
+    if (strcmp(interface_name, meta->name) != 0) {
+        return sbus_request_fail_and_finish(req,
+                    sbus_error_new(req,
+                                   DBUS_ERROR_UNKNOWN_INTERFACE,
+                                   "No such interface"));
+    }
+
+    sbus_request_invoke_or_finish(req, NULL,
+                                  intf->instance_data,
+                                  meta->invoker_get_all);
+    return EOK;
+}
+
 int sbus_properties_dispatch(struct sbus_request *dbus_req)
 {
     const char *member;
@@ -191,6 +303,10 @@ int sbus_properties_dispatch(struct sbus_request *dbus_req)
         return dispatch_properties_get(dbus_req->conn,
                                        dbus_req->intf,
                                        dbus_req->message);
+    } else if (strcmp (member, "GetAll") == 0) {
+        return dispatch_properties_get_all(dbus_req->conn,
+                                            dbus_req->intf,
+                                            dbus_req->message);
     }
 
     return ERR_SBUS_NOSUP;
-- 
1.9.0

-------------- next part --------------
>From 34891f73973878166ec6a27ae2775b5829f23bdb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina at redhat.com>
Date: Wed, 21 May 2014 16:41:13 +0200
Subject: [PATCH 2/5] SBUS: Add utility function
 sbus_add_array_as_variant_to_dict

---
 src/sbus/sssd_dbus.h            |  7 ++++
 src/sbus/sssd_dbus_properties.c | 76 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 83 insertions(+)

diff --git a/src/sbus/sssd_dbus.h b/src/sbus/sssd_dbus.h
index 9bd5019ecbd393eaef83b95c9e5fec5480b947af..0b7c7f1051f7a35734f4e39e70eed9e4e768471e 100644
--- a/src/sbus/sssd_dbus.h
+++ b/src/sbus/sssd_dbus.h
@@ -274,6 +274,13 @@ int sbus_add_variant_to_dict(DBusMessageIter *iter_dict,
                              int type,
                              const void *value);
 
+int sbus_add_array_as_variant_to_dict(DBusMessageIter *iter_dict,
+                                      const char *key,
+                                      int type,
+                                      uint8_t *values,
+                                      const int len,
+                                      const unsigned int item_size);
+
 int sbus_request_return_as_variant(struct sbus_request *dbus_req,
                                    int type,
                                    const void *value);
diff --git a/src/sbus/sssd_dbus_properties.c b/src/sbus/sssd_dbus_properties.c
index 07b33297b13782354cbcf812f129443a14c5d319..a85f0d6e2e5ec40c50a960e0266d97326e1096a1 100644
--- a/src/sbus/sssd_dbus_properties.c
+++ b/src/sbus/sssd_dbus_properties.c
@@ -91,6 +91,82 @@ int sbus_add_variant_to_dict(DBusMessageIter *iter_dict,
     return EOK;
 }
 
+int sbus_add_array_as_variant_to_dict(DBusMessageIter *iter_dict,
+                                      const char *key,
+                                      int type,
+                                      uint8_t *values,
+                                      const int len,
+                                      const unsigned int item_size)
+{
+    DBusMessageIter iter_dict_entry;
+    DBusMessageIter iter_variant;
+    DBusMessageIter iter_array;
+    dbus_bool_t dbret;
+    char variant_type[] = {DBUS_TYPE_ARRAY, type, '\0'};
+    char array_type[] = {type, '\0'};
+    void *addr = NULL;
+    int i;
+
+    dbret = dbus_message_iter_open_container(iter_dict,
+                                             DBUS_TYPE_DICT_ENTRY, NULL,
+                                             &iter_dict_entry);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    /* Start by appending the key */
+    dbret = dbus_message_iter_append_basic(&iter_dict_entry,
+                                           DBUS_TYPE_STRING, &key);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    dbret = dbus_message_iter_open_container(&iter_dict_entry,
+                                             DBUS_TYPE_VARIANT,
+                                             variant_type,
+                                             &iter_variant);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    dbret = dbus_message_iter_open_container(&iter_variant,
+                                             DBUS_TYPE_ARRAY,
+                                             array_type,
+                                             &iter_array);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    /* Now add the value */
+    for (i = 0; i < len; i++) {
+        addr = values + i * item_size;
+        dbret = dbus_message_iter_append_basic(&iter_array, type, addr);
+        if (!dbret) {
+            return ENOMEM;
+        }
+    }
+
+    dbret = dbus_message_iter_close_container(&iter_variant,
+                                              &iter_array);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    dbret = dbus_message_iter_close_container(&iter_dict_entry,
+                                              &iter_variant);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    dbret = dbus_message_iter_close_container(iter_dict,
+                                              &iter_dict_entry);
+    if (!dbret) {
+        return ENOMEM;
+    }
+
+    return EOK;
+}
+
 static int
 dispatch_properties_set(struct sbus_connection *conn,
                         struct sbus_interface *intf,
-- 
1.9.0

-------------- next part --------------
>From 7f2ee7a8956130cdbf3473c93c64d40dd2fb96de Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Wed, 21 May 2014 21:24:42 +0200
Subject: [PATCH 3/5] SBUS: Consolidate VTABLE_FUNC definitions in
 sssd_dbus_meta.h

We had several duplicated declarations of the VTABLE_FUNC macro in the
SSSD source code. This patch consolidates on one definition in
sssd_dbus_meta.h that is usable by all consumers, including the upcoming
GetAll method implementation.
---
 src/sbus/sssd_dbus_connection.c | 4 ----
 src/sbus/sssd_dbus_meta.h       | 4 ++++
 src/sbus/sssd_dbus_private.h    | 4 ----
 3 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/src/sbus/sssd_dbus_connection.c b/src/sbus/sssd_dbus_connection.c
index af1c8c56afee7a033e90bc6b2e92c7d8258139a0..06256a85b5e81b39d50923db6d41b64015114ce1 100644
--- a/src/sbus/sssd_dbus_connection.c
+++ b/src/sbus/sssd_dbus_connection.c
@@ -394,10 +394,6 @@ static bool sbus_iface_handles_path(struct sbus_interface_p *intf_p,
     return strcmp(path, intf_p->intf->path) == 0;
 }
 
-/* Looks up a vtable func, in a struct derived from struct sbus_vtable */
-#define VTABLE_FUNC(vtable, offset) \
-    (*((void **)((char *)(vtable) + (offset))))
-
 static void sbus_handler_got_caller_id(struct tevent_req *req);
 
 /* messsage_handler
diff --git a/src/sbus/sssd_dbus_meta.h b/src/sbus/sssd_dbus_meta.h
index 89f11224b9e077e5e9b2ce6b34fc5f93702a2dd4..2cb9e95e3e12da55b1f101e076a0e05203984215 100644
--- a/src/sbus/sssd_dbus_meta.h
+++ b/src/sbus/sssd_dbus_meta.h
@@ -33,6 +33,10 @@
  * http://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format
  */
 
+/* Looks up a vtable func, in a struct derived from struct sbus_vtable */
+#define VTABLE_FUNC(vtable, offset) \
+    (*((void **)((char *)(vtable) + (offset))))
+
 struct sbus_arg_meta {
     const char *name;
     const char *type;
diff --git a/src/sbus/sssd_dbus_private.h b/src/sbus/sssd_dbus_private.h
index fa11bc1c8ef625ba6c6e9382d7ccd146eabdbb26..624448d30526eb4e927f22f133451c9a63c2cebd 100644
--- a/src/sbus/sssd_dbus_private.h
+++ b/src/sbus/sssd_dbus_private.h
@@ -68,10 +68,6 @@ struct sbus_connection {
     struct sbus_watch_ctx *watch_list;
 };
 
-/* Looks up a vtable func, in a struct derived from struct sbus_vtable */
-#define VTABLE_FUNC(vtable, offset) \
-    (*((void **)((char *)(vtable) + (offset))))
-
 /* =Watches=============================================================== */
 
 struct sbus_watch_ctx {
-- 
1.9.0

-------------- next part --------------
>From ab7b0d6bda6652bfcb81464bcb386588ebebc723 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Wed, 21 May 2014 21:29:15 +0200
Subject: [PATCH 4/5] SBUS: Implement org.freedesktop.DBus.Properties.GetAll
 for primitive types

This patch implements the GetAll method of the
org.freedesktop.DBus.Properties interface by iterating over the
available getters and putting all the results into a single getter.

The patch includes a unit test that exercies all currently supported
array types.
---
 src/monitor/monitor_iface_generated.c         |  58 +++-
 src/providers/data_provider_iface_generated.c |  58 +++-
 src/responder/ifp/ifp_iface_generated.c       |  29 +-
 src/sbus/sbus_codegen                         | 100 ++++++-
 src/sbus/sssd_dbus_properties.c               |   2 +-
 src/tests/sbus_codegen_tests.c                | 299 +++++++++++++++++++
 src/tests/sbus_codegen_tests_generated.c      | 415 +++++++++++++++++++++++++-
 7 files changed, 944 insertions(+), 17 deletions(-)

diff --git a/src/monitor/monitor_iface_generated.c b/src/monitor/monitor_iface_generated.c
index e9c3c1d52468ac6969498e79491a1d62dc75cc71..ee59242c1bc3b7b30fb5e086a142aedd6be71319 100644
--- a/src/monitor/monitor_iface_generated.c
+++ b/src/monitor/monitor_iface_generated.c
@@ -24,12 +24,39 @@ const struct sbus_method_meta mon_srv_iface__methods[] = {
     { NULL, }
 };
 
+/* invokes GetAll for the 'org.freedesktop.sssd.monitor' interface */
+static int invoke_mon_srv_iface_get_all(struct sbus_request *dbus_req, void *function_ptr)
+{
+    DBusMessage *reply;
+    dbus_bool_t dbret;
+    DBusMessageIter iter;
+    DBusMessageIter iter_dict;
+
+    reply = dbus_message_new_method_return(dbus_req->message);
+    if (!reply) return ENOMEM;
+    dbus_message_iter_init_append(reply, &iter);
+    dbret = dbus_message_iter_open_container(
+                                     &iter, DBUS_TYPE_ARRAY,
+                                     DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+                                     DBUS_TYPE_STRING_AS_STRING
+                                     DBUS_TYPE_VARIANT_AS_STRING
+                                     DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+                                     &iter_dict);
+    if (!dbret) return ENOMEM;
+
+    dbret = dbus_message_iter_close_container(&iter, &iter_dict);
+    if (!dbret) return ENOMEM;
+
+    return sbus_request_finish(dbus_req, reply);
+}
+
 /* interface info for org.freedesktop.sssd.monitor */
 const struct sbus_interface_meta mon_srv_iface_meta = {
     "org.freedesktop.sssd.monitor", /* name */
     mon_srv_iface__methods,
     NULL, /* no signals */
-    NULL, /* no propetries */
+    NULL, /* no properties */
+    invoke_mon_srv_iface_get_all, /* GetAll invoker */
 };
 
 /* methods for org.freedesktop.sssd.service */
@@ -93,10 +120,37 @@ const struct sbus_method_meta mon_cli_iface__methods[] = {
     { NULL, }
 };
 
+/* invokes GetAll for the 'org.freedesktop.sssd.service' interface */
+static int invoke_mon_cli_iface_get_all(struct sbus_request *dbus_req, void *function_ptr)
+{
+    DBusMessage *reply;
+    dbus_bool_t dbret;
+    DBusMessageIter iter;
+    DBusMessageIter iter_dict;
+
+    reply = dbus_message_new_method_return(dbus_req->message);
+    if (!reply) return ENOMEM;
+    dbus_message_iter_init_append(reply, &iter);
+    dbret = dbus_message_iter_open_container(
+                                     &iter, DBUS_TYPE_ARRAY,
+                                     DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+                                     DBUS_TYPE_STRING_AS_STRING
+                                     DBUS_TYPE_VARIANT_AS_STRING
+                                     DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+                                     &iter_dict);
+    if (!dbret) return ENOMEM;
+
+    dbret = dbus_message_iter_close_container(&iter, &iter_dict);
+    if (!dbret) return ENOMEM;
+
+    return sbus_request_finish(dbus_req, reply);
+}
+
 /* interface info for org.freedesktop.sssd.service */
 const struct sbus_interface_meta mon_cli_iface_meta = {
     "org.freedesktop.sssd.service", /* name */
     mon_cli_iface__methods,
     NULL, /* no signals */
-    NULL, /* no propetries */
+    NULL, /* no properties */
+    invoke_mon_cli_iface_get_all, /* GetAll invoker */
 };
diff --git a/src/providers/data_provider_iface_generated.c b/src/providers/data_provider_iface_generated.c
index e7eca7def576772a695457444de7aaf99795fb65..58813762570c12b17c26f8116ced347de540b263 100644
--- a/src/providers/data_provider_iface_generated.c
+++ b/src/providers/data_provider_iface_generated.c
@@ -59,12 +59,39 @@ const struct sbus_method_meta data_provider_iface__methods[] = {
     { NULL, }
 };
 
+/* invokes GetAll for the 'org.freedesktop.sssd.dataprovider' interface */
+static int invoke_data_provider_iface_get_all(struct sbus_request *dbus_req, void *function_ptr)
+{
+    DBusMessage *reply;
+    dbus_bool_t dbret;
+    DBusMessageIter iter;
+    DBusMessageIter iter_dict;
+
+    reply = dbus_message_new_method_return(dbus_req->message);
+    if (!reply) return ENOMEM;
+    dbus_message_iter_init_append(reply, &iter);
+    dbret = dbus_message_iter_open_container(
+                                     &iter, DBUS_TYPE_ARRAY,
+                                     DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+                                     DBUS_TYPE_STRING_AS_STRING
+                                     DBUS_TYPE_VARIANT_AS_STRING
+                                     DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+                                     &iter_dict);
+    if (!dbret) return ENOMEM;
+
+    dbret = dbus_message_iter_close_container(&iter, &iter_dict);
+    if (!dbret) return ENOMEM;
+
+    return sbus_request_finish(dbus_req, reply);
+}
+
 /* interface info for org.freedesktop.sssd.dataprovider */
 const struct sbus_interface_meta data_provider_iface_meta = {
     "org.freedesktop.sssd.dataprovider", /* name */
     data_provider_iface__methods,
     NULL, /* no signals */
-    NULL, /* no propetries */
+    NULL, /* no properties */
+    invoke_data_provider_iface_get_all, /* GetAll invoker */
 };
 
 /* methods for org.freedesktop.sssd.dataprovider_rev */
@@ -86,10 +113,37 @@ const struct sbus_method_meta data_provider_rev_iface__methods[] = {
     { NULL, }
 };
 
+/* invokes GetAll for the 'org.freedesktop.sssd.dataprovider_rev' interface */
+static int invoke_data_provider_rev_iface_get_all(struct sbus_request *dbus_req, void *function_ptr)
+{
+    DBusMessage *reply;
+    dbus_bool_t dbret;
+    DBusMessageIter iter;
+    DBusMessageIter iter_dict;
+
+    reply = dbus_message_new_method_return(dbus_req->message);
+    if (!reply) return ENOMEM;
+    dbus_message_iter_init_append(reply, &iter);
+    dbret = dbus_message_iter_open_container(
+                                     &iter, DBUS_TYPE_ARRAY,
+                                     DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+                                     DBUS_TYPE_STRING_AS_STRING
+                                     DBUS_TYPE_VARIANT_AS_STRING
+                                     DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+                                     &iter_dict);
+    if (!dbret) return ENOMEM;
+
+    dbret = dbus_message_iter_close_container(&iter, &iter_dict);
+    if (!dbret) return ENOMEM;
+
+    return sbus_request_finish(dbus_req, reply);
+}
+
 /* interface info for org.freedesktop.sssd.dataprovider_rev */
 const struct sbus_interface_meta data_provider_rev_iface_meta = {
     "org.freedesktop.sssd.dataprovider_rev", /* name */
     data_provider_rev_iface__methods,
     NULL, /* no signals */
-    NULL, /* no propetries */
+    NULL, /* no properties */
+    invoke_data_provider_rev_iface_get_all, /* GetAll invoker */
 };
diff --git a/src/responder/ifp/ifp_iface_generated.c b/src/responder/ifp/ifp_iface_generated.c
index d3cb4990cf13fd51621b7606371cdf3175bc789a..91efda251491216fee41663d88fd67b687d3a2cd 100644
--- a/src/responder/ifp/ifp_iface_generated.c
+++ b/src/responder/ifp/ifp_iface_generated.c
@@ -66,12 +66,39 @@ const struct sbus_method_meta infopipe_iface__methods[] = {
     { NULL, }
 };
 
+/* invokes GetAll for the 'org.freedesktop.sssd.infopipe' interface */
+static int invoke_infopipe_iface_get_all(struct sbus_request *dbus_req, void *function_ptr)
+{
+    DBusMessage *reply;
+    dbus_bool_t dbret;
+    DBusMessageIter iter;
+    DBusMessageIter iter_dict;
+
+    reply = dbus_message_new_method_return(dbus_req->message);
+    if (!reply) return ENOMEM;
+    dbus_message_iter_init_append(reply, &iter);
+    dbret = dbus_message_iter_open_container(
+                                     &iter, DBUS_TYPE_ARRAY,
+                                     DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+                                     DBUS_TYPE_STRING_AS_STRING
+                                     DBUS_TYPE_VARIANT_AS_STRING
+                                     DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+                                     &iter_dict);
+    if (!dbret) return ENOMEM;
+
+    dbret = dbus_message_iter_close_container(&iter, &iter_dict);
+    if (!dbret) return ENOMEM;
+
+    return sbus_request_finish(dbus_req, reply);
+}
+
 /* interface info for org.freedesktop.sssd.infopipe */
 const struct sbus_interface_meta infopipe_iface_meta = {
     "org.freedesktop.sssd.infopipe", /* name */
     infopipe_iface__methods,
     NULL, /* no signals */
-    NULL, /* no propetries */
+    NULL, /* no properties */
+    invoke_infopipe_iface_get_all, /* GetAll invoker */
 };
 
 /* invokes a handler with a 's' DBus signature */
diff --git a/src/sbus/sbus_codegen b/src/sbus/sbus_codegen
index 6507753f2797b354da8aaa2503b7d9bd701668c8..15a6cadacc62e6809a9c807d30a48d6689ec0fd5 100755
--- a/src/sbus/sbus_codegen
+++ b/src/sbus/sbus_codegen
@@ -291,6 +291,21 @@ def source_method_invoker(signature, args):
     out(");")
     out("}")
 
+def source_prop_types(prop, type_prefix=False):
+    prefix = "%s_" % prop.type if type_prefix else ""
+    if prop.is_array:
+        out("    %s *%sprop_val;", prop.sssd_type, prefix)
+        out("    int %sprop_len;", prefix)
+        out("    %s *%sout_val;", prop.dbus_type, prefix)
+    else:
+        out("    %s %sprop_val;", prop.sssd_type, prefix)
+        out("    %s %sout_val;", prop.dbus_type, prefix)
+
+def source_prop_handler(prop, type_prefix=False):
+    prefix = "%s_" % prop.type if type_prefix else ""
+    out("    %s", prop.getter_signature("%shandler" % prefix), new_line=False)
+    out(";")
+
 def source_getter_invoker(prop):
     out("")
     if prop.is_array:
@@ -300,13 +315,9 @@ def source_getter_invoker(prop):
     out("static int %s(struct sbus_request *dbus_req, void *function_ptr)",
         prop.getter_invoker_name())
     out("{")
-    if prop.is_array:
-        out("    %s *prop_val;", prop.sssd_type)
-        out("    int prop_len;")
-        out("    %s *out_val;", prop.dbus_type)
-    else:
-        out("    %s prop_val;", prop.sssd_type)
-        out("    %s out_val;", prop.dbus_type)
+
+    source_prop_types(prop)
+
     out("")
     out("    %s", prop.getter_signature("handler"), new_line=False)
     out(" = function_ptr;")
@@ -330,6 +341,73 @@ def source_getter_invoker(prop):
         out("    return sbus_request_return_as_variant(dbus_req, %s, &out_val);", prop.dbus_constant)
     out("}")
 
+def source_getall_invoker(iface, prop_invokers):
+    out("")
+    out("/* invokes GetAll for the '%s' interface */", iface.name)
+    out("static int invoke_%s_get_all(struct sbus_request *dbus_req, void *function_ptr)",
+        iface.c_name())
+    out("{")
+    out("    DBusMessage *reply;")
+    out("    dbus_bool_t dbret;")
+    out("    DBusMessageIter iter;")
+    out("    DBusMessageIter iter_dict;")
+    if iface.properties:
+        out("    int ret;")
+        out("    struct sbus_interface *intf = dbus_req->intf;")
+        out("    const struct sbus_property_meta *property;")
+
+    iface_types = [ p.type for p in iface.properties ]
+    for prop in [ p for p in prop_invokers.values() if p.type in iface_types ]:
+        source_prop_types(prop, type_prefix=True)
+        source_prop_handler(prop, type_prefix=True)
+    out("")
+
+    out("    reply = dbus_message_new_method_return(dbus_req->message);")
+    out("    if (!reply) return ENOMEM;")
+    out("    dbus_message_iter_init_append(reply, &iter);")
+    out("    dbret = dbus_message_iter_open_container(")
+    out("                                     &iter, DBUS_TYPE_ARRAY,")
+    out("                                     DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING")
+    out("                                     DBUS_TYPE_STRING_AS_STRING")
+    out("                                     DBUS_TYPE_VARIANT_AS_STRING")
+    out("                                     DBUS_DICT_ENTRY_END_CHAR_AS_STRING,")
+    out("                                     &iter_dict);")
+    out("    if (!dbret) return ENOMEM;")
+    out("")
+
+    for prop in iface.properties:
+        out("    property = sbus_meta_find_property(intf->vtable->meta, \"%s\");", prop.c_name())
+        out("    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {")
+        out("        %s_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);", prop.type)
+        out("        if (%s_handler) {", prop.type)
+        out("            (%s_handler)(dbus_req, dbus_req->intf->instance_data, &%s_prop_val", prop.type, prop.type, new_line=False)
+        if prop.is_array:
+            out(", &%s_prop_len", prop.type, new_line=False)
+        out(");")
+        if prop.type == "s":
+            out("            %s_out_val = %s_prop_val == NULL ? \"\" : %s_prop_val;",
+                prop.type, prop.type, prop.type)
+        elif prop.type == "o":
+            out("            %s_out_val = %s_prop_val == NULL ? \"/\" : %s_prop_val;",
+                prop.type, prop.type, prop.type)
+        else:
+            out("            %s_out_val = %s_prop_val;", prop.type, prop.type)
+        if prop.is_array:
+            out("            ret = sbus_add_array_as_variant_to_dict(&iter_dict, \"%s\", %s, (uint8_t*)%s_out_val, %s_prop_len, sizeof(%s));", prop.c_name(), prop.dbus_constant, prop.type, prop.type, prop.sssd_type)
+        else:
+            out("            ret = sbus_add_variant_to_dict(&iter_dict, \"%s\", %s, &%s_out_val);", prop.c_name(), prop.dbus_constant, prop.type)
+        out("            if (ret != EOK) return ret;")
+        out("        }")
+        out("    }")
+        out("")
+
+    out("    dbret = dbus_message_iter_close_container(&iter, &iter_dict);")
+    out("    if (!dbret) return ENOMEM;")
+    out("")
+
+    out("    return sbus_request_finish(dbus_req, reply);")
+    out("}")
+
 def forward_method_invokers(ifaces):
     invokers = { }
     for iface in ifaces:
@@ -509,9 +587,10 @@ def source_interface(iface):
     else:
         out("    NULL, /* no signals */")
     if iface.properties:
-        out("    %s__properties", iface.c_name())
+        out("    %s__properties,", iface.c_name())
     else:
-        out("    NULL, /* no propetries */")
+        out("    NULL, /* no properties */")
+    out("    invoke_%s_get_all, /* GetAll invoker */", iface.c_name())
     out("};")
 
 def generate_source(ifaces, filename, include_header=None):
@@ -543,6 +622,9 @@ def generate_source(ifaces, filename, include_header=None):
         if iface.properties:
             source_properties(iface, iface.properties)
 
+        # always generate getall, for interfaces without properties
+        # let's return an empty array
+        source_getall_invoker(iface, prop_invokers)
         # The sbus_interface structure
         source_interface(iface)
 
diff --git a/src/sbus/sssd_dbus_properties.c b/src/sbus/sssd_dbus_properties.c
index a85f0d6e2e5ec40c50a960e0266d97326e1096a1..703f6eb81d8d788b7e9e46d68265b4e6136c0089 100644
--- a/src/sbus/sssd_dbus_properties.c
+++ b/src/sbus/sssd_dbus_properties.c
@@ -345,7 +345,7 @@ dispatch_properties_get_all(struct sbus_connection *conn,
                     sbus_error_new(req,
                                    DBUS_ERROR_INVALID_ARGS,
                                    "Invalid argument types passed " \
-                                   "to Set method"));
+                                   "to GetAll method"));
     }
 
     dbus_message_iter_init(message, &iter);
diff --git a/src/tests/sbus_codegen_tests.c b/src/tests/sbus_codegen_tests.c
index c7da414fe30f46d9d317f3a4205ab38c4e905081..561a6a24809013437c6c5ea178359dc1248589b0 100644
--- a/src/tests/sbus_codegen_tests.c
+++ b/src/tests/sbus_codegen_tests.c
@@ -1033,12 +1033,311 @@ START_TEST(test_get_basic_array_types)
 }
 END_TEST
 
+struct prop_test {
+    const char *name;
+    bool handled;
+    int length;
+    int type;
+    union prop_value {
+        bool bool_val;
+        const char *string_val;
+        const char *path_val;
+        uint8_t byte_val;
+        int16_t int16_val;
+        uint16_t uint16_val;
+        int32_t int32_val;
+        uint32_t uint32_val;
+        int64_t int64_val;
+        uint64_t uint64_val;
+        double double_val;
+
+        const char **string_arr_val;
+        const char **path_arr_val;
+        uint8_t *byte_arr_val;
+        int16_t *int16_arr_val;
+        uint16_t *uint16_arr_val;
+        int32_t *int32_arr_val;
+        uint32_t *uint32_arr_val;
+        int64_t *int64_arr_val;
+        uint64_t *uint64_arr_val;
+        double *double_arr_val;
+    } value;
+};
+
+void check_prop(DBusMessageIter *variter, struct prop_test *p)
+{
+    dbus_bool_t bool_val;
+    const char *string_val;
+    const char *path_val;
+    uint8_t byte_val;
+    int16_t int16_val;
+    uint16_t uint16_val;
+    int32_t int32_val;
+    uint32_t uint32_val;
+    int64_t int64_val;
+    uint64_t uint64_val;
+    double double_val;
+    int type;
+
+    type = dbus_message_iter_get_arg_type(variter);
+
+    /* No property should be returned twice */
+    ck_assert(p->handled == false);
+    ck_assert(p->type == type);
+    switch (p->type) {
+        case DBUS_TYPE_BOOLEAN:
+            dbus_message_iter_get_basic(variter, &bool_val);
+            ck_assert(bool_val == p->value.bool_val);
+            break;
+        case DBUS_TYPE_STRING:
+            dbus_message_iter_get_basic(variter, &string_val);
+            ck_assert_str_eq(string_val, p->value.string_val);
+            break;
+        case DBUS_TYPE_BYTE:
+            dbus_message_iter_get_basic(variter, &byte_val);
+            ck_assert_int_eq(byte_val, p->value.byte_val);
+            break;
+        case DBUS_TYPE_INT16:
+            dbus_message_iter_get_basic(variter, &int16_val);
+            ck_assert_int_eq(int16_val, p->value.int16_val);
+            break;
+        case DBUS_TYPE_UINT16:
+            dbus_message_iter_get_basic(variter, &uint16_val);
+            ck_assert_int_eq(uint16_val, p->value.uint16_val);
+            break;
+        case DBUS_TYPE_INT32:
+            dbus_message_iter_get_basic(variter, &int32_val);
+            ck_assert_int_eq(int32_val, p->value.int32_val);
+            break;
+        case DBUS_TYPE_UINT32:
+            dbus_message_iter_get_basic(variter, &uint32_val);
+            ck_assert_int_eq(uint32_val, p->value.uint32_val);
+            break;
+        case DBUS_TYPE_INT64:
+            dbus_message_iter_get_basic(variter, &int64_val);
+            ck_assert_int_eq(int64_val, p->value.int64_val);
+            break;
+        case DBUS_TYPE_UINT64:
+            dbus_message_iter_get_basic(variter, &uint64_val);
+            ck_assert_int_eq(uint64_val, p->value.uint64_val);
+            break;
+        case DBUS_TYPE_DOUBLE:
+            dbus_message_iter_get_basic(variter, &double_val);
+            ck_assert_int_eq(double_val, p->value.double_val);
+            break;
+        case DBUS_TYPE_OBJECT_PATH:
+            dbus_message_iter_get_basic(variter, &path_val);
+            ck_assert_str_eq(path_val, p->value.path_val);
+            break;
+        default:
+            /* Not handled */
+            return;
+    }
+
+    /* This attribute was handled, get the next one */
+    p->handled = true;
+}
+
+void check_arr_prop(DBusMessageIter *variter, struct prop_test *p)
+{
+    DBusMessageIter arriter;
+    const char **strings;
+    uint8_t *byte_arr_val;
+    int16_t *int16_arr_val;
+    uint16_t *uint16_arr_val;
+    int32_t *int32_arr_val;
+    uint32_t *uint32_arr_val;
+    int64_t *int64_arr_val;
+    uint64_t *uint64_arr_val;
+    double *double_arr_val;
+    int len;
+    int type;
+
+    ck_assert_int_eq(dbus_message_iter_get_arg_type(variter), DBUS_TYPE_ARRAY);
+    type = dbus_message_iter_get_element_type(variter);
+    ck_assert_int_eq(type, p->type);
+
+    dbus_message_iter_recurse(variter, &arriter);
+    if (type == DBUS_TYPE_STRING || type == DBUS_TYPE_OBJECT_PATH) {
+        int n = 0, i = 0;;
+        const char *s;
+
+        do {
+            n++;
+        } while (dbus_message_iter_next(&arriter));
+
+        /* Allocating on NULL is bad, but this is unit test */
+        strings = talloc_array(NULL, const char *, n);
+        ck_assert(strings != NULL);
+
+        dbus_message_iter_recurse(variter, &arriter);
+        do {
+            dbus_message_iter_get_basic(&arriter, &s);
+            strings[i] = talloc_strdup(strings, s);
+            ck_assert(strings[i] != NULL);
+            i++;
+        } while (dbus_message_iter_next(&arriter));
+
+        len = n;
+    }
+
+    switch (p->type) {
+        case DBUS_TYPE_STRING:
+            ck_assert_int_eq(len, 2);
+            ck_assert_str_eq(strings[0], pilot_string_array[0]);
+            ck_assert_str_eq(strings[1], pilot_string_array[1]);
+            break;
+        case DBUS_TYPE_BYTE:
+            dbus_message_iter_get_fixed_array(&arriter, &byte_arr_val, &len);
+            check_uint_array(byte_arr_val, len, p->value.byte_arr_val);
+            break;
+        case DBUS_TYPE_INT16:
+            dbus_message_iter_get_fixed_array(&arriter, &int16_arr_val, &len);
+            check_int_array(int16_arr_val, len, p->value.int16_arr_val);
+            break;
+        case DBUS_TYPE_UINT16:
+            dbus_message_iter_get_fixed_array(&arriter, &uint16_arr_val, &len);
+            check_uint_array(uint16_arr_val, len, p->value.uint16_arr_val);
+            break;
+        case DBUS_TYPE_INT32:
+            dbus_message_iter_get_fixed_array(&arriter, &int32_arr_val, &len);
+            check_int_array(int32_arr_val, len, p->value.int32_arr_val);
+            break;
+        case DBUS_TYPE_UINT32:
+            dbus_message_iter_get_fixed_array(&arriter, &uint32_arr_val, &len);
+            check_uint_array(uint32_arr_val, len, p->value.uint32_arr_val);
+            break;
+        case DBUS_TYPE_INT64:
+            dbus_message_iter_get_fixed_array(&arriter, &int64_arr_val, &len);
+            check_int_array(int64_arr_val, len, p->value.int64_arr_val);
+            break;
+        case DBUS_TYPE_UINT64:
+            dbus_message_iter_get_fixed_array(&arriter, &uint64_arr_val, &len);
+            check_uint_array(uint64_arr_val, len, p->value.uint64_arr_val);
+            break;
+        case DBUS_TYPE_DOUBLE:
+            dbus_message_iter_get_fixed_array(&arriter, &double_arr_val, &len);
+            check_int_array(double_arr_val, len, p->value.double_arr_val);
+            break;
+        case DBUS_TYPE_OBJECT_PATH:
+            ck_assert_int_eq(len, 2);
+            ck_assert_str_eq(strings[0], pilot_path_array[0]);
+            ck_assert_str_eq(strings[1], pilot_path_array[1]);
+            break;
+        default:
+            /* Not handled */
+            return;
+    }
+
+
+    p->handled = true;
+}
+
+START_TEST(test_getall_basic_types)
+{
+    DBusMessage *reply;
+    DBusMessageIter iter;
+    DBusMessageIter arriter;
+    DBusMessageIter dictiter;
+    DBusMessageIter variter;
+    dbus_bool_t dbret;
+    DBusError error = DBUS_ERROR_INIT;
+    TALLOC_CTX *ctx;
+    DBusConnection *client;
+    char *attr_name;
+    int i;
+    int num_prop;
+
+    struct prop_test pilot_properties[] = {
+      { "boolean", false, 0, DBUS_TYPE_BOOLEAN, { .bool_val = pilot_bool } },
+      { "FullName", false, 0, DBUS_TYPE_STRING, { .string_val = pilot_full_name } },
+      { "byte", false, 0, DBUS_TYPE_BYTE, { .byte_val = pilot_byte } },
+      { "int16", false, 0, DBUS_TYPE_INT16, { .int16_val = pilot_int16 } },
+      { "uint16", false, 0, DBUS_TYPE_UINT16, { .uint16_val = pilot_uint16 } },
+      { "int32", false, 0, DBUS_TYPE_INT32, { .int32_val = pilot_int32 } },
+      { "uint32", false, 0, DBUS_TYPE_UINT32, { .uint32_val = pilot_uint32 } },
+      { "int64", false, 0, DBUS_TYPE_INT64, { .int64_val = pilot_int64 } },
+      { "uint64", false, 0, DBUS_TYPE_UINT64, { .uint64_val = pilot_uint64 } },
+      { "double", false, 0, DBUS_TYPE_DOUBLE, { .double_val = pilot_double } },
+      { "string", false, 0, DBUS_TYPE_STRING, { .string_val = pilot_string } },
+      { "object_path", false, 0, DBUS_TYPE_OBJECT_PATH, { .path_val = pilot_path } },
+      { "null_string", false, 0, DBUS_TYPE_STRING, { .string_val = "" } },
+      { "null_path", false, 0, DBUS_TYPE_OBJECT_PATH, { .path_val = "/" } },
+
+      { "byte_array", false, N_ELEMENTS(pilot_byte_array), DBUS_TYPE_BYTE, { .byte_arr_val = pilot_byte_array } },
+      { "int16_array", false, N_ELEMENTS(pilot_int16_array), DBUS_TYPE_INT16, { .int16_arr_val = pilot_int16_array } },
+      { "uint16_array", false, N_ELEMENTS(pilot_uint16_array), DBUS_TYPE_UINT16, { .uint16_arr_val = pilot_uint16_array } },
+      { "int32_array", false, N_ELEMENTS(pilot_int32_array), DBUS_TYPE_INT32, { .int32_arr_val = pilot_int32_array } },
+      { "uint32_array", false, N_ELEMENTS(pilot_uint32_array), DBUS_TYPE_UINT32, { .uint32_arr_val = pilot_uint32_array } },
+      { "int64_array", false, N_ELEMENTS(pilot_int64_array), DBUS_TYPE_INT64, { .int64_arr_val = pilot_int64_array } },
+      { "uint64_array", false, N_ELEMENTS(pilot_uint64_array), DBUS_TYPE_UINT64, { .uint64_arr_val = pilot_uint64_array } },
+      { "double_array", false, N_ELEMENTS(pilot_double_array), DBUS_TYPE_DOUBLE, { .double_arr_val = pilot_double_array } },
+      { "string_array", false, N_ELEMENTS(pilot_string_array), DBUS_TYPE_STRING, { .string_arr_val = pilot_string_array } },
+      { "object_path_array", false, N_ELEMENTS(pilot_path_array), DBUS_TYPE_OBJECT_PATH, { .path_arr_val = pilot_path_array } },
+
+      { NULL, false, 0, 0, { .bool_val = false } }};
+
+    ctx = talloc_new(NULL);
+    client = test_dbus_setup_mock(ctx, NULL, pilot_test_server_init, NULL);
+
+    reply = test_dbus_call_sync(client,
+                                "/test/leela",
+                                DBUS_PROPERTIES_INTERFACE,
+                                "GetAll",
+                                &error,
+                                DBUS_TYPE_STRING,
+                                &test_pilot_meta.name,
+                                DBUS_TYPE_INVALID);
+    ck_assert(reply != NULL);
+
+    /* GetAll reply is an array of dictionaries */
+    dbret = dbus_message_iter_init(reply, &iter);
+    ck_assert(dbret == TRUE);
+    ck_assert_int_eq(dbus_message_iter_get_arg_type(&iter), DBUS_TYPE_ARRAY);
+
+    dbus_message_iter_recurse(&iter, &arriter);
+    num_prop = 0;
+    do {
+        ck_assert_int_eq(dbus_message_iter_get_arg_type(&arriter),
+                         DBUS_TYPE_DICT_ENTRY);
+        dbus_message_iter_recurse(&arriter, &dictiter);
+        dbus_message_iter_get_basic(&dictiter, &attr_name);
+        ck_assert(dbus_message_iter_next(&dictiter) == TRUE);
+        ck_assert_int_eq(dbus_message_iter_get_arg_type(&dictiter),
+                         DBUS_TYPE_VARIANT);
+
+        dbus_message_iter_recurse(&dictiter, &variter);
+
+        for (i=0; pilot_properties[i].name; i++) {
+            if (strcmp(attr_name, pilot_properties[i].name) == 0) {
+                if (dbus_message_iter_get_arg_type(&variter) == DBUS_TYPE_ARRAY) {
+                    check_arr_prop(&variter, &pilot_properties[i]);
+                } else {
+                    check_prop(&variter, &pilot_properties[i]);
+                }
+                break;
+            }
+        }
+
+        num_prop++;
+    } while(dbus_message_iter_next(&arriter));
+
+    /* All known properties must be handled now */
+    for (i=0; pilot_properties[i].name; i++) {
+        ck_assert(pilot_properties[i].handled == true);
+    }
+    /* Also all properties returned from the bus must be accounted for */
+    ck_assert_uint_eq(num_prop, N_ELEMENTS(pilot_properties)-1);
+}
+END_TEST
+
 TCase *create_handler_tests(void)
 {
     TCase *tc = tcase_create("handler");
 
     tcase_add_test(tc, test_marshal_basic_types);
     tcase_add_test(tc, test_get_basic_types);
+    tcase_add_test(tc, test_getall_basic_types);
     tcase_add_test(tc, test_get_basic_array_types);
 
     return tc;
diff --git a/src/tests/sbus_codegen_tests_generated.c b/src/tests/sbus_codegen_tests_generated.c
index 70302daff7c7a7f5b042428be7d994fa0cdd660a..502d6ce8a0436d5651e27e0ae6e8b87daa8715e3 100644
--- a/src/tests/sbus_codegen_tests_generated.c
+++ b/src/tests/sbus_codegen_tests_generated.c
@@ -125,12 +125,56 @@ const struct sbus_property_meta com_planetexpress_Ship__properties[] = {
     { NULL, }
 };
 
+/* invokes GetAll for the 'com.planetexpress.Ship' interface */
+static int invoke_com_planetexpress_Ship_get_all(struct sbus_request *dbus_req, void *function_ptr)
+{
+    DBusMessage *reply;
+    dbus_bool_t dbret;
+    DBusMessageIter iter;
+    DBusMessageIter iter_dict;
+    int ret;
+    struct sbus_interface *intf = dbus_req->intf;
+    const struct sbus_property_meta *property;
+    const char * s_prop_val;
+    const char * s_out_val;
+    void (*s_handler)(struct sbus_request *, void *data, const char * *);
+
+    reply = dbus_message_new_method_return(dbus_req->message);
+    if (!reply) return ENOMEM;
+    dbus_message_iter_init_append(reply, &iter);
+    dbret = dbus_message_iter_open_container(
+                                     &iter, DBUS_TYPE_ARRAY,
+                                     DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+                                     DBUS_TYPE_STRING_AS_STRING
+                                     DBUS_TYPE_VARIANT_AS_STRING
+                                     DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+                                     &iter_dict);
+    if (!dbret) return ENOMEM;
+
+    property = sbus_meta_find_property(intf->vtable->meta, "Color");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        s_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (s_handler) {
+            (s_handler)(dbus_req, dbus_req->intf->instance_data, &s_prop_val);
+            s_out_val = s_prop_val == NULL ? "" : s_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "Color", DBUS_TYPE_STRING, &s_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    dbret = dbus_message_iter_close_container(&iter, &iter_dict);
+    if (!dbret) return ENOMEM;
+
+    return sbus_request_finish(dbus_req, reply);
+}
+
 /* interface info for com.planetexpress.Ship */
 const struct sbus_interface_meta com_planetexpress_Ship_meta = {
     "com.planetexpress.Ship", /* name */
     com_planetexpress_Ship__methods,
     com_planetexpress_Ship__signals,
-    com_planetexpress_Ship__properties
+    com_planetexpress_Ship__properties,
+    invoke_com_planetexpress_Ship_get_all, /* GetAll invoker */
 };
 
 /* arguments for com.planetexpress.Pilot.Blink */
@@ -473,12 +517,379 @@ const struct sbus_property_meta test_pilot__properties[] = {
     { NULL, }
 };
 
+/* invokes GetAll for the 'com.planetexpress.Pilot' interface */
+static int invoke_test_pilot_get_all(struct sbus_request *dbus_req, void *function_ptr)
+{
+    DBusMessage *reply;
+    dbus_bool_t dbret;
+    DBusMessageIter iter;
+    DBusMessageIter iter_dict;
+    int ret;
+    struct sbus_interface *intf = dbus_req->intf;
+    const struct sbus_property_meta *property;
+    uint16_t *aq_prop_val;
+    int aq_prop_len;
+    uint16_t *aq_out_val;
+    void (*aq_handler)(struct sbus_request *, void *data, uint16_t * *, int *);
+    bool b_prop_val;
+    dbus_bool_t b_out_val;
+    void (*b_handler)(struct sbus_request *, void *data, bool *);
+    double d_prop_val;
+    double d_out_val;
+    void (*d_handler)(struct sbus_request *, void *data, double *);
+    const char * *ao_prop_val;
+    int ao_prop_len;
+    const char * *ao_out_val;
+    void (*ao_handler)(struct sbus_request *, void *data, const char * * *, int *);
+    int32_t i_prop_val;
+    int32_t i_out_val;
+    void (*i_handler)(struct sbus_request *, void *data, int32_t *);
+    const char * *as_prop_val;
+    int as_prop_len;
+    const char * *as_out_val;
+    void (*as_handler)(struct sbus_request *, void *data, const char * * *, int *);
+    const char * o_prop_val;
+    const char * o_out_val;
+    void (*o_handler)(struct sbus_request *, void *data, const char * *);
+    int16_t n_prop_val;
+    int16_t n_out_val;
+    void (*n_handler)(struct sbus_request *, void *data, int16_t *);
+    uint16_t q_prop_val;
+    uint16_t q_out_val;
+    void (*q_handler)(struct sbus_request *, void *data, uint16_t *);
+    uint8_t *ay_prop_val;
+    int ay_prop_len;
+    uint8_t *ay_out_val;
+    void (*ay_handler)(struct sbus_request *, void *data, uint8_t * *, int *);
+    const char * s_prop_val;
+    const char * s_out_val;
+    void (*s_handler)(struct sbus_request *, void *data, const char * *);
+    uint32_t u_prop_val;
+    uint32_t u_out_val;
+    void (*u_handler)(struct sbus_request *, void *data, uint32_t *);
+    uint64_t t_prop_val;
+    uint64_t t_out_val;
+    void (*t_handler)(struct sbus_request *, void *data, uint64_t *);
+    int64_t *ax_prop_val;
+    int ax_prop_len;
+    int64_t *ax_out_val;
+    void (*ax_handler)(struct sbus_request *, void *data, int64_t * *, int *);
+    uint8_t y_prop_val;
+    uint8_t y_out_val;
+    void (*y_handler)(struct sbus_request *, void *data, uint8_t *);
+    int64_t x_prop_val;
+    int64_t x_out_val;
+    void (*x_handler)(struct sbus_request *, void *data, int64_t *);
+    uint32_t *au_prop_val;
+    int au_prop_len;
+    uint32_t *au_out_val;
+    void (*au_handler)(struct sbus_request *, void *data, uint32_t * *, int *);
+    int16_t *an_prop_val;
+    int an_prop_len;
+    int16_t *an_out_val;
+    void (*an_handler)(struct sbus_request *, void *data, int16_t * *, int *);
+    double *ad_prop_val;
+    int ad_prop_len;
+    double *ad_out_val;
+    void (*ad_handler)(struct sbus_request *, void *data, double * *, int *);
+    int32_t *ai_prop_val;
+    int ai_prop_len;
+    int32_t *ai_out_val;
+    void (*ai_handler)(struct sbus_request *, void *data, int32_t * *, int *);
+    uint64_t *at_prop_val;
+    int at_prop_len;
+    uint64_t *at_out_val;
+    void (*at_handler)(struct sbus_request *, void *data, uint64_t * *, int *);
+
+    reply = dbus_message_new_method_return(dbus_req->message);
+    if (!reply) return ENOMEM;
+    dbus_message_iter_init_append(reply, &iter);
+    dbret = dbus_message_iter_open_container(
+                                     &iter, DBUS_TYPE_ARRAY,
+                                     DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+                                     DBUS_TYPE_STRING_AS_STRING
+                                     DBUS_TYPE_VARIANT_AS_STRING
+                                     DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+                                     &iter_dict);
+    if (!dbret) return ENOMEM;
+
+    property = sbus_meta_find_property(intf->vtable->meta, "FullName");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        s_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (s_handler) {
+            (s_handler)(dbus_req, dbus_req->intf->instance_data, &s_prop_val);
+            s_out_val = s_prop_val == NULL ? "" : s_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "FullName", DBUS_TYPE_STRING, &s_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "byte");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        y_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (y_handler) {
+            (y_handler)(dbus_req, dbus_req->intf->instance_data, &y_prop_val);
+            y_out_val = y_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "byte", DBUS_TYPE_BYTE, &y_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "boolean");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        b_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (b_handler) {
+            (b_handler)(dbus_req, dbus_req->intf->instance_data, &b_prop_val);
+            b_out_val = b_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "boolean", DBUS_TYPE_BOOLEAN, &b_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "int16");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        n_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (n_handler) {
+            (n_handler)(dbus_req, dbus_req->intf->instance_data, &n_prop_val);
+            n_out_val = n_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "int16", DBUS_TYPE_INT16, &n_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "uint16");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        q_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (q_handler) {
+            (q_handler)(dbus_req, dbus_req->intf->instance_data, &q_prop_val);
+            q_out_val = q_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "uint16", DBUS_TYPE_UINT16, &q_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "int32");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        i_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (i_handler) {
+            (i_handler)(dbus_req, dbus_req->intf->instance_data, &i_prop_val);
+            i_out_val = i_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "int32", DBUS_TYPE_INT32, &i_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "uint32");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        u_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (u_handler) {
+            (u_handler)(dbus_req, dbus_req->intf->instance_data, &u_prop_val);
+            u_out_val = u_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "uint32", DBUS_TYPE_UINT32, &u_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "int64");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        x_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (x_handler) {
+            (x_handler)(dbus_req, dbus_req->intf->instance_data, &x_prop_val);
+            x_out_val = x_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "int64", DBUS_TYPE_INT64, &x_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "uint64");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        t_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (t_handler) {
+            (t_handler)(dbus_req, dbus_req->intf->instance_data, &t_prop_val);
+            t_out_val = t_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "uint64", DBUS_TYPE_UINT64, &t_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "double");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        d_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (d_handler) {
+            (d_handler)(dbus_req, dbus_req->intf->instance_data, &d_prop_val);
+            d_out_val = d_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "double", DBUS_TYPE_DOUBLE, &d_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "string");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        s_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (s_handler) {
+            (s_handler)(dbus_req, dbus_req->intf->instance_data, &s_prop_val);
+            s_out_val = s_prop_val == NULL ? "" : s_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "string", DBUS_TYPE_STRING, &s_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "object_path");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        o_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (o_handler) {
+            (o_handler)(dbus_req, dbus_req->intf->instance_data, &o_prop_val);
+            o_out_val = o_prop_val == NULL ? "/" : o_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "object_path", DBUS_TYPE_OBJECT_PATH, &o_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "null_string");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        s_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (s_handler) {
+            (s_handler)(dbus_req, dbus_req->intf->instance_data, &s_prop_val);
+            s_out_val = s_prop_val == NULL ? "" : s_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "null_string", DBUS_TYPE_STRING, &s_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "null_path");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        o_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (o_handler) {
+            (o_handler)(dbus_req, dbus_req->intf->instance_data, &o_prop_val);
+            o_out_val = o_prop_val == NULL ? "/" : o_prop_val;
+            ret = sbus_add_variant_to_dict(&iter_dict, "null_path", DBUS_TYPE_OBJECT_PATH, &o_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "byte_array");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        ay_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (ay_handler) {
+            (ay_handler)(dbus_req, dbus_req->intf->instance_data, &ay_prop_val, &ay_prop_len);
+            ay_out_val = ay_prop_val;
+            ret = sbus_add_array_as_variant_to_dict(&iter_dict, "byte_array", DBUS_TYPE_BYTE, (uint8_t*)ay_out_val, ay_prop_len, sizeof(uint8_t));
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "int16_array");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        an_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (an_handler) {
+            (an_handler)(dbus_req, dbus_req->intf->instance_data, &an_prop_val, &an_prop_len);
+            an_out_val = an_prop_val;
+            ret = sbus_add_array_as_variant_to_dict(&iter_dict, "int16_array", DBUS_TYPE_INT16, (uint8_t*)an_out_val, an_prop_len, sizeof(int16_t));
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "uint16_array");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        aq_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (aq_handler) {
+            (aq_handler)(dbus_req, dbus_req->intf->instance_data, &aq_prop_val, &aq_prop_len);
+            aq_out_val = aq_prop_val;
+            ret = sbus_add_array_as_variant_to_dict(&iter_dict, "uint16_array", DBUS_TYPE_UINT16, (uint8_t*)aq_out_val, aq_prop_len, sizeof(uint16_t));
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "int32_array");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        ai_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (ai_handler) {
+            (ai_handler)(dbus_req, dbus_req->intf->instance_data, &ai_prop_val, &ai_prop_len);
+            ai_out_val = ai_prop_val;
+            ret = sbus_add_array_as_variant_to_dict(&iter_dict, "int32_array", DBUS_TYPE_INT32, (uint8_t*)ai_out_val, ai_prop_len, sizeof(int32_t));
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "uint32_array");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        au_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (au_handler) {
+            (au_handler)(dbus_req, dbus_req->intf->instance_data, &au_prop_val, &au_prop_len);
+            au_out_val = au_prop_val;
+            ret = sbus_add_array_as_variant_to_dict(&iter_dict, "uint32_array", DBUS_TYPE_UINT32, (uint8_t*)au_out_val, au_prop_len, sizeof(uint32_t));
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "int64_array");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        ax_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (ax_handler) {
+            (ax_handler)(dbus_req, dbus_req->intf->instance_data, &ax_prop_val, &ax_prop_len);
+            ax_out_val = ax_prop_val;
+            ret = sbus_add_array_as_variant_to_dict(&iter_dict, "int64_array", DBUS_TYPE_INT64, (uint8_t*)ax_out_val, ax_prop_len, sizeof(int64_t));
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "uint64_array");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        at_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (at_handler) {
+            (at_handler)(dbus_req, dbus_req->intf->instance_data, &at_prop_val, &at_prop_len);
+            at_out_val = at_prop_val;
+            ret = sbus_add_array_as_variant_to_dict(&iter_dict, "uint64_array", DBUS_TYPE_UINT64, (uint8_t*)at_out_val, at_prop_len, sizeof(uint64_t));
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "double_array");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        ad_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (ad_handler) {
+            (ad_handler)(dbus_req, dbus_req->intf->instance_data, &ad_prop_val, &ad_prop_len);
+            ad_out_val = ad_prop_val;
+            ret = sbus_add_array_as_variant_to_dict(&iter_dict, "double_array", DBUS_TYPE_DOUBLE, (uint8_t*)ad_out_val, ad_prop_len, sizeof(double));
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "string_array");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        as_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (as_handler) {
+            (as_handler)(dbus_req, dbus_req->intf->instance_data, &as_prop_val, &as_prop_len);
+            as_out_val = as_prop_val;
+            ret = sbus_add_array_as_variant_to_dict(&iter_dict, "string_array", DBUS_TYPE_STRING, (uint8_t*)as_out_val, as_prop_len, sizeof(const char *));
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "object_path_array");
+    if (property != NULL && property->flags & SBUS_PROPERTY_READABLE) {
+        ao_handler = VTABLE_FUNC(intf->vtable, property->vtable_offset_get);
+        if (ao_handler) {
+            (ao_handler)(dbus_req, dbus_req->intf->instance_data, &ao_prop_val, &ao_prop_len);
+            ao_out_val = ao_prop_val;
+            ret = sbus_add_array_as_variant_to_dict(&iter_dict, "object_path_array", DBUS_TYPE_OBJECT_PATH, (uint8_t*)ao_out_val, ao_prop_len, sizeof(const char *));
+            if (ret != EOK) return ret;
+        }
+    }
+
+    dbret = dbus_message_iter_close_container(&iter, &iter_dict);
+    if (!dbret) return ENOMEM;
+
+    return sbus_request_finish(dbus_req, reply);
+}
+
 /* interface info for com.planetexpress.Pilot */
 const struct sbus_interface_meta test_pilot_meta = {
     "com.planetexpress.Pilot", /* name */
     test_pilot__methods,
     NULL, /* no signals */
-    test_pilot__properties
+    test_pilot__properties,
+    invoke_test_pilot_get_all, /* GetAll invoker */
 };
 
 /* invokes a handler with a 'bu' DBus signature */
-- 
1.9.0

-------------- next part --------------
>From cbd8d3192ef371d7cf92c011993563061919e9f2 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Wed, 21 May 2014 20:10:23 +0200
Subject: [PATCH 5/5] SBUS: Add org.freedesktop.DBus.Properties.GetAll to
 Introspection

---
 src/sbus/sssd_dbus_introspect.c | 4 ++++
 src/tests/sbus_tests.c          | 4 ++++
 2 files changed, 8 insertions(+)

diff --git a/src/sbus/sssd_dbus_introspect.c b/src/sbus/sssd_dbus_introspect.c
index 4bd9563e6dad31009e92a0f4f7de97428a0185ca..cb8780dce3e08509dee6437fe57eae1dcc48ebe9 100644
--- a/src/sbus/sssd_dbus_introspect.c
+++ b/src/sbus/sssd_dbus_introspect.c
@@ -54,6 +54,10 @@ const struct sbus_method_meta introspect_method =
      "     <arg name=\"property\" direction=\"in\" type=\"s\"/>\n"          \
      "     <arg name=\"value\" direction=\"out\" type=\"v\"/>\n"            \
      "   </method>\n"                                                       \
+     "   <method name=\"GetAll\">\n"                                        \
+     "     <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n"         \
+     "     <arg name=\"properties\" direction=\"out\" type=\"a{sv}\"/>\n"   \
+     "   </method>\n"                                                       \
      " </interface>\n"
 
 struct introspect_ctx {
diff --git a/src/tests/sbus_tests.c b/src/tests/sbus_tests.c
index d2725cf0e542f20bc1d22db91fa04e80392e7fa9..31b91c48ab57823d80323c8616e3451f6cf5f164 100644
--- a/src/tests/sbus_tests.c
+++ b/src/tests/sbus_tests.c
@@ -65,6 +65,10 @@
         "     <arg name=\"property\" direction=\"in\" type=\"s\"/>\n"                        \
         "     <arg name=\"value\" direction=\"out\" type=\"v\"/>\n"                          \
         "   </method>\n"                                                                     \
+        "   <method name=\"GetAll\">\n"                                                      \
+        "     <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n"                       \
+        "     <arg name=\"properties\" direction=\"out\" type=\"a{sv}\"/>\n"                 \
+        "   </method>\n"                                                                     \
         " </interface>\n"                                                                    \
         "</node>\n"
 
-- 
1.9.0



More information about the sssd-devel mailing list