From 1c86437693217b12cff1b08e86fb9e6327b79d27 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Thu, 22 May 2014 19:01:35 +0200
Subject: [PATCH 2/7] IFP: Implement domain getters

---
 src/responder/ifp/ifp_domains.c         | 307 +++++++++++++++++++++++
 src/responder/ifp/ifp_domains.h         |  60 +++++
 src/responder/ifp/ifp_iface.xml         |  19 ++
 src/responder/ifp/ifp_iface_generated.c | 415 ++++++++++++++++++++++++++++++++
 src/responder/ifp/ifp_iface_generated.h |  39 +++
 src/responder/ifp/ifpsrv.c              |  19 ++
 6 files changed, 859 insertions(+)

diff --git a/src/responder/ifp/ifp_domains.c b/src/responder/ifp/ifp_domains.c
index a06ba471c43ac7111693aa0d22a14cf33d168caa..0d50dac32471d82e98ba7a958e44e42a30d2cbf5 100644
--- a/src/responder/ifp/ifp_domains.c
+++ b/src/responder/ifp/ifp_domains.c
@@ -20,6 +20,8 @@
 */
 
 #include <talloc.h>
+#include <tevent.h>
+#include <string.h>
 
 #include "db/sysdb.h"
 #include "util/util.h"
@@ -27,6 +29,19 @@
 #include "responder/common/responder.h"
 #include "responder/ifp/ifp_domains.h"
 
+#define RETURN_DOM_PROP_AS_STRING(dbus_req, pvt_data, out, property) do { \
+    struct sss_domain_info *__dom;                                        \
+                                                                          \
+    *(out) = NULL;                                                        \
+                                                                          \
+    __dom = get_domain_info_from_req((dbus_req), (pvt_data));             \
+    if (__dom == NULL) {                                                  \
+        return;                                                           \
+    }                                                                     \
+                                                                          \
+    *(out) = __dom->property;                                             \
+} while (0)
+
 static void ifp_list_domains_process(struct tevent_req *req);
 
 int ifp_list_domains(struct sbus_request *dbus_req,
@@ -232,3 +247,295 @@ static void ifp_find_domain_by_name_process(struct tevent_req *req)
         DEBUG(SSSDBG_OP_FAILURE, "Could not finish request!\n");
     }
 }
