>From 4e777f67ac28e7cf0c9e8c989508aa57bf712b32 Mon Sep 17 00:00:00 2001
From: Stef Walter <stefw@redhat.com>
Date: Fri, 10 Jan 2014 08:58:12 +0100
Subject: [PATCH 4/6] sbus: Rework sbus to use interface metadata and vtables

Previous commits added support for interface metadata and
handler vtables. This commit ports sbus_dbus_connection to
use them.

Port the internal uses of dbus to use the new scheme in a
very minimal way. Further cleanup is possible here.

This commit provides basic definitions of the internal
dbus interfaces. The interfaces aren't fully defined, as the
handlers will continue to unpack manually, and often overload
DBus methods with different arguments (which is rather
unorthodox, but not the end of the world).
---
 Makefile.am                                   | 30 +++++++--
 src/monitor/monitor.c                         | 12 ++--
 src/monitor/monitor_iface.xml                 | 41 ++++++++++++
 src/monitor/monitor_iface_generated.c         | 92 +++++++++++++++++++++++++++
 src/monitor/monitor_iface_generated.h         | 56 ++++++++++++++++
 src/monitor/monitor_interfaces.h              |  2 +
 src/providers/data_provider.h                 |  1 +
 src/providers/data_provider_be.c              | 43 ++++++-------
 src/providers/data_provider_iface.xml         | 38 +++++++++++
 src/providers/data_provider_iface_generated.c | 86 +++++++++++++++++++++++++
 src/providers/data_provider_iface_generated.h | 55 ++++++++++++++++
 src/providers/proxy/proxy_child.c             | 16 +++--
 src/providers/proxy/proxy_init.c              | 16 +++--
 src/responder/autofs/autofssrv.c              | 35 ++++++----
 src/responder/nss/nsssrv.c                    | 33 +++++-----
 src/responder/pac/pacsrv.c                    | 34 ++++++----
 src/responder/pam/pamsrv.c                    | 34 ++++++----
 src/responder/ssh/sshsrv.c                    | 34 ++++++----
 src/responder/sudo/sudosrv.c                  | 34 ++++++----
 src/sbus/sssd_dbus.h                          | 11 +---
 src/sbus/sssd_dbus_connection.c               | 67 +++++++++++--------
 21 files changed, 606 insertions(+), 164 deletions(-)
 create mode 100644 src/monitor/monitor_iface.xml
 create mode 100644 src/monitor/monitor_iface_generated.c
 create mode 100644 src/monitor/monitor_iface_generated.h
 create mode 100644 src/providers/data_provider_iface.xml
 create mode 100644 src/providers/data_provider_iface_generated.c
 create mode 100644 src/providers/data_provider_iface_generated.h

diff --git a/Makefile.am b/Makefile.am
index 9842a3d..35db35a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -325,7 +325,11 @@ SSSD_RESPONDER_OBJ = \
     src/responder/common/responder_common.c \
     src/responder/common/responder_dp.c \
     src/responder/common/responder_packet.c \
-    src/responder/common/responder_get_domains.c
+    src/responder/common/responder_get_domains.c \
+    src/monitor/monitor_iface_generated.c \
+    src/monitor/monitor_iface_generated.h \
+    src/providers/data_provider_iface_generated.c \
+    src/providers/data_provider_iface_generated.h
 
 SSSD_TOOLS_OBJ = \
     src/tools/sss_sync_ops.c \
@@ -667,7 +671,9 @@ include_HEADERS = \
 # Yes, the goal here is that the generated files end up in $(srcdir)
 # not $(builddir). Always use $(srcdir) here.
 CODEGEN_XML = \
-    $(srcdir)/src/tests/sbus_codegen_tests.xml
+    $(srcdir)/src/tests/sbus_codegen_tests.xml \
+    $(srcdir)/src/monitor/monitor_iface.xml \
+    $(srcdir)/src/providers/data_provider_iface.xml
 
 SBUS_CODEGEN = src/sbus/sbus_codegen
 
@@ -698,7 +704,9 @@ sssd_SOURCES = \
     src/monitor/monitor.c \
     src/monitor/monitor_netlink.c \
     src/confdb/confdb_setup.c \
-    src/util/nscd.c
+    src/util/nscd.c \
+    src/monitor/monitor_iface_generated.c \
+    src/monitor/monitor_iface_generated.h
 sssd_LDADD = \
     $(SSSD_LIBS) \
     $(INOTIFY_LIBS) \
@@ -791,6 +799,10 @@ sssd_be_SOURCES = \
     src/providers/dp_dyndns.c \
     src/providers/dp_ptask.c \
     src/providers/dp_refresh.c \
+    src/monitor/monitor_iface_generated.c \
+    src/monitor/monitor_iface_generated.h \
+    src/providers/data_provider_iface_generated.c \
+    src/providers/data_provider_iface_generated.h \
     $(SSSD_FAILOVER_OBJ)
 sssd_be_LDADD = \
     $(LIBADD_DL) \
@@ -1200,6 +1212,10 @@ simple_access_tests_SOURCES = \
     src/providers/data_provider_callbacks.c \
     src/providers/dp_ptask.c \
     src/providers/dp_refresh.c \
+    src/monitor/monitor_iface_generated.c \
+    src/monitor/monitor_iface_generated.h \
+    src/providers/data_provider_iface_generated.c \
+    src/providers/data_provider_iface_generated.h \
     $(SSSD_FAILOVER_OBJ)
 simple_access_tests_CFLAGS = \
     $(AM_CFLAGS) \
@@ -1787,7 +1803,9 @@ libsss_proxy_la_SOURCES = \
     src/providers/proxy/proxy_id.c \
     src/providers/proxy/proxy_netgroup.c \
     src/providers/proxy/proxy_services.c \
-    src/providers/proxy/proxy_auth.c
+    src/providers/proxy/proxy_auth.c \
+    src/providers/data_provider_iface_generated.c \
+    src/providers/data_provider_iface_generated.h
 libsss_proxy_la_CFLAGS = \
     $(AM_CFLAGS)
 libsss_proxy_la_LIBADD = \