+
+static struct sss_domain_info *
+get_domain_info_from_req(struct sbus_request *dbus_req, void *data)
+{
+    struct ifp_ctx *ctx = NULL;
+    struct sss_domain_info *domains = NULL;
+    struct sss_domain_info *iter = NULL;
+    const char *path = dbus_message_get_path(dbus_req->message);
+    const char *raw_name = NULL;
+    char *name = NULL;
+
+    ctx = talloc_get_type(data, struct ifp_ctx);
+    if (ctx == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
+        return NULL;
+    }
+
+    raw_name = ifp_path_strip_prefix(path, INFOPIPE_DOMAIN_PATH_PFX "/");
+    if (raw_name == NULL) {
+        return NULL;
+    }
+
+    name = ifp_bus_path_unescape(dbus_req, raw_name);
+    if (name == NULL) {
+        return NULL;
+    }
+
+    DEBUG(SSSDBG_TRACE_INTERNAL, "Looking for domain %s\n", name);
+
+    domains = ctx->rctx->domains;
+    for (iter = domains; iter != NULL; iter = get_next_domain(iter, true)) {
+        if (strcasecmp(iter->name, name) == 0) {
+            break;
+        }
+    }
+
+    talloc_free(name);
+    return iter;
+}
+
+static void get_server_list(struct sbus_request *dbus_req,
+                            void *data,
+                            const char ***_out,
+                            int *_out_len,
+                            bool backup)
+{
+    static const char *srv[] = {"_srv_"};
+    struct sss_domain_info *dom = NULL;
+    struct ifp_ctx *ctx = NULL;
+    const char *conf_path = NULL;
+    const char *option = NULL;
+    const char **out = NULL;
+    char **servers = NULL;
+    int num_servers;
+    errno_t ret;
+    int i;
+
+    *_out = NULL;
+    *_out_len = 0;
+
+    dom = get_domain_info_from_req(dbus_req, data);
+    if (dom == NULL) {
+        return;
+    }
+
+    if (dom->parent != NULL) {
+        /* subdomains are not present in configuration */
+        ret = ENOENT;
+        goto done;
+    }
+
+    ctx = talloc_get_type(data, struct ifp_ctx);
+    if (ctx == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Invalid ifp context!\n");
+        ret = ENOMEM;
+        goto done;
+    }
+
+    conf_path = talloc_asprintf(dbus_req, CONFDB_DOMAIN_PATH_TMPL, dom->name);
+    if (conf_path == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    /* TODO: replace hardcoded values with option names from the provider */
+    if (strcasecmp(dom->provider, "ldap") == 0) {
+        option = backup == false ? "ldap_uri" : "ldap_backup_uri";
+    } else if (strcasecmp(dom->provider, "ipa") == 0) {
+        option = backup == false ? "ipa_server" : "ipa_backup_server";
+    } else if (strcasecmp(dom->provider, "ad") == 0) {
+        option = backup == false ? "ad_server" : "ad_backup_server";
+    } else {
+        ret = EINVAL;
+        goto done;
+    }
+
+    ret = confdb_get_string_as_list(ctx->rctx->cdb, dbus_req, conf_path,
+                                    option, &servers);
+    if (ret != EOK) {
+        goto done;
+    }
+
+    for (num_servers = 0; servers[num_servers] != NULL; num_servers++);
+
+    if (num_servers == 0) {
+        ret = ENOENT;
+        goto done;
+    }
+
+    out = talloc_zero_array(dbus_req, const char*, num_servers);
+    if (out == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    for (i = 0; i < num_servers; i++) {
+        out[i] = talloc_steal(out, servers[i]);
+    }
+
+    *_out = out;
+    *_out_len = num_servers;
+
+    ret = EOK;
+
+done:
+    if (ret == ENOENT) {
+        *_out = srv;
+        *_out_len = 1;
+    }
+
+    return;
+}
+
+void ifp_dom_get_name(struct sbus_request *dbus_req,
+                      void *data,
+                      const char **_out)
+{
+    RETURN_DOM_PROP_AS_STRING(dbus_req, data, _out, name);
+}
+
+void ifp_dom_get_provider(struct sbus_request *dbus_req,
+                          void *data,
+                          const char **_out)
+{
+    RETURN_DOM_PROP_AS_STRING(dbus_req, data, _out, provider);
+}
+
+void ifp_dom_get_primary_servers(struct sbus_request *dbus_req,
+                                 void *data,
+                                 const char ***_out,
+                                 int *_out_len)
+{
+    get_server_list(dbus_req, data, _out, _out_len, false);
+}
+
+void ifp_dom_get_backup_servers(struct sbus_request *dbus_req,
+                                void *data,
+                                const char ***_out,
+                                int *_out_len)
+{
+    get_server_list(dbus_req, data, _out, _out_len, true);
+}
+
+void ifp_dom_get_min_id(struct sbus_request *dbus_req,
+                        void *data,
+                        uint32_t *_out)
+{
+    struct sss_domain_info *dom;
+
+    *_out = 1;
+
+    dom = get_domain_info_from_req(dbus_req, data);
+    if (dom == NULL) {
+        return;
+    }
+
+    *_out = dom->id_min;
+}
+
+void ifp_dom_get_max_id(struct sbus_request *dbus_req,
+                        void *data,
+                        uint32_t *_out)
+{
+    struct sss_domain_info *dom;
+
+    *_out = 0;
+
+    dom = get_domain_info_from_req(dbus_req, data);
+    if (dom == NULL) {
+        return;
+    }
+
+    *_out = dom->id_max;
+}
+
+void ifp_dom_get_realm(struct sbus_request *dbus_req,
+                       void *data,
+                       const char **_out)
+{
+    RETURN_DOM_PROP_AS_STRING(dbus_req, data, _out, realm);
+}
+
+void ifp_dom_get_forest(struct sbus_request *dbus_req,
+                        void *data,
+                        const char **_out)
+{
+    RETURN_DOM_PROP_AS_STRING(dbus_req, data, _out, forest);
+}
+
+void ifp_dom_get_login_format(struct sbus_request *dbus_req,
+                              void *data,
+                              const char **_out)
+{
+    RETURN_DOM_PROP_AS_STRING(dbus_req, data, _out, names->re_pattern);
+}
+
+void ifp_dom_get_fqdn_format(struct sbus_request *dbus_req,
+                             void *data,
+                             const char **_out)
+{
+    RETURN_DOM_PROP_AS_STRING(dbus_req, data, _out, names->fq_fmt);
+}
+
+void ifp_dom_get_enumerable(struct sbus_request *dbus_req,
+                            void *data,
+                            bool *_out)
+{
+    struct sss_domain_info *dom;
+
+    *_out = false;
+
+    dom = get_domain_info_from_req(dbus_req, data);
+    if (dom == NULL) {
+        return;
+    }
+
+    *_out = dom->enumerate;
+}
+
+void ifp_dom_get_use_fqdn(struct sbus_request *dbus_req,
+                          void *data,
+                          bool *_out)
+{
+    struct sss_domain_info *dom;
+
+    *_out = false;
+
+    dom = get_domain_info_from_req(dbus_req, data);
+    if (dom == NULL) {
+        return;
+    }
+
+    *_out = dom->fqnames;
+}
+
+void ifp_dom_get_subdomain(struct sbus_request *dbus_req,
+                           void *data,
+                           bool *_out)
+{
+    struct sss_domain_info *dom;
+
+    *_out = false;
+
+    dom = get_domain_info_from_req(dbus_req, data);
+    if (dom == NULL) {
+        return;
+    }
+
+    *_out = dom->parent ? true : false;
+}
+
+void ifp_dom_get_parent_domain(struct sbus_request *dbus_req,
+                              void *data,
+                              const char **_out)
+{
+    struct sss_domain_info *dom;
+
+    *_out = NULL;
+
+    dom = get_domain_info_from_req(dbus_req, data);
+    if (dom == NULL) {
+        return;
+    }
+
+    if (dom->parent == NULL) {
+        *_out = "/";
+        return;
+    }
+
+    *_out = ifp_reply_objpath(dbus_req, INFOPIPE_DOMAIN_PATH_PFX,
+                              dom->parent->name);
+}
diff --git a/src/responder/ifp/ifp_domains.h b/src/responder/ifp/ifp_domains.h
index 32771a93c74ce919860dcd3521e7aa30a1ff8114..d6ef1a04d10ee69ea620fb638c8ee358d3fe21f5 100644
--- a/src/responder/ifp/ifp_domains.h
+++ b/src/responder/ifp/ifp_domains.h
@@ -37,4 +37,64 @@ int ifp_find_domain_by_name(struct sbus_request *dbus_req,
                             void *data,
                             const char *arg_name);
 
+/* org.freedesktop.sssd.infopipe.Domains */
+
+void ifp_dom_get_name(struct sbus_request *dbus_req,
+                      void *data,
+                      const char **_out);
+
+void ifp_dom_get_provider(struct sbus_request *dbus_req,
+                          void *data,
+                          const char **_out);
+
+void ifp_dom_get_primary_servers(struct sbus_request *dbus_req,
+                                 void *data,
+                                 const char ***_out,
+                                 int *_out_len);
+
+void ifp_dom_get_backup_servers(struct sbus_request *dbus_req,
+                                void *data,
+                                const char ***_out,
+                                int *_out_len);
+
+void ifp_dom_get_min_id(struct sbus_request *dbus_req,
+                        void *data,
+                        uint32_t *_out);
+
+void ifp_dom_get_max_id(struct sbus_request *dbus_req,
+                        void *data,
+                        uint32_t *_out);
+
+void ifp_dom_get_realm(struct sbus_request *dbus_req,
+                       void *data,
+                       const char **_out);
+
+void ifp_dom_get_forest(struct sbus_request *dbus_req,
+                        void *data,
+                        const char **_out);
+
+void ifp_dom_get_login_format(struct sbus_request *dbus_req,
+                              void *data,
+                              const char **_out);
+
+void ifp_dom_get_fqdn_format(struct sbus_request *dbus_req,
+                             void *data,
+                             const char **_out);
+
+void ifp_dom_get_enumerable(struct sbus_request *dbus_req,
+                            void *data,
+                            bool *_out);
+
+void ifp_dom_get_use_fqdn(struct sbus_request *dbus_req,
+                          void *data,
+                          bool *_out);
+
+void ifp_dom_get_subdomain(struct sbus_request *dbus_req,
+                           void *data,
+                           bool *_out);
+
+void ifp_dom_get_parent_domain(struct sbus_request *dbus_req,
+                              void *data,
+                              const char **_out);
+
 #endif /* IFP_DOMAINS_H_ */
diff --git a/src/responder/ifp/ifp_iface.xml b/src/responder/ifp/ifp_iface.xml
index af75ae88de060b731f14a01b2e99349719817aa9..1b9acd113db3f30904865e944d7214a7b45c2b34 100644
--- a/src/responder/ifp/ifp_iface.xml
+++ b/src/responder/ifp/ifp_iface.xml
@@ -31,4 +31,23 @@
         </method>
 
     </interface>
+
+    <interface name="org.freedesktop.sssd.infopipe.Domains">
+        <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="infopipe_domain"/>
+
+        <property name="name" type="s" access="read"/>
+        <property name="provider" type="s" access="read"/>
+        <property name="primary_servers" type="as" access="read"/>
+        <property name="backup_servers" type="as" access="read"/>
+        <property name="min_id" type="u" access="read"/>
+        <property name="max_id" type="u" access="read"/>
+        <property name="realm" type="s" access="read"/>
+        <property name="forest" type="s" access="read"/>
+        <property name="login_format" type="s" access="read"/>
+        <property name="fully_qualified_name_format" type="s" access="read"/>
+        <property name="enumerable" type="b" access="read"/>
+        <property name="use_fully_qualified_names" type="b" access="read"/>
+        <property name="subdomain" type="b" access="read"/>
+        <property name="parent_domain" type="o" access="read"/>
+    </interface>
 </node>
diff --git a/src/responder/ifp/ifp_iface_generated.c b/src/responder/ifp/ifp_iface_generated.c
index fe203e240398b5095a9cda253e6a36ffac59ddc0..16beb65094b2ce5e9bd901847dfa7a7ab1548189 100644
--- a/src/responder/ifp/ifp_iface_generated.c
+++ b/src/responder/ifp/ifp_iface_generated.c
@@ -7,6 +7,11 @@
 
 /* invokes a handler with a 's' DBus signature */
 static int invoke_s_method(struct sbus_request *dbus_req, void *function_ptr);
+static int invoke_get_s(struct sbus_request *dbus_req, void *function_ptr);
+static int invoke_get_as(struct sbus_request *dbus_req, void *function_ptr);
+static int invoke_get_u(struct sbus_request *dbus_req, void *function_ptr);
+static int invoke_get_b(struct sbus_request *dbus_req, void *function_ptr);
+static int invoke_get_o(struct sbus_request *dbus_req, void *function_ptr);
 
 /* arguments for org.freedesktop.sssd.infopipe.GetUserAttr */
 const struct sbus_arg_meta infopipe_iface_GetUserAttr__in[] = {
@@ -147,6 +152,345 @@ const struct sbus_interface_meta infopipe_iface_meta = {
     invoke_infopipe_iface_get_all, /* GetAll invoker */
 };
 
+/* invokes GetAll for the 'org.freedesktop.sssd.infopipe.Domains' interface */
+static int invoke_infopipe_domain_get_all(struct sbus_request *dbus_req, void *function_ptr)
+{
+    struct sbus_interface *intf = dbus_req->intf;
+    const struct sbus_property_meta *property;
+    DBusMessage *reply;
+    dbus_bool_t dbret;
+    DBusMessageIter iter;
+    DBusMessageIter iter_dict;
+    int ret;
+    const char * s_prop_val;
+    const char * s_out_val;
+    void (*s_handler)(struct sbus_request *, void *data, const char * *);
+    bool b_prop_val;
+    dbus_bool_t b_out_val;
+    void (*b_handler)(struct sbus_request *, void *data, bool *);
+    uint32_t u_prop_val;
+    uint32_t u_out_val;
+    void (*u_handler)(struct sbus_request *, void *data, uint32_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 * *);
+
+    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, "name");
+    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, "name", DBUS_TYPE_STRING, &s_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "provider");
+    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, "provider", DBUS_TYPE_STRING, &s_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "primary_servers");
+    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, "primary_servers", 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, "backup_servers");
+    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, "backup_servers", 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, "min_id");
+    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, "min_id", DBUS_TYPE_UINT32, &u_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "max_id");
+    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, "max_id", DBUS_TYPE_UINT32, &u_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "realm");
+    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, "realm", DBUS_TYPE_STRING, &s_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "forest");
+    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, "forest", DBUS_TYPE_STRING, &s_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "login_format");
+    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, "login_format", DBUS_TYPE_STRING, &s_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "fully_qualified_name_format");
+    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, "fully_qualified_name_format", DBUS_TYPE_STRING, &s_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "enumerable");
+    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, "enumerable", DBUS_TYPE_BOOLEAN, &b_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "use_fully_qualified_names");
+    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, "use_fully_qualified_names", DBUS_TYPE_BOOLEAN, &b_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "subdomain");
+    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, "subdomain", DBUS_TYPE_BOOLEAN, &b_out_val);
+            if (ret != EOK) return ret;
+        }
+    }
+
+    property = sbus_meta_find_property(intf->vtable->meta, "parent_domain");
+    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, "parent_domain", DBUS_TYPE_OBJECT_PATH, &o_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);
+}
+
+/* property info for org.freedesktop.sssd.infopipe.Domains */
+const struct sbus_property_meta infopipe_domain__properties[] = {
+    {
+        "name", /* name */
+        "s", /* type */
+        SBUS_PROPERTY_READABLE,
+        offsetof(struct infopipe_domain, infopipe_domain_get_name),
+        invoke_get_s,
+        0, /* not writable */
+        NULL, /* no invoker */
+    },
+    {
+        "provider", /* name */
+        "s", /* type */
+        SBUS_PROPERTY_READABLE,
+        offsetof(struct infopipe_domain, infopipe_domain_get_provider),
+        invoke_get_s,
+        0, /* not writable */
+        NULL, /* no invoker */
+    },
+    {
+        "primary_servers", /* name */
+        "as", /* type */
+        SBUS_PROPERTY_READABLE,
+        offsetof(struct infopipe_domain, infopipe_domain_get_primary_servers),
+        invoke_get_as,
+        0, /* not writable */
+        NULL, /* no invoker */
+    },
+    {
+        "backup_servers", /* name */
+        "as", /* type */
+        SBUS_PROPERTY_READABLE,
+        offsetof(struct infopipe_domain, infopipe_domain_get_backup_servers),
+        invoke_get_as,
+        0, /* not writable */
+        NULL, /* no invoker */
+    },
+    {
+        "min_id", /* name */
+        "u", /* type */
+        SBUS_PROPERTY_READABLE,
+        offsetof(struct infopipe_domain, infopipe_domain_get_min_id),
+        invoke_get_u,
+        0, /* not writable */
+        NULL, /* no invoker */
+    },
+    {
+        "max_id", /* name */
+        "u", /* type */
+        SBUS_PROPERTY_READABLE,
+        offsetof(struct infopipe_domain, infopipe_domain_get_max_id),
+        invoke_get_u,
+        0, /* not writable */
+        NULL, /* no invoker */
+    },
+    {
+        "realm", /* name */
+        "s", /* type */
+        SBUS_PROPERTY_READABLE,
+        offsetof(struct infopipe_domain, infopipe_domain_get_realm),
+        invoke_get_s,
+        0, /* not writable */
+        NULL, /* no invoker */
+    },
+    {
+        "forest", /* name */
+        "s", /* type */
+        SBUS_PROPERTY_READABLE,
+        offsetof(struct infopipe_domain, infopipe_domain_get_forest),
+        invoke_get_s,
+        0, /* not writable */
+        NULL, /* no invoker */
+    },
+    {
+        "login_format", /* name */
+        "s", /* type */
+        SBUS_PROPERTY_READABLE,
+        offsetof(struct infopipe_domain, infopipe_domain_get_login_format),
+        invoke_get_s,
+        0, /* not writable */
+        NULL, /* no invoker */
+    },
+    {
+        "fully_qualified_name_format", /* name */
+        "s", /* type */
+        SBUS_PROPERTY_READABLE,
+        offsetof(struct infopipe_domain, infopipe_domain_get_fully_qualified_name_format),
+        invoke_get_s,
+        0, /* not writable */
+        NULL, /* no invoker */
+    },
+    {
+        "enumerable", /* name */
+        "b", /* type */
+        SBUS_PROPERTY_READABLE,
+        offsetof(struct infopipe_domain, infopipe_domain_get_enumerable),
+        invoke_get_b,
+        0, /* not writable */
+        NULL, /* no invoker */
+    },
+    {
+        "use_fully_qualified_names", /* name */
+        "b", /* type */
+        SBUS_PROPERTY_READABLE,
+        offsetof(struct infopipe_domain, infopipe_domain_get_use_fully_qualified_names),
+        invoke_get_b,
+        0, /* not writable */
+        NULL, /* no invoker */
+    },
+    {
+        "subdomain", /* name */
+        "b", /* type */
+        SBUS_PROPERTY_READABLE,
+        offsetof(struct infopipe_domain, infopipe_domain_get_subdomain),
+        invoke_get_b,
+        0, /* not writable */
+        NULL, /* no invoker */
+    },
+    {
+        "parent_domain", /* name */
+        "o", /* type */
+        SBUS_PROPERTY_READABLE,
+        offsetof(struct infopipe_domain, infopipe_domain_get_parent_domain),
+        invoke_get_o,
+        0, /* not writable */
+        NULL, /* no invoker */
+    },
+    { NULL, }
+};
+
+/* interface info for org.freedesktop.sssd.infopipe.Domains */
+const struct sbus_interface_meta infopipe_domain_meta = {
+    "org.freedesktop.sssd.infopipe.Domains", /* name */
+    NULL, /* no methods */
+    NULL, /* no signals */
+    infopipe_domain__properties,
+    invoke_infopipe_domain_get_all, /* GetAll invoker */
+};
+
 /* invokes a handler with a 's' DBus signature */
 static int invoke_s_method(struct sbus_request *dbus_req, void *function_ptr)
 {
@@ -162,3 +506,74 @@ static int invoke_s_method(struct sbus_request *dbus_req, void *function_ptr)
     return (handler)(dbus_req, dbus_req->intf->instance_data,
                      arg_0);
 }
+
+/* invokes a getter with a 'const char *' DBus type */
+static int invoke_get_s(struct sbus_request *dbus_req, void *function_ptr)
+{
+    const char * prop_val;
+    const char * out_val;
+
+    void (*handler)(struct sbus_request *, void *data, const char * *) = function_ptr;
+
+    (handler)(dbus_req, dbus_req->intf->instance_data, &prop_val);
+
+    out_val = prop_val == NULL ? "" : prop_val;
+    return sbus_request_return_as_variant(dbus_req, DBUS_TYPE_STRING, &out_val);
+}
+
+/* invokes a getter with a 'dbus_bool_t' DBus type */
+static int invoke_get_b(struct sbus_request *dbus_req, void *function_ptr)
+{
+    bool prop_val;
+    dbus_bool_t out_val;
+
+    void (*handler)(struct sbus_request *, void *data, bool *) = function_ptr;
+
+    (handler)(dbus_req, dbus_req->intf->instance_data, &prop_val);
+
+    out_val = prop_val;
+    return sbus_request_return_as_variant(dbus_req, DBUS_TYPE_BOOLEAN, &out_val);
+}
+
+/* invokes a getter with a 'uint32_t' DBus type */
+static int invoke_get_u(struct sbus_request *dbus_req, void *function_ptr)
+{
+    uint32_t prop_val;
+    uint32_t out_val;
+
+    void (*handler)(struct sbus_request *, void *data, uint32_t *) = function_ptr;
+
+    (handler)(dbus_req, dbus_req->intf->instance_data, &prop_val);
+
+    out_val = prop_val;
+    return sbus_request_return_as_variant(dbus_req, DBUS_TYPE_UINT32, &out_val);
+}
+
+/* invokes a getter with an array of 'const char *' DBus type */
+static int invoke_get_as(struct sbus_request *dbus_req, void *function_ptr)
+{
+    const char * *prop_val;
+    int prop_len;
+    const char * *out_val;
+
+    void (*handler)(struct sbus_request *, void *data, const char * * *, int *) = function_ptr;
+
+    (handler)(dbus_req, dbus_req->intf->instance_data, &prop_val, &prop_len);
+
+    out_val = prop_val;
+    return sbus_request_return_array_as_variant(dbus_req, DBUS_TYPE_STRING, (uint8_t*)out_val, prop_len, sizeof(const char *));
+}
+
+/* invokes a getter with a 'const char *' DBus type */
+static int invoke_get_o(struct sbus_request *dbus_req, void *function_ptr)
+{
+    const char * prop_val;
+    const char * out_val;
+
+    void (*handler)(struct sbus_request *, void *data, const char * *) = function_ptr;
+
+    (handler)(dbus_req, dbus_req->intf->instance_data, &prop_val);
+
+    out_val = prop_val == NULL ? "/" : prop_val;
+    return sbus_request_return_as_variant(dbus_req, DBUS_TYPE_OBJECT_PATH, &out_val);
+}
diff --git a/src/responder/ifp/ifp_iface_generated.h b/src/responder/ifp/ifp_iface_generated.h
index ca0e1c3668f94ceb57c77306552866ff59370df4..3fe8c41e9165b89565723c0027b2c63d73a7c1c8 100644
--- a/src/responder/ifp/ifp_iface_generated.h
+++ b/src/responder/ifp/ifp_iface_generated.h
@@ -19,6 +19,23 @@
 #define INFOPIPE_IFACE_FINDDOMAINBYNAME "FindDomainByName"
 #define INFOPIPE_IFACE_LISTDOMAINS "ListDomains"
 