@@ -1982,7 +2000,9 @@ ldap_child_LDADD = \
     $(KRB5_LIBS)
 
 proxy_child_SOURCES = \
-    src/providers/proxy/proxy_child.c
+    src/providers/proxy/proxy_child.c \
+    src/providers/data_provider_iface_generated.c \
+    src/providers/data_provider_iface_generated.h
 proxy_child_CFLAGS = \
     $(AM_CFLAGS) \
     $(POPT_CFLAGS)
diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
index 8a0844b..c2e5a5a 100644
--- a/src/monitor/monitor.c
+++ b/src/monitor/monitor.c
@@ -523,17 +523,15 @@ static int add_services_startup_timeout(struct mt_ctx *ctx)
     return EOK;
 }
 
-struct sbus_method monitor_methods[] = {
-    { MON_SRV_METHOD_VERSION, get_monitor_version },
-    { MON_SRV_METHOD_REGISTER, client_registration },
-    { NULL, NULL }
+struct mon_srv_iface monitor_methods = {
+    { &mon_srv_iface_meta, 0 },
+    .getVersion = get_monitor_version,
+    .RegisterService = client_registration,
 };
 
 struct sbus_interface monitor_server_interface = {
-    MON_SRV_INTERFACE,
     MON_SRV_PATH,
-    SBUS_DEFAULT_VTABLE,
-    monitor_methods,
+    &monitor_methods.vtable,
     NULL
 };
 
diff --git a/src/monitor/monitor_iface.xml b/src/monitor/monitor_iface.xml
new file mode 100644
index 0000000..506b749
--- /dev/null
+++ b/src/monitor/monitor_iface.xml
@@ -0,0 +1,41 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+    <interface name="org.freedesktop.sssd.monitor">
+        <annotation value="mon_srv_iface" name="org.freedesktop.DBus.GLib.CSymbol"/>
+        <method name="getVersion">
+            <!-- manual argument parsing -->
+        </method>
+        <method name="RegisterService">
+            <!-- manual argument parsing -->
+        </method>
+    </interface>
+
+    <interface name="org.freedesktop.sssd.service">
+        <annotation value="mon_cli_iface" name="org.freedesktop.DBus.GLib.CSymbol"/>
+        <method name="ping">
+            <!-- no arguments -->
+        </method>
+        <method name="resInit">
+            <!-- no arguments -->
+        </method>
+        <method name="shutDown">
+            <!-- no arguments -->
+        </method>
+        <method name="goOffline">
+            <!-- no arguments -->
+        </method>
+        <method name="resetOffline">
+            <!-- no arguments -->
+        </method>
+        <method name="rotateLogs">
+            <!-- no arguments -->
+        </method>
+        <method name="clearMemcache">
+            <!-- no arguments -->
+        </method>
+        <method name="clearEnumCache">
+            <!-- no arguments -->
+        </method>
+    </interface>
+</node>
diff --git a/src/monitor/monitor_iface_generated.c b/src/monitor/monitor_iface_generated.c
new file mode 100644
index 0000000..81a7c24
--- /dev/null
+++ b/src/monitor/monitor_iface_generated.c
@@ -0,0 +1,92 @@
+/* The following definitions are auto-generated from monitor_iface.xml */
+
+#include "util/util.h"
+#include "sbus/sssd_dbus.h"
+#include "sbus/sssd_dbus_meta.h"
+#include "monitor_iface_generated.h"
+
+/* methods for org.freedesktop.sssd.monitor */
+const struct sbus_method_meta mon_srv_iface__methods[] = {
+    {
+        "getVersion", /* name */
+        NULL, /* no in_args */
+        NULL, /* no out_args */
+        offsetof(struct mon_srv_iface, getVersion),
+    },
+    {
+        "RegisterService", /* name */
+        NULL, /* no in_args */
+        NULL, /* no out_args */
+        offsetof(struct mon_srv_iface, RegisterService),
+    },
+    { NULL, }
+};
+
+/* 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 */
+};
+
+/* methods for org.freedesktop.sssd.service */
+const struct sbus_method_meta mon_cli_iface__methods[] = {
+    {
+        "ping", /* name */
+        NULL, /* no in_args */
+        NULL, /* no out_args */
+        offsetof(struct mon_cli_iface, ping),
+    },
+    {
+        "resInit", /* name */
+        NULL, /* no in_args */
+        NULL, /* no out_args */
+        offsetof(struct mon_cli_iface, resInit),
+    },
+    {
+        "shutDown", /* name */
+        NULL, /* no in_args */
+        NULL, /* no out_args */
+        offsetof(struct mon_cli_iface, shutDown),
+    },
+    {
+        "goOffline", /* name */
+        NULL, /* no in_args */
+        NULL, /* no out_args */
+        offsetof(struct mon_cli_iface, goOffline),
+    },
+    {
+        "resetOffline", /* name */
+        NULL, /* no in_args */
+        NULL, /* no out_args */
+        offsetof(struct mon_cli_iface, resetOffline),
+    },
+    {
+        "rotateLogs", /* name */
+        NULL, /* no in_args */
+        NULL, /* no out_args */
+        offsetof(struct mon_cli_iface, rotateLogs),
+    },
+    {
+        "clearMemcache", /* name */
+        NULL, /* no in_args */
+        NULL, /* no out_args */
+        offsetof(struct mon_cli_iface, clearMemcache),
+    },
+    {
+        "clearEnumCache", /* name */
+        NULL, /* no in_args */
+        NULL, /* no out_args */
+        offsetof(struct mon_cli_iface, clearEnumCache),
+    },
+    { NULL, }
+};
+
+/* 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 */
+};
diff --git a/src/monitor/monitor_iface_generated.h b/src/monitor/monitor_iface_generated.h
new file mode 100644
index 0000000..cde7749
--- /dev/null
+++ b/src/monitor/monitor_iface_generated.h
@@ -0,0 +1,56 @@
+/* The following declarations are auto-generated from monitor_iface.xml */
+
+#ifndef __MONITOR_IFACE_XML__
+#define __MONITOR_IFACE_XML__
+
+#include "sbus/sssd_dbus.h"
+
+/* ------------------------------------------------------------------------
+ * DBus Vtable handler structures
+ *
+ * These structures are filled in by implementors of the different
+ * dbus interfaces to handle method calls.
+ *
+ * Handler functions of type sbus_msg_handler_fn accept raw messages,
+ * other handlers will be typed appropriately. If a handler that is
+ * set to NULL is invoked it will result in a
+ * org.freedesktop.DBus.Error.NotSupported error for the caller.
+ */
+
+/* vtable for org.freedesktop.sssd.monitor */
+struct mon_srv_iface {
+    struct sbus_vtable vtable; /* derive from sbus_vtable */
+    sbus_msg_handler_fn getVersion;
+    sbus_msg_handler_fn RegisterService;
+};
+
+/* vtable for org.freedesktop.sssd.service */
+struct mon_cli_iface {
+    struct sbus_vtable vtable; /* derive from sbus_vtable */
+    sbus_msg_handler_fn ping;
+    sbus_msg_handler_fn resInit;
+    sbus_msg_handler_fn shutDown;
+    sbus_msg_handler_fn goOffline;
+    sbus_msg_handler_fn resetOffline;
+    sbus_msg_handler_fn rotateLogs;
+    sbus_msg_handler_fn clearMemcache;
+    sbus_msg_handler_fn clearEnumCache;
+};
+
+/* ------------------------------------------------------------------------
+ * DBus Interface Metadata
+ *
+ * These structure definitions are filled in with the information about
+ * the interfaces, methods, properties and so on.
+ *
+ * The actual definitions are found in the accompanying C file next
+ * to this header.
+ */
+
+/* interface info for org.freedesktop.sssd.monitor */
+extern const struct sbus_interface_meta mon_srv_iface_meta;
+
+/* interface info for org.freedesktop.sssd.service */
+extern const struct sbus_interface_meta mon_cli_iface_meta;
+
+#endif /* __MONITOR_IFACE_XML__ */
diff --git a/src/monitor/monitor_interfaces.h b/src/monitor/monitor_interfaces.h
index f27c7d0..308642f 100644
--- a/src/monitor/monitor_interfaces.h
+++ b/src/monitor/monitor_interfaces.h
@@ -21,6 +21,8 @@
 
 #include "sbus/sssd_dbus.h"
 