+/* constants for org.freedesktop.sssd.infopipe.Domains */
+#define INFOPIPE_DOMAIN "org.freedesktop.sssd.infopipe.Domains"
+#define INFOPIPE_DOMAIN_NAME "name"
+#define INFOPIPE_DOMAIN_PROVIDER "provider"
+#define INFOPIPE_DOMAIN_PRIMARY_SERVERS "primary_servers"
+#define INFOPIPE_DOMAIN_BACKUP_SERVERS "backup_servers"
+#define INFOPIPE_DOMAIN_MIN_ID "min_id"
+#define INFOPIPE_DOMAIN_MAX_ID "max_id"
+#define INFOPIPE_DOMAIN_REALM "realm"
+#define INFOPIPE_DOMAIN_FOREST "forest"
+#define INFOPIPE_DOMAIN_LOGIN_FORMAT "login_format"
+#define INFOPIPE_DOMAIN_FULLY_QUALIFIED_NAME_FORMAT "fully_qualified_name_format"
+#define INFOPIPE_DOMAIN_ENUMERABLE "enumerable"
+#define INFOPIPE_DOMAIN_USE_FULLY_QUALIFIED_NAMES "use_fully_qualified_names"
+#define INFOPIPE_DOMAIN_SUBDOMAIN "subdomain"
+#define INFOPIPE_DOMAIN_PARENT_DOMAIN "parent_domain"
+
 /* ------------------------------------------------------------------------
  * DBus handlers
  *
@@ -56,6 +73,25 @@ int infopipe_iface_FindDomainByName_finish(struct sbus_request *req, const char
 /* finish function for ListDomains */
 int infopipe_iface_ListDomains_finish(struct sbus_request *req, const char *arg_domain[], int len_domain);
 
+/* vtable for org.freedesktop.sssd.infopipe.Domains */
+struct infopipe_domain {
+    struct sbus_vtable vtable; /* derive from sbus_vtable */
+    void (*infopipe_domain_get_name)(struct sbus_request *, void *data, const char * *);
+    void (*infopipe_domain_get_provider)(struct sbus_request *, void *data, const char * *);
+    void (*infopipe_domain_get_primary_servers)(struct sbus_request *, void *data, const char * * *, int *);
+    void (*infopipe_domain_get_backup_servers)(struct sbus_request *, void *data, const char * * *, int *);
+    void (*infopipe_domain_get_min_id)(struct sbus_request *, void *data, uint32_t *);
+    void (*infopipe_domain_get_max_id)(struct sbus_request *, void *data, uint32_t *);
+    void (*infopipe_domain_get_realm)(struct sbus_request *, void *data, const char * *);
+    void (*infopipe_domain_get_forest)(struct sbus_request *, void *data, const char * *);
+    void (*infopipe_domain_get_login_format)(struct sbus_request *, void *data, const char * *);
+    void (*infopipe_domain_get_fully_qualified_name_format)(struct sbus_request *, void *data, const char * *);
+    void (*infopipe_domain_get_enumerable)(struct sbus_request *, void *data, bool *);
+    void (*infopipe_domain_get_use_fully_qualified_names)(struct sbus_request *, void *data, bool *);
+    void (*infopipe_domain_get_subdomain)(struct sbus_request *, void *data, bool *);
+    void (*infopipe_domain_get_parent_domain)(struct sbus_request *, void *data, const char * *);
+};
+
 /* ------------------------------------------------------------------------
  * DBus Interface Metadata
  *
@@ -69,4 +105,7 @@ int infopipe_iface_ListDomains_finish(struct sbus_request *req, const char *arg_
 /* interface info for org.freedesktop.sssd.infopipe */
 extern const struct sbus_interface_meta infopipe_iface_meta;
 