+#include "monitor/monitor_iface_generated.h"
+
 /*** Monitor ***/
 
 #define MONITOR_VERSION 0x0001
diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h
index c33445c..7149830 100644
--- a/src/providers/data_provider.h
+++ b/src/providers/data_provider.h
@@ -43,6 +43,7 @@
 #include "sbus/sbus_client.h"
 #include "sss_client/sss_cli.h"
 #include "util/authtok.h"
+#include "providers/data_provider_iface_generated.h"
 
 #define DATA_PROVIDER_VERSION 0x0001
 #define DATA_PROVIDER_PIPE "private/sbus-dp"
diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
index 2e64226..67d5210 100644
--- a/src/providers/data_provider_be.c
+++ b/src/providers/data_provider_be.c
@@ -63,20 +63,21 @@ static int data_provider_reset_offline(DBusMessage *message,
 static int data_provider_logrotate(DBusMessage *message,
                                 struct sbus_connection *conn);
 
-struct sbus_method monitor_be_methods[] = {
-    { MON_CLI_METHOD_PING, monitor_common_pong },
-    { MON_CLI_METHOD_RES_INIT, data_provider_res_init },
-    { MON_CLI_METHOD_OFFLINE, data_provider_go_offline },
-    { MON_CLI_METHOD_RESET_OFFLINE, data_provider_reset_offline },
-    { MON_CLI_METHOD_ROTATE, data_provider_logrotate },
-    { NULL, NULL }
+struct mon_cli_iface monitor_be_methods = {
+    { &mon_cli_iface_meta, 0 },
+    .ping = monitor_common_pong,
+    .resInit = data_provider_res_init,
+    .shutDown = NULL,
+    .goOffline = data_provider_go_offline,
+    .resetOffline = data_provider_reset_offline,
+    .rotateLogs = data_provider_logrotate,
+    .clearMemcache = NULL,
+    .clearEnumCache = NULL,
 };
 
 struct sbus_interface monitor_be_interface = {
-    MONITOR_INTERFACE,
     MONITOR_PATH,
-    SBUS_DEFAULT_VTABLE,
-    monitor_be_methods,
+    &monitor_be_methods.vtable,
     NULL
 };
 
@@ -88,22 +89,20 @@ static int be_autofs_handler(DBusMessage *message, struct sbus_connection *conn)
 static int be_host_handler(DBusMessage *message, struct sbus_connection *conn);
 static int be_get_subdomains(DBusMessage *message, struct sbus_connection *conn);
 
-struct sbus_method be_methods[] = {
-    { DP_METHOD_REGISTER, client_registration },
-    { DP_METHOD_GETACCTINFO, be_get_account_info },
-    { DP_METHOD_PAMHANDLER, be_pam_handler },
-    { DP_METHOD_SUDOHANDLER, be_sudo_handler },
-    { DP_METHOD_AUTOFSHANDLER, be_autofs_handler },
-    { DP_METHOD_HOSTHANDLER, be_host_handler },
-    { DP_METHOD_GETDOMAINS, be_get_subdomains },
-    { NULL, NULL }
+struct data_provider_iface be_methods = {
+    { &data_provider_iface_meta, 0 },
+    .RegisterService = client_registration,
+    .pamHandler = be_pam_handler,
+    .sudoHandler = be_sudo_handler,
+    .autofsHandler = be_autofs_handler,
+    .hostHandler = be_host_handler,
+    .getDomains = be_get_subdomains,
+    .getAccountInfo = be_get_account_info,
 };
 
 struct sbus_interface be_interface = {
-    DP_INTERFACE,
     DP_PATH,
-    SBUS_DEFAULT_VTABLE,
-    be_methods,
+    &be_methods.vtable,
     NULL
 };
 
diff --git a/src/providers/data_provider_iface.xml b/src/providers/data_provider_iface.xml
new file mode 100644
index 0000000..1f34964
--- /dev/null
+++ b/src/providers/data_provider_iface.xml
@@ -0,0 +1,38 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+    <interface name="org.freedesktop.sssd.dataprovider">
+        <annotation value="data_provider_iface" name="org.freedesktop.DBus.GLib.CSymbol"/>
+        <method name="RegisterService">
+            <!-- arguments parsed manually -->
+        </method>
+        <method name="pamHandler">
+            <!-- arguments parsed manually -->
+        </method>
+        <method name="sudoHandler">
+            <!-- arguments parsed manually -->
+        </method>
+        <method name="autofsHandler">
+            <!-- arguments parsed manually -->
+        </method>
+        <method name="hostHandler">
+            <!-- arguments parsed manually -->
+        </method>
+        <method name="getDomains">
+            <!-- arguments parsed manually -->
+        </method>
+        <method name="getAccountInfo">
+            <!-- arguments parsed manually -->
+        </method>
+    </interface>
+
+    <interface name="org.freedesktop.sssd.dataprovider_rev">
+        <annotation value="data_provider_rev_iface" name="org.freedesktop.DBus.GLib.CSymbol"/>
+        <method name="updateCache">
+            <!-- manual argument parsing -->
+        </method>
+        <method name="initgrCheck">
+            <!-- manual argument parsing -->
+        </method>
+    </interface>
+</node>
diff --git a/src/providers/data_provider_iface_generated.c b/src/providers/data_provider_iface_generated.c
new file mode 100644
index 0000000..517b7ad
--- /dev/null
+++ b/src/providers/data_provider_iface_generated.c
@@ -0,0 +1,86 @@
+/* The following definitions are auto-generated from data_provider_iface.xml */
+
+#include "util/util.h"
+#include "sbus/sssd_dbus.h"
+#include "sbus/sssd_dbus_meta.h"
+#include "data_provider_iface_generated.h"
+
+/* methods for org.freedesktop.sssd.dataprovider */
+const struct sbus_method_meta data_provider_iface__methods[] = {
+    {
+        "RegisterService", /* name */
+        NULL, /* no in_args */
+        NULL, /* no out_args */
+        offsetof(struct data_provider_iface, RegisterService),
+    },
+    {
+        "pamHandler", /* name */
+        NULL, /* no in_args */
+        NULL, /* no out_args */
+        offsetof(struct data_provider_iface, pamHandler),
+    },
+    {
+        "sudoHandler", /* name */
+        NULL, /* no in_args */
+        NULL, /* no out_args */
+        offsetof(struct data_provider_iface, sudoHandler),
+    },
+    {
+        "autofsHandler", /* name */
+        NULL, /* no in_args */
+        NULL, /* no out_args */
+        offsetof(struct data_provider_iface, autofsHandler),
+    },
+    {
+        "hostHandler", /* name */
+        NULL, /* no in_args */
+        NULL, /* no out_args */
+        offsetof(struct data_provider_iface, hostHandler),
+    },
+    {
+        "getDomains", /* name */
+        NULL, /* no in_args */
+        NULL, /* no out_args */
+        offsetof(struct data_provider_iface, getDomains),
+    },
+    {
+        "getAccountInfo", /* name */
+        NULL, /* no in_args */
+        NULL, /* no out_args */
+        offsetof(struct data_provider_iface, getAccountInfo),
+    },
+    { NULL, }
+};
+
+/* 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 */
+};
+
+/* methods for org.freedesktop.sssd.dataprovider_rev */
+const struct sbus_method_meta data_provider_rev_iface__methods[] = {
+    {
+        "updateCache", /* name */
+        NULL, /* no in_args */
+        NULL, /* no out_args */
+        offsetof(struct data_provider_rev_iface, updateCache),
+    },
+    {
+        "initgrCheck", /* name */
+        NULL, /* no in_args */
+        NULL, /* no out_args */
+        offsetof(struct data_provider_rev_iface, initgrCheck),
+    },
+    { NULL, }
+};
+
+/* 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 */
+};
diff --git a/src/providers/data_provider_iface_generated.h b/src/providers/data_provider_iface_generated.h
new file mode 100644
index 0000000..0851964
--- /dev/null
+++ b/src/providers/data_provider_iface_generated.h
@@ -0,0 +1,55 @@
+/* The following declarations are auto-generated from data_provider_iface.xml */
+
+#ifndef __DATA_PROVIDER_IFACE_XML__
+#define __DATA_PROVIDER_IFACE_XML__
+
+#include "sbus/sssd_dbus.h"
+
+/* ------------------------------------------------------------------------
+ * DBus Vtable handler structures
+ *
+ * These structures are filled in by implementors of the different
+ * dbus interfaces to handle method calls.
+ *
+ * Handler functions of type sbus_msg_handler_fn accept raw messages,
+ * other handlers will be typed appropriately. If a handler that is
+ * set to NULL is invoked it will result in a
+ * org.freedesktop.DBus.Error.NotSupported error for the caller.
+ */
+
+/* vtable for org.freedesktop.sssd.dataprovider */
+struct data_provider_iface {
+    struct sbus_vtable vtable; /* derive from sbus_vtable */
+    sbus_msg_handler_fn RegisterService;
+    sbus_msg_handler_fn pamHandler;
+    sbus_msg_handler_fn sudoHandler;
+    sbus_msg_handler_fn autofsHandler;
+    sbus_msg_handler_fn hostHandler;
+    sbus_msg_handler_fn getDomains;
+    sbus_msg_handler_fn getAccountInfo;
+};
+
+/* vtable for org.freedesktop.sssd.dataprovider_rev */
+struct data_provider_rev_iface {
+    struct sbus_vtable vtable; /* derive from sbus_vtable */
+    sbus_msg_handler_fn updateCache;
+    sbus_msg_handler_fn initgrCheck;
+};
+
+/* ------------------------------------------------------------------------
+ * DBus Interface Metadata
+ *
+ * These structure definitions are filled in with the information about
+ * the interfaces, methods, properties and so on.
+ *
+ * The actual definitions are found in the accompanying C file next
+ * to this header.
+ */
+
+/* interface info for org.freedesktop.sssd.dataprovider */
+extern const struct sbus_interface_meta data_provider_iface_meta;
+
+/* interface info for org.freedesktop.sssd.dataprovider_rev */
+extern const struct sbus_interface_meta data_provider_rev_iface_meta;
+
+#endif /* __DATA_PROVIDER_IFACE_XML__ */
diff --git a/src/providers/proxy/proxy_child.c b/src/providers/proxy/proxy_child.c
index 5296865..737b0cf 100644
--- a/src/providers/proxy/proxy_child.c
+++ b/src/providers/proxy/proxy_child.c
@@ -49,16 +49,20 @@
 
 static int pc_pam_handler(DBusMessage *message, struct sbus_connection *conn);
 
-struct sbus_method pc_methods[] = {
-    { DP_METHOD_PAMHANDLER, pc_pam_handler },
-    { NULL, NULL }
+struct data_provider_iface pc_methods = {
+    { &data_provider_iface_meta, 0 },
+    .RegisterService = NULL,
+    .pamHandler = pc_pam_handler,
+    .sudoHandler = NULL,
+    .autofsHandler = NULL,
+    .hostHandler = NULL,
+    .getDomains = NULL,
+    .getAccountInfo = NULL,
 };
 
 struct sbus_interface pc_interface = {
-    DP_INTERFACE,
     DP_PATH,
-    SBUS_DEFAULT_VTABLE,
-    pc_methods,
+    &pc_methods.vtable,
     NULL
 };
 
diff --git a/src/providers/proxy/proxy_init.c b/src/providers/proxy/proxy_init.c
index ae73fe7..60ae4a9 100644
--- a/src/providers/proxy/proxy_init.c
+++ b/src/providers/proxy/proxy_init.c
@@ -30,16 +30,20 @@
 static int client_registration(DBusMessage *message,
                                struct sbus_connection *conn);
 
-static struct sbus_method proxy_methods[] = {
-    { DP_METHOD_REGISTER, client_registration },
-    { NULL, NULL }
+static struct data_provider_iface proxy_methods = {
+    { &data_provider_iface_meta, 0 },
+    .RegisterService = client_registration,
+    .pamHandler = NULL,
+    .sudoHandler = NULL,
+    .autofsHandler = NULL,
+    .hostHandler = NULL,
+    .getDomains = NULL,
+    .getAccountInfo = NULL,
 };
 
 struct sbus_interface proxy_interface = {
-    DP_INTERFACE,
     DP_PATH,
-    SBUS_DEFAULT_VTABLE,
-    proxy_methods,
+    &proxy_methods.vtable,
     NULL
 };
 
diff --git a/src/responder/autofs/autofssrv.c b/src/responder/autofs/autofssrv.c
index 12f318e..5ce9ae0 100644
--- a/src/responder/autofs/autofssrv.c
+++ b/src/responder/autofs/autofssrv.c
@@ -32,31 +32,38 @@
 static int autofs_clean_hash_table(DBusMessage *message,
                                    struct sbus_connection *conn);
 
-struct sbus_method monitor_autofs_methods[] = {
-    { MON_CLI_METHOD_PING, monitor_common_pong },
-    { MON_CLI_METHOD_RES_INIT, monitor_common_res_init },
-    { MON_CLI_METHOD_ROTATE, responder_logrotate },
-    { MON_CLI_METHOD_CLEAR_ENUM_CACHE, autofs_clean_hash_table },
-    { NULL, NULL }
+struct mon_cli_iface monitor_autofs_methods = {
+    { &mon_cli_iface_meta, 0 },
+    .ping = monitor_common_pong,
+    .resInit = monitor_common_res_init,
+    .shutDown = NULL,
+    .goOffline = NULL,
+    .resetOffline = NULL,
+    .rotateLogs = responder_logrotate,
+    .clearMemcache = NULL,
+    .clearEnumCache = autofs_clean_hash_table,
 };
 
 struct sbus_interface monitor_autofs_interface = {
-    MONITOR_INTERFACE,
     MONITOR_PATH,
-    SBUS_DEFAULT_VTABLE,
-    monitor_autofs_methods,
+    &monitor_autofs_methods.vtable,
     NULL
 };
 
-static struct sbus_method autofs_dp_methods[] = {
-    { NULL, NULL }
+static struct data_provider_iface autofs_dp_methods = {
+    { &data_provider_iface_meta, 0 },
+    .RegisterService = NULL,
+    .pamHandler = NULL,
+    .sudoHandler = NULL,
+    .autofsHandler = NULL,
+    .hostHandler = NULL,
+    .getDomains = NULL,
+    .getAccountInfo = NULL,
 };
 
 struct sbus_interface autofs_dp_interface = {
-    DP_INTERFACE,
     DP_PATH,
-    SBUS_DEFAULT_VTABLE,
-    autofs_dp_methods,
+    &autofs_dp_methods.vtable,
     NULL
 };
 
diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c
index d258dfc..a385f29 100644
--- a/src/responder/nss/nsssrv.c
+++ b/src/responder/nss/nsssrv.c
@@ -60,20 +60,21 @@ static int nss_clear_memcache(DBusMessage *message,
 static int nss_clear_netgroup_hash_table(DBusMessage *message,
                                          struct sbus_connection *conn);
 
-struct sbus_method monitor_nss_methods[] = {
-    { MON_CLI_METHOD_PING, monitor_common_pong },
-    { MON_CLI_METHOD_RES_INIT, monitor_common_res_init },
-    { MON_CLI_METHOD_ROTATE, responder_logrotate },
-    { MON_CLI_METHOD_CLEAR_MEMCACHE, nss_clear_memcache},
-    { MON_CLI_METHOD_CLEAR_ENUM_CACHE, nss_clear_netgroup_hash_table},
-    { NULL, NULL }
+struct mon_cli_iface monitor_nss_methods = {
+    { &mon_cli_iface_meta, 0 },
+    .ping = monitor_common_pong,
+    .resInit = monitor_common_res_init,
+    .shutDown = NULL,
+    .goOffline = NULL,
+    .resetOffline = NULL,
+    .rotateLogs = responder_logrotate,
+    .clearMemcache = nss_clear_memcache,
+    .clearEnumCache = nss_clear_netgroup_hash_table
 };
 
 struct sbus_interface monitor_nss_interface = {
-    MONITOR_INTERFACE,
     MONITOR_PATH,
-    SBUS_DEFAULT_VTABLE,
-    monitor_nss_methods,
+    &monitor_nss_methods.vtable,
     NULL
 };
 
@@ -372,17 +373,15 @@ static int nss_memcache_initgr_check(DBusMessage *message,
     return EOK;
 }
 
-static struct sbus_method nss_dp_methods[] = {
-    { DP_REV_METHOD_UPDATE_CACHE, nss_update_memcache },
-    { DP_REV_METHOD_INITGR_CHECK, nss_memcache_initgr_check },
-    { NULL, NULL }
+static struct data_provider_rev_iface nss_dp_methods = {
+    { &data_provider_rev_iface_meta, 0 },
+    .updateCache = nss_update_memcache,
+    .initgrCheck = nss_memcache_initgr_check
 };
 
 struct sbus_interface nss_dp_interface = {
-    DP_REV_INTERFACE,
     DP_PATH,
-    SBUS_DEFAULT_VTABLE,
-    nss_dp_methods,
+    &nss_dp_methods.vtable,
     NULL
 };
 
diff --git a/src/responder/pac/pacsrv.c b/src/responder/pac/pacsrv.c
index 2fb9429..04a6200 100644
--- a/src/responder/pac/pacsrv.c
+++ b/src/responder/pac/pacsrv.c
@@ -48,30 +48,38 @@
 #define DEFAULT_PAC_FD_LIMIT 8192
 #define DEFAULT_ALLOWED_UIDS "0"
 
-struct sbus_method monitor_pac_methods[] = {
-    { MON_CLI_METHOD_PING, monitor_common_pong },
-    { MON_CLI_METHOD_RES_INIT, monitor_common_res_init },
-    { MON_CLI_METHOD_ROTATE, responder_logrotate },
-    { NULL, NULL }
+struct mon_cli_iface monitor_pac_methods = {
+    { &mon_cli_iface_meta, 0 },
+    .ping = monitor_common_pong,
+    .resInit = monitor_common_res_init,
+    .shutDown = NULL,
+    .goOffline = NULL,
+    .resetOffline = NULL,
+    .rotateLogs = responder_logrotate,
+    .clearMemcache = NULL,
+    .clearEnumCache = NULL,
 };
 
 struct sbus_interface monitor_pac_interface = {
-    MONITOR_INTERFACE,
     MONITOR_PATH,
-    SBUS_DEFAULT_VTABLE,
-    monitor_pac_methods,
+    &monitor_pac_methods.vtable,
     NULL
 };
 
-static struct sbus_method pac_dp_methods[] = {
-    { NULL, NULL }
+static struct data_provider_iface pac_dp_methods = {
+    { &data_provider_iface_meta, 0 },
+    .RegisterService = NULL,
+    .pamHandler = NULL,
+    .sudoHandler = NULL,
+    .autofsHandler = NULL,
+    .hostHandler = NULL,
+    .getDomains = NULL,
+    .getAccountInfo = NULL,
 };
 
 struct sbus_interface pac_dp_interface = {
-    DP_INTERFACE,
     DP_PATH,
-    SBUS_DEFAULT_VTABLE,
-    pac_dp_methods,
+    &pac_dp_methods.vtable,
     NULL
 };
 
diff --git a/src/responder/pam/pamsrv.c b/src/responder/pam/pamsrv.c
index 5f9844e..1fc9f62 100644
--- a/src/responder/pam/pamsrv.c
+++ b/src/responder/pam/pamsrv.c
@@ -47,30 +47,38 @@
 
 #define DEFAULT_PAM_FD_LIMIT 8192
 
-struct sbus_method monitor_pam_methods[] = {
-    { MON_CLI_METHOD_PING, monitor_common_pong },
-    { MON_CLI_METHOD_RES_INIT, monitor_common_res_init },
-    { MON_CLI_METHOD_ROTATE, responder_logrotate },
-    { NULL, NULL }
+struct mon_cli_iface monitor_pam_methods = {
+    { &mon_cli_iface_meta, 0 },
+    .ping = monitor_common_pong,
+    .resInit = monitor_common_res_init,
+    .shutDown = NULL,
+    .goOffline = NULL,
+    .resetOffline = NULL,
+    .rotateLogs = responder_logrotate,
+    .clearMemcache = NULL,
+    .clearEnumCache = NULL,
 };
 
 struct sbus_interface monitor_pam_interface = {
-    MONITOR_INTERFACE,
     MONITOR_PATH,
-    SBUS_DEFAULT_VTABLE,
-    monitor_pam_methods,
+    &monitor_pam_methods.vtable,
     NULL
 };
 
-static struct sbus_method pam_dp_methods[] = {
-        { NULL, NULL }
+static struct data_provider_iface pam_dp_methods = {
+    { &data_provider_iface_meta, 0 },
+    .RegisterService = NULL,
+    .pamHandler = NULL,
+    .sudoHandler = NULL,
+    .autofsHandler = NULL,
+    .hostHandler = NULL,
+    .getDomains = NULL,
+    .getAccountInfo = NULL,
 };
 
 struct sbus_interface pam_dp_interface = {
-    DP_INTERFACE,
     DP_PATH,
-    SBUS_DEFAULT_VTABLE,
-    pam_dp_methods,
+    &pam_dp_methods.vtable,
     NULL
 };
 
diff --git a/src/responder/ssh/sshsrv.c b/src/responder/ssh/sshsrv.c
index ea943af..fb0738f 100644
--- a/src/responder/ssh/sshsrv.c
+++ b/src/responder/ssh/sshsrv.c
@@ -28,30 +28,38 @@
 #include "responder/ssh/sshsrv_private.h"
 #include "providers/data_provider.h"
 
-struct sbus_method monitor_ssh_methods[] = {
-    { MON_CLI_METHOD_PING, monitor_common_pong },
-    { MON_CLI_METHOD_RES_INIT, monitor_common_res_init },
-    { MON_CLI_METHOD_ROTATE, responder_logrotate },
-    { NULL, NULL }
+struct mon_cli_iface monitor_ssh_methods = {
+    { &mon_cli_iface_meta, 0 },
+    .ping = monitor_common_pong,
+    .resInit = monitor_common_res_init,
+    .shutDown = NULL,
+    .goOffline = NULL,
+    .resetOffline = NULL,
+    .rotateLogs = responder_logrotate,
+    .clearMemcache = NULL,
+    .clearEnumCache = NULL,
 };
 
 struct sbus_interface monitor_ssh_interface = {
-    MONITOR_INTERFACE,
     MONITOR_PATH,
-    SBUS_DEFAULT_VTABLE,
-    monitor_ssh_methods,
+    &monitor_ssh_methods.vtable,
     NULL
 };
 
-static struct sbus_method ssh_dp_methods[] = {
-    { NULL, NULL }
+static struct data_provider_iface ssh_dp_methods = {
+    { &data_provider_iface_meta, 0 },
+    .RegisterService = NULL,
+    .pamHandler = NULL,
+    .sudoHandler = NULL,
+    .autofsHandler = NULL,
+    .hostHandler = NULL,
+    .getDomains = NULL,
+    .getAccountInfo = NULL,
 };
 
 struct sbus_interface ssh_dp_interface = {
-    DP_INTERFACE,
     DP_PATH,
-    SBUS_DEFAULT_VTABLE,
-    ssh_dp_methods,
+    &ssh_dp_methods.vtable,
     NULL
 };
 
diff --git a/src/responder/sudo/sudosrv.c b/src/responder/sudo/sudosrv.c
index b821c96..1ad260b 100644
--- a/src/responder/sudo/sudosrv.c
+++ b/src/responder/sudo/sudosrv.c
@@ -28,30 +28,38 @@
 #include "responder/sudo/sudosrv_private.h"
 #include "providers/data_provider.h"
 
-struct sbus_method monitor_sudo_methods[] = {
-    { MON_CLI_METHOD_PING, monitor_common_pong },
-    { MON_CLI_METHOD_RES_INIT, monitor_common_res_init },
-    { MON_CLI_METHOD_ROTATE, responder_logrotate },
-    { NULL, NULL }
+struct mon_cli_iface monitor_sudo_methods = {
+    { &mon_cli_iface_meta, 0 },
+    .ping = monitor_common_pong,
+    .resInit = monitor_common_res_init,
+    .shutDown = NULL,
+    .goOffline = NULL,
+    .resetOffline = NULL,
+    .rotateLogs = responder_logrotate,
+    .clearMemcache = NULL,
+    .clearEnumCache = NULL,
 };
 
 struct sbus_interface monitor_sudo_interface = {
-    MONITOR_INTERFACE,
     MONITOR_PATH,
-    SBUS_DEFAULT_VTABLE,
-    monitor_sudo_methods,
+    &monitor_sudo_methods.vtable,
     NULL
 };
 
-static struct sbus_method sudo_dp_methods[] = {
-    { NULL, NULL }
+static struct data_provider_iface sudo_dp_methods = {
+    { &data_provider_iface_meta, 0 },
+    .RegisterService = NULL,
+    .pamHandler = NULL,
+    .sudoHandler = NULL,
+    .autofsHandler = NULL,
+    .hostHandler = NULL,
+    .getDomains = NULL,
+    .getAccountInfo = NULL,
 };
 
 struct sbus_interface sudo_dp_interface = {
-    DP_INTERFACE,
     DP_PATH,
-    SBUS_DEFAULT_VTABLE,
-    sudo_dp_methods,
+    &sudo_dp_methods.vtable,
     NULL
 };
 
diff --git a/src/sbus/sssd_dbus.h b/src/sbus/sssd_dbus.h
index e9e7c98..7d00b94 100644
--- a/src/sbus/sssd_dbus.h
+++ b/src/sbus/sssd_dbus.h
@@ -74,18 +74,9 @@ struct sbus_vtable {
 #define DBUS_INTROSPECT_INTERFACE "org.freedesktop.DBus.Introspectable"
 #define DBUS_INTROSPECT_METHOD "Introspect"
 
-#define SBUS_DEFAULT_VTABLE { NULL, sbus_message_handler, NULL, NULL, NULL, NULL }
-
-struct sbus_method {
-    const char *method;
-    sbus_msg_handler_fn fn;
-};
-
 struct sbus_interface {
-    const char *interface;
     const char *path;
-    DBusObjectPathVTable vtable;
-    struct sbus_method *methods;
+    struct sbus_vtable *vtable;
     sbus_msg_handler_fn introspect_fn;
 };
 
diff --git a/src/sbus/sssd_dbus_connection.c b/src/sbus/sssd_dbus_connection.c
index eb07b8d..d39f1c0 100644
--- a/src/sbus/sssd_dbus_connection.c
+++ b/src/sbus/sssd_dbus_connection.c
@@ -25,10 +25,14 @@
 #include "util/util.h"
 #include "sbus/sssd_dbus.h"
 #include "sbus/sssd_dbus_private.h"
+#include "sbus/sssd_dbus_meta.h"
 
 /* Types */
 struct dbus_ctx_list;
 
+static DBusObjectPathVTable dbus_object_path_vtable =
+    { NULL, sbus_message_handler, NULL, NULL, NULL, NULL };
+
 struct sbus_interface_p {
     struct sbus_interface_p *prev, *next;
     struct sbus_connection *conn;
@@ -394,6 +398,10 @@ static int sbus_reply_internal_error(DBusMessage *message,
     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 }
 
+/* Looks up a vtable func, in a struct derived from struct sbus_vtable */
+#define VTABLE_FUNC(vtable, offset) \
+    (*((void **)((char *)(vtable) + (offset))))
+
 /* messsage_handler
  * Receive messages and process them
  */
@@ -402,24 +410,26 @@ DBusHandlerResult sbus_message_handler(DBusConnection *dbus_conn,
                                          void *user_data)
 {
     struct sbus_interface_p *intf_p;
-    const char *method;
+    const char *msg_method;
     const char *path;
     const char *msg_interface;
     DBusMessage *reply = NULL;
-    int i, ret;
-    int found;
+    const struct sbus_method_meta *method;
+    const struct sbus_interface_meta *interface;
+    sbus_msg_handler_fn handler_fn;
+    int ret;
 
     if (!user_data) {
         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
     }
     intf_p = talloc_get_type(user_data, struct sbus_interface_p);
 
-    method = dbus_message_get_member(message);
-    DEBUG(SSSDBG_TRACE_ALL, "Received SBUS method [%s]\n", method);
+    msg_method = dbus_message_get_member(message);
+    DEBUG(SSSDBG_TRACE_ALL, "Received SBUS method [%s]\n", msg_method);
     path = dbus_message_get_path(message);
     msg_interface = dbus_message_get_interface(message);
 
-    if (!method || !path || !msg_interface)
+    if (!msg_method || !path || !msg_interface)
         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 
     /* Validate the D-BUS path */
@@ -427,26 +437,33 @@ DBusHandlerResult sbus_message_handler(DBusConnection *dbus_conn,
         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 
     /* Validate the method interface */
-    if (strcmp(msg_interface, intf_p->intf->interface) == 0) {
-        found = 0;
-        for (i = 0; intf_p->intf->methods[i].method != NULL; i++) {
-            if (strcmp(method, intf_p->intf->methods[i].method) == 0) {
-                found = 1;
-                ret = intf_p->intf->methods[i].fn(message, intf_p->conn);
-                if (ret != EOK) {
-                    return sbus_reply_internal_error(message, intf_p->conn);
-                }
-                break;
-            }
-        }
-
-        if (!found) {
+    interface = intf_p->intf->vtable->meta;
+    if (strcmp(msg_interface, interface->name) == 0) {
+        handler_fn = NULL;
+        method = sbus_meta_find_method(interface, msg_method);
+        if (method && method->vtable_offset)
+            handler_fn = VTABLE_FUNC(intf_p->intf->vtable, method->vtable_offset);
+
+        if (!method) {
             /* Reply DBUS_ERROR_UNKNOWN_METHOD */
             DEBUG(SSSDBG_CRIT_FAILURE,
-                  "No matching method found for %s.\n", method);
+                  "No matching method found for %s.\n", msg_method);
             reply = dbus_message_new_error(message, DBUS_ERROR_UNKNOWN_METHOD, NULL);
             sbus_conn_send_reply(intf_p->conn, reply);
             dbus_message_unref(reply);
+
+        } else if (!handler_fn) {
+            /* Reply DBUS_ERROR_NOT_SUPPORTED */
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "No handler provided found for %s.\n", msg_method);
+            reply = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, NULL);
+            sbus_conn_send_reply(intf_p->conn, reply);
+            dbus_message_unref(reply);
+
+        } else {
+            ret = handler_fn(message, intf_p->conn);
+            if (ret != EOK)
+                return sbus_reply_internal_error(message, intf_p->conn);
         }
     }
     else {
@@ -454,7 +471,7 @@ DBusHandlerResult sbus_message_handler(DBusConnection *dbus_conn,
          * This is usually only useful for system bus connections
          */
         if (strcmp(msg_interface, DBUS_INTROSPECT_INTERFACE) == 0 &&
-            strcmp(method, DBUS_INTROSPECT_METHOD) == 0)
+            strcmp(msg_method, DBUS_INTROSPECT_METHOD) == 0)
         {
             if (intf_p->intf->introspect_fn) {
                 /* If we have been asked for introspection data and we have
@@ -483,7 +500,7 @@ int sbus_conn_add_interface(struct sbus_connection *conn,
     dbus_bool_t dbret;
     const char *path;
 
-    if (!conn || !intf || !intf->vtable.message_function) {
+    if (!conn || !intf || !intf->vtable || !intf->vtable->meta) {
         return EINVAL;
     }
 
@@ -505,7 +522,7 @@ int sbus_conn_add_interface(struct sbus_connection *conn,
     DLIST_ADD(conn->intf_list, intf_p);
 
     dbret = dbus_connection_register_object_path(conn->dbus.conn,
-                                                 path, &intf->vtable, intf_p);
+                                                 path, &dbus_object_path_vtable, intf_p);
     if (!dbret) {
         DEBUG(SSSDBG_FATAL_FAILURE,
               "Could not register object path to the connection.\n");
@@ -586,7 +603,7 @@ static void sbus_reconnect(struct tevent_context *ev,
         while (iter) {
             dbret = dbus_connection_register_object_path(conn->dbus.conn,
                                                          iter->intf->path,
-                                                         &iter->intf->vtable,
+                                                         &dbus_object_path_vtable,
                                                          iter);
             if (!dbret) {
                 DEBUG(SSSDBG_FATAL_FAILURE,
-- 
1.8.5.3