+/* interface info for org.freedesktop.sssd.infopipe.Domains */
+extern const struct sbus_interface_meta infopipe_domain_meta;
+
 #endif /* __IFP_IFACE_XML__ */
diff --git a/src/responder/ifp/ifpsrv.c b/src/responder/ifp/ifpsrv.c
index 2cffe6987e4079330d3b1552c303a0ff6fdd33cc..3e7d0dff6a31761af8174ee16765a3f5e4ea3b16 100644
--- a/src/responder/ifp/ifpsrv.c
+++ b/src/responder/ifp/ifpsrv.c
@@ -73,6 +73,24 @@ struct infopipe_iface ifp_iface = {
     .FindDomainByName = ifp_find_domain_by_name,
 };
 
+struct infopipe_domain ifp_domain = {
+    { &infopipe_domain_meta, 0 },
+    .infopipe_domain_get_name = ifp_dom_get_name,
+    .infopipe_domain_get_provider = ifp_dom_get_provider,
+    .infopipe_domain_get_primary_servers = ifp_dom_get_primary_servers,
+    .infopipe_domain_get_backup_servers = ifp_dom_get_backup_servers,
+    .infopipe_domain_get_min_id = ifp_dom_get_min_id,
+    .infopipe_domain_get_max_id = ifp_dom_get_max_id,
+    .infopipe_domain_get_realm = ifp_dom_get_realm,
+    .infopipe_domain_get_forest = ifp_dom_get_forest,
+    .infopipe_domain_get_login_format = ifp_dom_get_login_format,
+    .infopipe_domain_get_fully_qualified_name_format = ifp_dom_get_fqdn_format,
+    .infopipe_domain_get_enumerable = ifp_dom_get_enumerable,
+    .infopipe_domain_get_use_fully_qualified_names = ifp_dom_get_use_fqdn,
+    .infopipe_domain_get_subdomain = ifp_dom_get_subdomain,
+    .infopipe_domain_get_parent_domain = ifp_dom_get_parent_domain
+};
+
 struct sysbus_iface {
     const char *path;
     struct sbus_vtable *iface_vtable;
@@ -80,6 +98,7 @@ struct sysbus_iface {
 
 static struct sysbus_iface ifp_ifaces[] = {
     { INFOPIPE_PATH, &ifp_iface.vtable },
+    { INFOPIPE_DOMAIN_PATH, &ifp_domain.vtable },
     { NULL, NULL },
 };
 
-- 
1.7.11.7

