>From f952b8e4695f80aa11538a59737546c0080591ad Mon Sep 17 00:00:00 2001
From: Stef Walter <stefw@gnome.org>
Date: Fri, 17 Jan 2014 12:54:42 +0100
Subject: [PATCH 2/6] sbus: Add struct sbus_request to represent a DBus
 invocation

struct sbus_request represents a request from a dbus client
being handled by a dbus server implementation. The struct
contains the message, connection and method (and in the
future teh property) which is being requested.

In the future it will contain caller information as well.

sbus_request is a talloc memory context, and is a good place to
attach any allocations and memory specific to the request.

Each handler accepts an sbus_request. If a handler returns
EOK, it is assumed that the handler will finish the request.
Any of the sbus_request_*finish() methods can be used to
complete the request and send back a reply.

sbus_request_return_and_finish() uses the same argument
varargs syntax as dbus_message_append_args(), which isn't
a great syntax. Document it a bit, but don't try to redesign:
The marshalling work (will follow this patch set) will remove
the need to use varargs for most DBus implementation code.

This patch migrates the monitor and data provider dbus code
to use sbus_request, but does not try to rework the talloc
context's to use it.
---
 Makefile.am                             |   1 +
 src/monitor/monitor.c                   |  54 +---
 src/monitor/monitor_interfaces.h        |   6 +-
 src/monitor/monitor_sbus.c              |  26 +-
 src/providers/data_provider_be.c        | 503 +++++++++++---------------------
 src/providers/proxy/proxy_child.c       |  14 +-
 src/providers/proxy/proxy_init.c        |  38 +--
 src/responder/autofs/autofssrv.c        |  10 +-
 src/responder/common/responder.h        |   3 +-
 src/responder/common/responder_common.c |   7 +-
 src/responder/nss/nsssrv.c              |  50 +---
 src/sbus/sssd_dbus.h                    |  78 ++++-
 src/sbus/sssd_dbus_connection.c         |  46 +--
 src/sbus/sssd_dbus_private.h            |   6 +
 src/sbus/sssd_dbus_request.c            | 111 +++++++
 src/tests/sbus_codegen_tests.c          |   4 +-
 16 files changed, 459 insertions(+), 498 deletions(-)
 create mode 100644 src/sbus/sssd_dbus_request.c

diff --git a/Makefile.am b/Makefile.am
index a861d0e..29e03a6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -589,6 +589,7 @@ libsss_util_la_SOURCES = \
     src/sbus/sssd_dbus_common.c \
     src/sbus/sssd_dbus_connection.c \
     src/sbus/sssd_dbus_meta.c \
+    src/sbus/sssd_dbus_request.c \
     src/sbus/sssd_dbus_server.c \
     src/util/util.c \
     src/util/memory.c \
diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
index ecfa95c..945f89f 100644
--- a/src/monitor/monitor.c
+++ b/src/monitor/monitor.c
@@ -217,28 +217,13 @@ static void network_status_change_cb(void *cb_data)
 
 /* dbus_get_monitor_version
  * Return the monitor version over D-BUS */
-static int get_monitor_version(DBusMessage *message,
-                               struct sbus_connection *conn)
+static int get_monitor_version(struct sbus_request *request)
 {
     dbus_uint16_t version = MONITOR_VERSION;
-    DBusMessage *reply;
-    dbus_bool_t ret;
 
-    reply = dbus_message_new_method_return(message);
-    if (!reply) return ENOMEM;
-    ret = dbus_message_append_args(reply,
-                                   DBUS_TYPE_UINT16, &version,
-                                   DBUS_TYPE_INVALID);
-    if (!ret) {
-        dbus_message_unref(reply);
-        return EIO;
-    }
-
-    /* send reply back */
-    sbus_conn_send_reply(conn, reply);
-    dbus_message_unref(reply);
-
-    return EOK;
+    return sbus_request_return_and_finish(request,
+                                          DBUS_TYPE_UINT16, &version,
+                                          DBUS_TYPE_INVALID);
 }
 
 struct mon_init_conn {
@@ -251,21 +236,19 @@ static int add_svc_conn_spy(struct mt_svc *svc);
 
 /* registers a new client.
  * if operation is successful also sends back the Monitor version */
-static int client_registration(DBusMessage *message,
-                               struct sbus_connection *conn)
+static int client_registration(struct sbus_request *request)
 {
     dbus_uint16_t version = MONITOR_VERSION;
     struct mon_init_conn *mini;
     struct mt_svc *svc;
     void *data;
-    DBusMessage *reply;
     DBusError dbus_error;
     dbus_uint16_t svc_ver;
     char *svc_name;
     dbus_bool_t dbret;
     int ret;
 
-    data = sbus_conn_get_private_data(conn);
+    data = sbus_conn_get_private_data(request->conn);
     mini = talloc_get_type(data, struct mon_init_conn);
     if (!mini) {
         DEBUG(SSSDBG_FATAL_FAILURE, "Connection holds no valid init data\n");
@@ -277,7 +260,7 @@ static int client_registration(DBusMessage *message,
 
     dbus_error_init(&dbus_error);
 
-    dbret = dbus_message_get_args(message, &dbus_error,
+    dbret = dbus_message_get_args(request->message, &dbus_error,
                                   DBUS_TYPE_STRING, &svc_name,
                                   DBUS_TYPE_UINT16, &svc_ver,
                                   DBUS_TYPE_INVALID);
@@ -285,7 +268,8 @@ static int client_registration(DBusMessage *message,
         DEBUG(SSSDBG_CRIT_FAILURE,
               "Failed to parse message, killing connection\n");
         if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error);
-        sbus_disconnect(conn);
+        sbus_disconnect(request->conn);
+        sbus_request_finish(request, NULL);
         /* FIXME: should we just talloc_zfree(conn) ? */
         goto done;
     }
@@ -306,7 +290,8 @@ static int client_registration(DBusMessage *message,
         DEBUG(SSSDBG_FATAL_FAILURE,
               "Unable to find peer [%s] in list of services,"
                   " killing connection!\n", svc_name);
-        sbus_disconnect(conn);
+        sbus_disconnect(request->conn);
+        sbus_request_finish(request, NULL);
         /* FIXME: should we just talloc_zfree(conn) ? */
         goto done;
     }
@@ -321,20 +306,9 @@ static int client_registration(DBusMessage *message,
     }
 
     /* reply that all is ok */
-    reply = dbus_message_new_method_return(message);
-    if (!reply) return ENOMEM;
-
-    dbret = dbus_message_append_args(reply,
-                                     DBUS_TYPE_UINT16, &version,
-                                     DBUS_TYPE_INVALID);
-    if (!dbret) {
-        dbus_message_unref(reply);
-        return EIO;
-    }
-
-    /* send reply back */
-    sbus_conn_send_reply(conn, reply);
-    dbus_message_unref(reply);
+    sbus_request_return_and_finish(request,
+                                   DBUS_TYPE_UINT16, &version,
+                                   DBUS_TYPE_INVALID);
 
 done:
     /* init complete, get rid of temp init context */
diff --git a/src/monitor/monitor_interfaces.h b/src/monitor/monitor_interfaces.h
index ef4254a..6f485a4 100644
--- a/src/monitor/monitor_interfaces.h
+++ b/src/monitor/monitor_interfaces.h
@@ -38,10 +38,8 @@
 int monitor_get_sbus_address(TALLOC_CTX *mem_ctx, char **address);
 int monitor_common_send_id(struct sbus_connection *conn,
                            const char *name, uint16_t version);
-int monitor_common_pong(DBusMessage *message,
-                        struct sbus_connection *conn);
-int monitor_common_res_init(DBusMessage *message,
-                            struct sbus_connection *conn);
+int monitor_common_pong(struct sbus_request *request);
+int monitor_common_res_init(struct sbus_request *request);
 int monitor_common_rotate_logs(struct confdb_ctx *confdb,
                                const char *conf_entry);
 
diff --git a/src/monitor/monitor_sbus.c b/src/monitor/monitor_sbus.c
index b1550bc..946d8b9 100644
--- a/src/monitor/monitor_sbus.c
+++ b/src/monitor/monitor_sbus.c
@@ -144,30 +144,12 @@ int monitor_common_send_id(struct sbus_connection *conn,
     return retval;
 }
 
-int monitor_common_pong(DBusMessage *message,
-                        struct sbus_connection *conn)
+int monitor_common_pong(struct sbus_request *request)
 {
-    DBusMessage *reply;
-    dbus_bool_t ret;
-
-    reply = dbus_message_new_method_return(message);
-    if (!reply) return ENOMEM;
-
-    ret = dbus_message_append_args(reply, DBUS_TYPE_INVALID);
-    if (!ret) {
-        dbus_message_unref(reply);
-        return EIO;
-    }
-
-    /* send reply back */
-    sbus_conn_send_reply(conn, reply);
-    dbus_message_unref(reply);
-
-    return EOK;
+    return sbus_request_return_and_finish(request, DBUS_TYPE_INVALID);
 }
 
-int monitor_common_res_init(DBusMessage *message,
-                            struct sbus_connection *conn)
+int monitor_common_res_init(struct sbus_request *request)
 {
     int ret;
 
@@ -177,7 +159,7 @@ int monitor_common_res_init(DBusMessage *message,
     }
 
     /* Send an empty reply to acknowledge receipt */
-    return monitor_common_pong(message, conn);
+    return sbus_request_return_and_finish(request, DBUS_TYPE_INVALID);
 }
 
 errno_t monitor_common_rotate_logs(struct confdb_ctx *confdb,
diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
index 5207d19..8a19abe 100644
--- a/src/providers/data_provider_be.c
+++ b/src/providers/data_provider_be.c
@@ -54,14 +54,10 @@
 #define ACCESS_DENY "deny"
 #define NO_PROVIDER "none"
 
-static int data_provider_res_init(DBusMessage *message,
-                                  struct sbus_connection *conn);
-static int data_provider_go_offline(DBusMessage *message,
-                                    struct sbus_connection *conn);
-static int data_provider_reset_offline(DBusMessage *message,
-                                       struct sbus_connection *conn);
-static int data_provider_logrotate(DBusMessage *message,
-                                struct sbus_connection *conn);
+static int data_provider_res_init(struct sbus_request *request);
+static int data_provider_go_offline(struct sbus_request *request);
+static int data_provider_reset_offline(struct sbus_request *request);
+static int data_provider_logrotate(struct sbus_request *request);
 
 struct mon_cli_iface monitor_be_methods = {
     { &mon_cli_iface_meta, 0 },
@@ -81,13 +77,13 @@ struct sbus_interface monitor_be_interface = {
     NULL
 };
 
-static int client_registration(DBusMessage *message, struct sbus_connection *conn);
-static int be_get_account_info(DBusMessage *message, struct sbus_connection *conn);
-static int be_pam_handler(DBusMessage *message, struct sbus_connection *conn);
-static int be_sudo_handler(DBusMessage *message, struct sbus_connection *conn);
-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);
+static int client_registration(struct sbus_request *request);
+static int be_get_account_info(struct sbus_request *request);
+static int be_pam_handler(struct sbus_request *request);
+static int be_sudo_handler(struct sbus_request *request);
+static int be_autofs_handler(struct sbus_request *request);
+static int be_host_handler(struct sbus_request *request);
+static int be_get_subdomains(struct sbus_request *request);
 
 struct data_provider_iface be_methods = {
     { &data_provider_iface_meta, 0 },
@@ -396,14 +392,12 @@ static void be_queue_next_request(struct be_req *be_req, enum bet_type type)
     struct bet_queue_item *item;
     struct bet_queue_item *current = NULL;
     struct bet_queue_item **req_queue;
+    struct sbus_request *dbus_req;
     int ret;
-    DBusMessage *reply;
     uint16_t err_maj;
     uint32_t err_min;
     const char *err_msg = "Cannot file back end request";
     struct be_req *next_be_req = NULL;
-    dbus_bool_t dbret;
-    DBusConnection *dbus_conn;
 
     req_queue = &be_req->becli->bectx->bet_info[type].req_queue;
 
@@ -440,9 +434,9 @@ static void be_queue_next_request(struct be_req *be_req, enum bet_type type)
 
     be_queue_next_request(next_be_req, type);
 
-    reply = (DBusMessage *) next_be_req->pvt;
+    dbus_req = (struct sbus_request *) next_be_req->pvt;
 
-    if (reply) {
+    if (dbus_req) {
         /* Return a reply if one was requested
          * There may not be one if this request began
          * while we were offline
@@ -450,28 +444,13 @@ static void be_queue_next_request(struct be_req *be_req, enum bet_type type)
         err_maj = DP_ERR_FATAL;
         err_min = ret;
 
-        dbret = dbus_message_append_args(reply,
-                                         DBUS_TYPE_UINT16, &err_maj,
-                                         DBUS_TYPE_UINT32, &err_min,
-                                         DBUS_TYPE_STRING, &err_msg,
-                                         DBUS_TYPE_INVALID);
-
-        if (!dbret) {
-            DEBUG(SSSDBG_CRIT_FAILURE, "Failed to generate dbus reply\n");
-            dbus_message_unref(reply);
-            goto done;
-        }
-
-        dbus_conn = sbus_get_connection(next_be_req->becli->conn);
-        if (dbus_conn == NULL) {
-            DEBUG(SSSDBG_CRIT_FAILURE, "D-BUS not connected\n");
-            goto done;
-        }
-        dbus_connection_send(dbus_conn, reply, NULL);
-        dbus_message_unref(reply);
+        sbus_request_return_and_finish(dbus_req,
+                                       DBUS_TYPE_UINT16, &err_maj,
+                                       DBUS_TYPE_UINT32, &err_min,
+                                       DBUS_TYPE_STRING, &err_msg,
+                                       DBUS_TYPE_INVALID);
     }
 
-done:
     talloc_free(next_be_req);
 }
 
@@ -551,9 +530,7 @@ static void get_subdomains_callback(struct be_req *req,
                                     int errnum,
                                     const char *errstr)
 {
-    DBusMessage *reply;
-    DBusConnection *dbus_conn;
-    dbus_bool_t dbret;
+    struct sbus_request *dbus_req;
     dbus_uint16_t err_maj = 0;
     dbus_uint32_t err_min = 0;
     const char *err_msg = NULL;
@@ -564,9 +541,9 @@ static void get_subdomains_callback(struct be_req *req,
 
     be_queue_next_request(req, BET_SUBDOMAINS);
 
-    reply = (DBusMessage *)req->pvt;
+    dbus_req = (struct sbus_request *)req->pvt;
 
-    if (reply) {
+    if (dbus_req) {
         /* Return a reply if one was requested
          * There may not be one if this request began
          * while we were offline
@@ -584,39 +561,22 @@ static void get_subdomains_callback(struct be_req *req,
             err_msg = "OOM";
         }
 
-        dbret = dbus_message_append_args(reply,
-                                         DBUS_TYPE_UINT16, &err_maj,
-                                         DBUS_TYPE_UINT32, &err_min,
-                                         DBUS_TYPE_STRING, &err_msg,
-                                         DBUS_TYPE_INVALID);
-
-        if (!dbret) {
-            DEBUG(SSSDBG_CRIT_FAILURE, "Failed to generate dbus reply\n");
-            dbus_message_unref(reply);
-            goto done;
-        }
-
-        dbus_conn = sbus_get_connection(req->becli->conn);
-        if (dbus_conn == NULL) {
-            DEBUG(SSSDBG_CRIT_FAILURE, "D-BUS not connected\n");
-            goto done;
-        }
-        dbus_connection_send(dbus_conn, reply, NULL);
-        dbus_message_unref(reply);
+        sbus_request_return_and_finish(dbus_req,
+                                       DBUS_TYPE_UINT16, &err_maj,
+                                       DBUS_TYPE_UINT32, &err_min,
+                                       DBUS_TYPE_STRING, &err_msg,
+                                       DBUS_TYPE_INVALID);
     }
 
-done:
     talloc_free(req);
 }
 
-static int be_get_subdomains(DBusMessage *message, struct sbus_connection *conn)
+static int be_get_subdomains(struct sbus_request *dbus_req)
 {
     struct be_subdom_req *req;
     struct be_req *be_req = NULL;
     struct be_client *becli;
-    DBusMessage *reply;
     DBusError dbus_error;
-    dbus_bool_t dbret;
     void *user_data;
     dbus_bool_t force;
     char *domain_hint;
@@ -625,14 +585,14 @@ static int be_get_subdomains(DBusMessage *message, struct sbus_connection *conn)
     const char *err_msg;
     int ret;
 
-    user_data = sbus_conn_get_private_data(conn);
+    user_data = sbus_conn_get_private_data(dbus_req->conn);
     if (!user_data) return EINVAL;
     becli = talloc_get_type(user_data, struct be_client);
     if (!becli) return EINVAL;
 
     dbus_error_init(&dbus_error);
 
-    ret = dbus_message_get_args(message, &dbus_error,
+    ret = dbus_message_get_args(dbus_req->message, &dbus_error,
                                 DBUS_TYPE_BOOLEAN, &force,
                                 DBUS_TYPE_STRING, &domain_hint,
                                 DBUS_TYPE_INVALID);
@@ -642,9 +602,6 @@ static int be_get_subdomains(DBusMessage *message, struct sbus_connection *conn)
         return EIO;
     }
 
-    reply = dbus_message_new_method_return(message);
-    if (!reply) return ENOMEM;
-
     /* return an error if corresponding backend target is not configured */
     if (becli->bectx->bet_info[BET_SUBDOMAINS].bet_ops == NULL) {
         DEBUG(SSSDBG_TRACE_INTERNAL, "Undefined backend target.\n");
@@ -671,7 +628,7 @@ static int be_get_subdomains(DBusMessage *message, struct sbus_connection *conn)
     /* process request */
 
     be_req = be_req_create(becli, becli, becli->bectx,
-                           get_subdomains_callback, reply);
+                           get_subdomains_callback, dbus_req);
     if (!be_req) {
         err_maj = DP_ERR_FATAL;
         err_min = ENOMEM;
@@ -716,26 +673,16 @@ immediate:
         talloc_free(be_req);
     }
 
-    if (reply) {
-        dbret = dbus_message_append_args(reply,
-                                         DBUS_TYPE_UINT16, &err_maj,
-                                         DBUS_TYPE_UINT32, &err_min,
-                                         DBUS_TYPE_STRING, &err_msg,
-                                         DBUS_TYPE_INVALID);
-        if (!dbret) {
-            DEBUG(SSSDBG_CRIT_FAILURE, "Failed to generate dbus reply\n");
-            dbus_message_unref(reply);
-            return EIO;
-        }
-
-        if (!(err_maj == DP_ERR_FATAL && err_min == ENODEV)) {
-            DEBUG(SSSDBG_TRACE_LIBS, "Request processed. Returned %d,%d,%s\n",
-                  err_maj, err_min, err_msg);
-        }
+    /* send reply back */
+    sbus_request_return_and_finish(dbus_req,
+                                   DBUS_TYPE_UINT16, &err_maj,
+                                   DBUS_TYPE_UINT32, &err_min,
+                                   DBUS_TYPE_STRING, &err_msg,
+                                   DBUS_TYPE_INVALID);
 
-        /* send reply back */
-        sbus_conn_send_reply(conn, reply);
-        dbus_message_unref(reply);
+    if (!(err_maj == DP_ERR_FATAL && err_min == ENODEV)) {
+        DEBUG(SSSDBG_TRACE_LIBS, "Request processed. Returned %d,%d,%s\n",
+                err_maj, err_min, err_msg);
     }
 
     return EOK;
@@ -746,16 +693,14 @@ static void acctinfo_callback(struct be_req *req,
                               int errnum,
                               const char *errstr)
 {
-    DBusMessage *reply;
-    DBusConnection *dbus_conn;
-    dbus_bool_t dbret;
+    struct sbus_request *dbus_req;
     dbus_uint16_t err_maj = 0;
     dbus_uint32_t err_min = 0;
     const char *err_msg = NULL;
 
-    reply = (DBusMessage *)req->pvt;
+    dbus_req = (struct sbus_request *)req->pvt;
 
-    if (reply) {
+    if (dbus_req) {
         /* Return a reply if one was requested
          * There may not be one if this request began
          * while we were offline
@@ -774,24 +719,11 @@ static void acctinfo_callback(struct be_req *req,
             err_msg = "OOM";
         }
 
-        dbret = dbus_message_append_args(reply,
-                                         DBUS_TYPE_UINT16, &err_maj,
-                                         DBUS_TYPE_UINT32, &err_min,
-                                         DBUS_TYPE_STRING, &err_msg,
-                                         DBUS_TYPE_INVALID);
-        if (!dbret) {
-            DEBUG(SSSDBG_CRIT_FAILURE, "Failed to generate dbus reply\n");
-            return;
-        }
-
-        dbus_conn = sbus_get_connection(req->becli->conn);
-        if (!dbus_conn) {
-            DEBUG(SSSDBG_CRIT_FAILURE, "D-BUS not connected\n");
-            return;
-        }
-
-        dbus_connection_send(dbus_conn, reply, NULL);
-        dbus_message_unref(reply);
+        sbus_request_return_and_finish(dbus_req,
+                                       DBUS_TYPE_UINT16, &err_maj,
+                                       DBUS_TYPE_UINT32, &err_min,
+                                       DBUS_TYPE_STRING, &err_msg,
+                                       DBUS_TYPE_INVALID);
 
         DEBUG(SSSDBG_CONF_SETTINGS, "Request processed. Returned %d,%d,%s\n",
                   err_maj, err_min, err_msg);
@@ -1120,14 +1052,12 @@ errno_t be_get_account_info_recv(struct tevent_req *req,
     return EOK;
 }
 
-static int be_get_account_info(DBusMessage *message, struct sbus_connection *conn)
+static int be_get_account_info(struct sbus_request *dbus_req)
 {
     struct be_acct_req *req;
     struct be_req *be_req;
     struct be_client *becli;
-    DBusMessage *reply;
     DBusError dbus_error;
-    dbus_bool_t dbret;
     void *user_data;
     uint32_t type;
     char *filter;
@@ -1140,14 +1070,14 @@ static int be_get_account_info(DBusMessage *message, struct sbus_connection *con
 
     be_req = NULL;
 
-    user_data = sbus_conn_get_private_data(conn);
+    user_data = sbus_conn_get_private_data(dbus_req->conn);
     if (!user_data) return EINVAL;
     becli = talloc_get_type(user_data, struct be_client);
     if (!becli) return EINVAL;
 
     dbus_error_init(&dbus_error);
 
-    ret = dbus_message_get_args(message, &dbus_error,
+    ret = dbus_message_get_args(dbus_req->message, &dbus_error,
                                 DBUS_TYPE_UINT32, &type,
                                 DBUS_TYPE_UINT32, &attr_type,
                                 DBUS_TYPE_STRING, &filter,
@@ -1162,9 +1092,6 @@ static int be_get_account_info(DBusMessage *message, struct sbus_connection *con
     DEBUG(SSSDBG_CONF_SETTINGS,
           "Got request for [%u][%d][%s]\n", type, attr_type, filter);
 
-    reply = dbus_message_new_method_return(message);
-    if (!reply) return ENOMEM;
-
     /* If we are offline and fast reply was requested
      * return offline immediately
      */
@@ -1174,19 +1101,17 @@ static int be_get_account_info(DBusMessage *message, struct sbus_connection *con
         err_min = EAGAIN;
         err_msg = "Fast reply - offline";
 
-        dbret = dbus_message_append_args(reply,
-                                         DBUS_TYPE_UINT16, &err_maj,
-                                         DBUS_TYPE_UINT32, &err_min,
-                                         DBUS_TYPE_STRING, &err_msg,
-                                         DBUS_TYPE_INVALID);
-        if (!dbret) return EIO;
+        ret = sbus_request_return_and_finish(dbus_req,
+                                             DBUS_TYPE_UINT16, &err_maj,
+                                             DBUS_TYPE_UINT32, &err_min,
+                                             DBUS_TYPE_STRING, &err_msg,
+                                             DBUS_TYPE_INVALID);
+        if (ret != EOK) return ret;
 
         DEBUG(SSSDBG_CONF_SETTINGS, "Request processed. Returned %d,%d,%s\n",
                   err_maj, err_min, err_msg);
 
-        sbus_conn_send_reply(conn, reply);
-        dbus_message_unref(reply);
-        reply = NULL;
+        dbus_req = NULL;
         /* This reply will be queued and sent
          * when we reenter the mainloop.
          *
@@ -1196,7 +1121,7 @@ static int be_get_account_info(DBusMessage *message, struct sbus_connection *con
     }
 
     be_req = be_req_create(becli, becli, becli->bectx,
-                           acctinfo_callback, reply);
+                           acctinfo_callback, dbus_req);
     if (!be_req) {
         err_maj = DP_ERR_FATAL;
         err_min = ENOMEM;
@@ -1297,20 +1222,17 @@ done:
         talloc_free(be_req);
     }
 
-    if (reply) {
-        dbret = dbus_message_append_args(reply,
-                                         DBUS_TYPE_UINT16, &err_maj,
-                                         DBUS_TYPE_UINT32, &err_min,
-                                         DBUS_TYPE_STRING, &err_msg,
-                                         DBUS_TYPE_INVALID);
-        if (!dbret) return EIO;
+    if (dbus_req) {
+        ret = sbus_request_return_and_finish(dbus_req,
+                                             DBUS_TYPE_UINT16, &err_maj,
+                                             DBUS_TYPE_UINT32, &err_min,
+                                             DBUS_TYPE_STRING, &err_msg,
+                                             DBUS_TYPE_INVALID);
+        if (ret != EOK)
+            return ret;
 
         DEBUG(SSSDBG_CONF_SETTINGS, "Request processed. Returned %d,%d,%s\n",
                   err_maj, err_min, err_msg);
-
-        /* send reply back */
-        sbus_conn_send_reply(conn, reply);
-        dbus_message_unref(reply);
     }
 
     return EOK;
@@ -1322,9 +1244,9 @@ static void be_pam_handler_callback(struct be_req *req,
                                     const char *errstr)
 {
     struct be_client *becli = req->becli;
+    struct sbus_request *dbus_req;
     struct pam_data *pd;
     DBusMessage *reply;
-    DBusConnection *dbus_conn;
     dbus_bool_t dbret;
     errno_t ret;
 
@@ -1359,7 +1281,14 @@ static void be_pam_handler_callback(struct be_req *req,
 
     DEBUG(SSSDBG_CONF_SETTINGS,
           "Sending result [%d][%s]\n", pd->pam_status, pd->domain);
-    reply = (DBusMessage *)req->pvt;
+    dbus_req = (struct sbus_request *)req->pvt;
+    reply = dbus_message_new_method_return(dbus_req->message);
+    if (reply == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "dbus_message_new_method_return failed, cannot send reply.\n");
+        goto done;
+    }
+
     dbret = dp_pack_pam_response(reply, pd);
     if (!dbret) {
         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to generate dbus reply\n");
@@ -1367,13 +1296,7 @@ static void be_pam_handler_callback(struct be_req *req,
         goto done;
     }
 
-    dbus_conn = sbus_get_connection(req->becli->conn);
-    if (!dbus_conn) {
-        DEBUG(SSSDBG_CRIT_FAILURE, "D-BUS not connected\n");
-        goto done;
-    }
-
-    dbus_connection_send(dbus_conn, reply, NULL);
+    sbus_request_finish(dbus_req, reply);
     dbus_message_unref(reply);
 
     DEBUG(SSSDBG_CONF_SETTINGS,
@@ -1383,7 +1306,7 @@ done:
     talloc_free(req);
 }
 
-static int be_pam_handler(DBusMessage *message, struct sbus_connection *conn)
+static int be_pam_handler(struct sbus_request *dbus_req)
 {
     DBusError dbus_error;
     DBusMessage *reply;
@@ -1394,29 +1317,21 @@ static int be_pam_handler(DBusMessage *message, struct sbus_connection *conn)
     struct be_req *be_req = NULL;
     enum bet_type target = BET_NULL;
 
-    user_data = sbus_conn_get_private_data(conn);
+    user_data = sbus_conn_get_private_data(dbus_req->conn);
     if (!user_data) return EINVAL;
     becli = talloc_get_type(user_data, struct be_client);
     if (!becli) return EINVAL;
 
-    reply = dbus_message_new_method_return(message);
-    if (!reply) {
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              "dbus_message_new_method_return failed, cannot send reply.\n");
-        return ENOMEM;
-    }
-
     be_req = be_req_create(becli, becli, becli->bectx,
-                           be_pam_handler_callback, reply);
+                           be_pam_handler_callback, dbus_req);
     if (!be_req) {
         DEBUG(SSSDBG_TRACE_LIBS, "talloc_zero failed.\n");
-        dbus_message_unref(reply);
         return ENOMEM;
     }
 
     dbus_error_init(&dbus_error);
 
-    ret = dp_unpack_pam_request(message, be_req, &pd, &dbus_error);
+    ret = dp_unpack_pam_request(dbus_req->message, be_req, &pd, &dbus_error);
     if (!ret) {
         DEBUG(SSSDBG_CRIT_FAILURE,"Failed, to parse message!\n");
         talloc_free(be_req);
@@ -1494,6 +1409,13 @@ done:
     DEBUG(SSSDBG_CONF_SETTINGS, "Sending result [%d][%s]\n",
               pd->pam_status, pd->domain);
 
+    reply = dbus_message_new_method_return(dbus_req->message);
+    if (reply == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "dbus_message_new_method_return failed, cannot send reply.\n");
+        return ENOMEM;
+    }
+
     ret = dp_pack_pam_response(reply, pd);
     if (!ret) {
         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to generate dbus reply\n");
@@ -1503,7 +1425,7 @@ done:
     }
 
     /* send reply back immediately */
-    sbus_conn_send_reply(conn, reply);
+    sbus_request_finish(dbus_req, reply);
     dbus_message_unref(reply);
 
     talloc_free(be_req);
@@ -1511,42 +1433,26 @@ done:
     return EOK;
 }
 
-static void be_sudo_handler_reply(struct sbus_connection *conn,
-                                  DBusMessage *reply,
+static void be_sudo_handler_reply(struct sbus_request *dbus_req,
                                   dbus_uint16_t dp_err,
                                   dbus_uint32_t dp_ret,
                                   const char *errstr)
 {
-    DBusConnection *dbus_conn = NULL;
-    dbus_bool_t dbret;
     const char *err_msg = NULL;
 
-    if (reply == NULL) {
+    if (dbus_req == NULL) {
         return;
     }
 
     err_msg = errstr ? errstr : "No errmsg set\n";
-    dbret = dbus_message_append_args(reply,
-                                     DBUS_TYPE_UINT16, &dp_err,
-                                     DBUS_TYPE_UINT32, &dp_ret,
-                                     DBUS_TYPE_STRING, &err_msg,
-                                     DBUS_TYPE_INVALID);
-    if (!dbret) {
-        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to generate dbus reply\n");
-        return;
-    }
+    sbus_request_return_and_finish(dbus_req,
+                                   DBUS_TYPE_UINT16, &dp_err,
+                                   DBUS_TYPE_UINT32, &dp_ret,
+                                   DBUS_TYPE_STRING, &err_msg,
+                                   DBUS_TYPE_INVALID);
 
     DEBUG(SSSDBG_FUNC_DATA, "SUDO Backend returned: (%d, %d, %s)\n",
                              dp_err, dp_ret, errstr ? errstr : "<NULL>");
-
-    dbus_conn = sbus_get_connection(conn);
-    if (!dbus_conn) {
-        DEBUG(SSSDBG_CRIT_FAILURE, "D-BUS not connected\n");
-        return;
-    }
-
-    dbus_connection_send(dbus_conn, reply, NULL);
-    dbus_message_unref(reply);
 }
 
 static void be_sudo_handler_callback(struct be_req *req,
@@ -1554,18 +1460,17 @@ static void be_sudo_handler_callback(struct be_req *req,
                                      int dp_ret,
                                      const char *errstr)
 {
-    DBusMessage *reply = NULL;
-    reply = (DBusMessage*)(req->pvt);
+    struct sbus_request *dbus_req;
+    dbus_req = (struct sbus_request *)(req->pvt);
 
-    be_sudo_handler_reply(req->becli->conn, reply, dp_err, dp_ret, errstr);
+    be_sudo_handler_reply(dbus_req, dp_err, dp_ret, errstr);
 
     talloc_free(req);
 }
 
-static int be_sudo_handler(DBusMessage *message, struct sbus_connection *conn)
+static int be_sudo_handler(struct sbus_request *dbus_req)
 {
     DBusError dbus_error;
-    DBusMessage *reply = NULL;
     DBusMessageIter iter;
     dbus_bool_t iter_next = FALSE;
     struct be_client *be_cli = NULL;
@@ -1581,7 +1486,7 @@ static int be_sudo_handler(DBusMessage *message, struct sbus_connection *conn)
 
     DEBUG(SSSDBG_TRACE_FUNC, "Entering be_sudo_handler()\n");
 
-    user_data = sbus_conn_get_private_data(conn);
+    user_data = sbus_conn_get_private_data(dbus_req->conn);
     if (user_data == NULL) {
         return EINVAL;
     }
@@ -1591,24 +1496,16 @@ static int be_sudo_handler(DBusMessage *message, struct sbus_connection *conn)
         return EINVAL;
     }
 
-    reply = dbus_message_new_method_return(message);
-    if (!reply) {
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              "dbus_message_new_method_return failed, cannot send reply.\n");
-        return ENOMEM;
-    }
-
     /* create be request */
     be_req = be_req_create(be_cli, be_cli, be_cli->bectx,
-                           be_sudo_handler_callback, reply);
+                           be_sudo_handler_callback, dbus_req);
     if (be_req == NULL) {
         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
-        dbus_message_unref(reply);
         return ENOMEM;
     }
 
     dbus_error_init(&dbus_error);
-    dbus_message_iter_init(message, &iter);
+    dbus_message_iter_init(dbus_req->message, &iter);
 
     /* get type of the request */
     if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32) {
@@ -1624,9 +1521,9 @@ static int be_sudo_handler(DBusMessage *message, struct sbus_connection *conn)
      * return offline immediately
      */
     if ((type & BE_REQ_FAST) && be_cli->bectx->offstat.offline) {
-        be_sudo_handler_reply(conn, reply, DP_ERR_OFFLINE, EAGAIN,
+        be_sudo_handler_reply(dbus_req, DP_ERR_OFFLINE, EAGAIN,
                               "Fast reply - offline");
-        reply = NULL;
+        be_req->pvt = dbus_req = NULL;
         /* This reply will be queued and sent
          * when we reenter the mainloop.
          *
@@ -1738,11 +1635,9 @@ static void be_autofs_handler_callback(struct be_req *req,
                                        int errnum,
                                        const char *errstr);
 
-static int be_autofs_handler(DBusMessage *message, struct sbus_connection *conn)
+static int be_autofs_handler(struct sbus_request *dbus_req)
 {
     DBusError dbus_error;
-    DBusMessage *reply = NULL;
-    dbus_bool_t dbret;
     struct be_client *be_cli = NULL;
     struct be_req *be_req = NULL;
     struct be_autofs_req *be_autofs_req = NULL;
@@ -1757,7 +1652,7 @@ static int be_autofs_handler(DBusMessage *message, struct sbus_connection *conn)
 
     DEBUG(SSSDBG_TRACE_FUNC, "Entering be_autofs_handler()\n");
 
-    user_data = sbus_conn_get_private_data(conn);
+    user_data = sbus_conn_get_private_data(dbus_req->conn);
     if (user_data == NULL) {
         DEBUG(SSSDBG_CRIT_FAILURE, "Cannot get SBUS private data\n");
         return EINVAL;
@@ -1771,7 +1666,7 @@ static int be_autofs_handler(DBusMessage *message, struct sbus_connection *conn)
 
     dbus_error_init(&dbus_error);
 
-    ret = dbus_message_get_args(message, &dbus_error,
+    ret = dbus_message_get_args(dbus_req->message, &dbus_error,
                                 DBUS_TYPE_UINT32, &type,
                                 DBUS_TYPE_STRING, &filter,
                                 DBUS_TYPE_INVALID);
@@ -1781,13 +1676,6 @@ static int be_autofs_handler(DBusMessage *message, struct sbus_connection *conn)
         return EIO;
     }
 
-    reply = dbus_message_new_method_return(message);
-    if (!reply) {
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              "dbus_message_new_method_return failed, cannot send reply.\n");
-        return ENOMEM;
-    }
-
     /* If we are offline and fast reply was requested
      * return offline immediately
      */
@@ -1797,19 +1685,17 @@ static int be_autofs_handler(DBusMessage *message, struct sbus_connection *conn)
         err_min = EAGAIN;
         err_msg = "Fast reply - offline";
 
-        dbret = dbus_message_append_args(reply,
-                                         DBUS_TYPE_UINT16, &err_maj,
-                                         DBUS_TYPE_UINT32, &err_min,
-                                         DBUS_TYPE_STRING, &err_msg,
-                                         DBUS_TYPE_INVALID);
-        if (!dbret) return EIO;
+        ret = sbus_request_return_and_finish(dbus_req,
+                                             DBUS_TYPE_UINT16, &err_maj,
+                                             DBUS_TYPE_UINT32, &err_min,
+                                             DBUS_TYPE_STRING, &err_msg,
+                                             DBUS_TYPE_INVALID);
+        if (ret != EOK) return ret;
 
         DEBUG(SSSDBG_TRACE_LIBS, "Request processed. Returned %d,%d,%s\n",
               err_maj, err_min, err_msg);
 
-        sbus_conn_send_reply(conn, reply);
-        dbus_message_unref(reply);
-        reply = NULL;
+        dbus_req = NULL;
         /* This reply will be queued and sent
          * when we reenter the mainloop.
          *
@@ -1836,7 +1722,7 @@ static int be_autofs_handler(DBusMessage *message, struct sbus_connection *conn)
 
     /* create be request */
     be_req = be_req_create(be_cli, be_cli, be_cli->bectx,
-                           be_autofs_handler_callback, reply);
+                           be_autofs_handler_callback, dbus_req);
     if (be_req == NULL) {
         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
         err_maj = DP_ERR_FATAL;
@@ -1892,20 +1778,17 @@ done:
         talloc_free(be_req);
     }
 
-    if (reply) {
-        dbret = dbus_message_append_args(reply,
-                                         DBUS_TYPE_UINT16, &err_maj,
-                                         DBUS_TYPE_UINT32, &err_min,
-                                         DBUS_TYPE_STRING, &err_msg,
-                                         DBUS_TYPE_INVALID);
-        if (!dbret) return EIO;
+    if (dbus_req) {
+        ret = sbus_request_return_and_finish(dbus_req,
+                                             DBUS_TYPE_UINT16, &err_maj,
+                                             DBUS_TYPE_UINT32, &err_min,
+                                             DBUS_TYPE_STRING, &err_msg,
+                                             DBUS_TYPE_INVALID);
+        if (ret != EOK)
+            return ret;
 
         DEBUG(SSSDBG_TRACE_LIBS, "Request processed. Returned %d,%d,%s\n",
               err_maj, err_min, err_msg);
-
-        /* send reply back */
-        sbus_conn_send_reply(conn, reply);
-        dbus_message_unref(reply);
     }
 
     return EOK;
@@ -1916,16 +1799,14 @@ static void be_autofs_handler_callback(struct be_req *req,
                                        int errnum,
                                        const char *errstr)
 {
-    DBusMessage *reply;
-    DBusConnection *dbus_conn;
-    dbus_bool_t dbret;
+    struct sbus_request *dbus_req;
     dbus_uint16_t err_maj = 0;
     dbus_uint32_t err_min = 0;
     const char *err_msg = NULL;
 
-    reply = (DBusMessage *)req->pvt;
+    dbus_req = (struct sbus_request *)req->pvt;
 
-    if (reply) {
+    if (dbus_req) {
         /* Return a reply if one was requested
          * There may not be one if this request began
          * while we were offline
@@ -1944,24 +1825,11 @@ static void be_autofs_handler_callback(struct be_req *req,
             err_msg = "OOM";
         }
 
-        dbret = dbus_message_append_args(reply,
-                                         DBUS_TYPE_UINT16, &err_maj,
-                                         DBUS_TYPE_UINT32, &err_min,
-                                         DBUS_TYPE_STRING, &err_msg,
-                                         DBUS_TYPE_INVALID);
-        if (!dbret) {
-            DEBUG(SSSDBG_CRIT_FAILURE, "Failed to generate dbus reply\n");
-            return;
-        }
-
-        dbus_conn = sbus_get_connection(req->becli->conn);
-        if (!dbus_conn) {
-            DEBUG(SSSDBG_CRIT_FAILURE, "D-BUS not connected\n");
-            return;
-        }
-
-        dbus_connection_send(dbus_conn, reply, NULL);
-        dbus_message_unref(reply);
+        sbus_request_return_and_finish(dbus_req,
+                                       DBUS_TYPE_UINT16, &err_maj,
+                                       DBUS_TYPE_UINT32, &err_min,
+                                       DBUS_TYPE_STRING, &err_msg,
+                                       DBUS_TYPE_INVALID);
 
         DEBUG(SSSDBG_TRACE_LIBS,
               "Request processed. Returned %d,%d,%s\n",
@@ -1972,14 +1840,12 @@ static void be_autofs_handler_callback(struct be_req *req,
     talloc_free(req);
 }
 
-static int be_host_handler(DBusMessage *message, struct sbus_connection *conn)
+static int be_host_handler(struct sbus_request *dbus_req)
 {
     struct be_host_req *req;
     struct be_req *be_req;
     struct be_client *becli;
-    DBusMessage *reply;
     DBusError dbus_error;
-    dbus_bool_t dbret;
     void *user_data;
     uint32_t flags;
     char *filter;
@@ -1990,14 +1856,14 @@ static int be_host_handler(DBusMessage *message, struct sbus_connection *conn)
 
     be_req = NULL;
 
-    user_data = sbus_conn_get_private_data(conn);
+    user_data = sbus_conn_get_private_data(dbus_req->conn);
     if (!user_data) return EINVAL;
     becli = talloc_get_type(user_data, struct be_client);
     if (!becli) return EINVAL;
 
     dbus_error_init(&dbus_error);
 
-    ret = dbus_message_get_args(message, &dbus_error,
+    ret = dbus_message_get_args(dbus_req->message, &dbus_error,
                                 DBUS_TYPE_UINT32, &flags,
                                 DBUS_TYPE_STRING, &filter,
                                 DBUS_TYPE_INVALID);
@@ -2010,9 +1876,6 @@ static int be_host_handler(DBusMessage *message, struct sbus_connection *conn)
     DEBUG(SSSDBG_TRACE_LIBS,
           "Got request for [%u][%s]\n", flags, filter);
 
-    reply = dbus_message_new_method_return(message);
-    if (!reply) return ENOMEM;
-
     /* If we are offline and fast reply was requested
      * return offline immediately
      */
@@ -2022,20 +1885,18 @@ static int be_host_handler(DBusMessage *message, struct sbus_connection *conn)
         err_min = EAGAIN;
         err_msg = "Fast reply - offline";
 
-        dbret = dbus_message_append_args(reply,
-                                         DBUS_TYPE_UINT16, &err_maj,
-                                         DBUS_TYPE_UINT32, &err_min,
-                                         DBUS_TYPE_STRING, &err_msg,
-                                         DBUS_TYPE_INVALID);
-        if (!dbret) return EIO;
+        ret = sbus_request_return_and_finish(dbus_req,
+                                             DBUS_TYPE_UINT16, &err_maj,
+                                             DBUS_TYPE_UINT32, &err_min,
+                                             DBUS_TYPE_STRING, &err_msg,
+                                             DBUS_TYPE_INVALID);
+        if (ret != EOK) return ret;
 
         DEBUG(SSSDBG_TRACE_LIBS,
               "Request processed. Returned %d,%d,%s\n",
                err_maj, err_min, err_msg);
 
-        sbus_conn_send_reply(conn, reply);
-        dbus_message_unref(reply);
-        reply = NULL;
+        dbus_req = NULL;
         /* This reply will be queued and sent
          * when we reenter the mainloop.
          *
@@ -2045,7 +1906,7 @@ static int be_host_handler(DBusMessage *message, struct sbus_connection *conn)
     }
 
     be_req = be_req_create(becli, becli, becli->bectx,
-                           acctinfo_callback, reply);
+                           acctinfo_callback, dbus_req);
     if (!be_req) {
         err_maj = DP_ERR_FATAL;
         err_min = ENOMEM;
@@ -2113,21 +1974,18 @@ done:
         talloc_free(be_req);
     }
 
-    if (reply) {
-        dbret = dbus_message_append_args(reply,
-                                         DBUS_TYPE_UINT16, &err_maj,
-                                         DBUS_TYPE_UINT32, &err_min,
-                                         DBUS_TYPE_STRING, &err_msg,
-                                         DBUS_TYPE_INVALID);
-        if (!dbret) return EIO;
+    if (dbus_req) {
+        ret = sbus_request_return_and_finish(dbus_req,
+                                             DBUS_TYPE_UINT16, &err_maj,
+                                             DBUS_TYPE_UINT32, &err_min,
+                                             DBUS_TYPE_STRING, &err_msg,
+                                             DBUS_TYPE_INVALID);
+        if (ret != EOK)
+            return ret;
 
         DEBUG(SSSDBG_TRACE_LIBS,
               "Request processed. Returned %d,%d,%s\n",
                err_maj, err_min, err_msg);
-
-        /* send reply back */
-        sbus_conn_send_reply(conn, reply);
-        dbus_message_unref(reply);
     }
 
     return EOK;
@@ -2162,18 +2020,19 @@ static int be_client_destructor(void *ctx)
     return 0;
 }
 
-static int client_registration(DBusMessage *message,
-                               struct sbus_connection *conn)
+static int client_registration(struct sbus_request *dbus_req)
 {
     dbus_uint16_t version = DATA_PROVIDER_VERSION;
+    struct sbus_connection *conn;
     struct be_client *becli;
-    DBusMessage *reply;
     DBusError dbus_error;
     dbus_uint16_t cli_ver;
     char *cli_name;
     dbus_bool_t dbret;
     void *data;
+    int ret;
 
+    conn = dbus_req->conn;
     data = sbus_conn_get_private_data(conn);
     becli = talloc_get_type(data, struct be_client);
     if (!becli) {
@@ -2187,7 +2046,7 @@ static int client_registration(DBusMessage *message,
 
     dbus_error_init(&dbus_error);
 
-    dbret = dbus_message_get_args(message, &dbus_error,
+    dbret = dbus_message_get_args(dbus_req->message, &dbus_error,
                                   DBUS_TYPE_UINT16, &cli_ver,
                                   DBUS_TYPE_STRING, &cli_name,
                                   DBUS_TYPE_INVALID);
@@ -2220,26 +2079,14 @@ static int client_registration(DBusMessage *message,
     DEBUG(SSSDBG_CONF_SETTINGS, "Added Frontend client [%s]\n", cli_name);
 
     /* reply that all is ok */
-    reply = dbus_message_new_method_return(message);
-    if (!reply) {
-        DEBUG(SSSDBG_FATAL_FAILURE, "Dbus Out of memory!\n");
-        return ENOMEM;
-    }
-
-    dbret = dbus_message_append_args(reply,
-                                     DBUS_TYPE_UINT16, &version,
-                                     DBUS_TYPE_INVALID);
-    if (!dbret) {
-        DEBUG(SSSDBG_FATAL_FAILURE, "Failed to build dbus reply\n");
-        dbus_message_unref(reply);
+    ret = sbus_request_return_and_finish(dbus_req,
+                                         DBUS_TYPE_UINT16, &version,
+                                         DBUS_TYPE_INVALID);
+    if (ret != EOK) {
         sbus_disconnect(conn);
-        return EIO;
+        return ret;
     }
 
-    /* send reply back */
-    sbus_conn_send_reply(conn, reply);
-    dbus_message_unref(reply);
-
     becli->initialized = true;
     return EOK;
 }
@@ -3028,45 +2875,41 @@ int main(int argc, const char *argv[])
 }
 #endif
 
-static int data_provider_res_init(DBusMessage *message,
-                                  struct sbus_connection *conn)
+static int data_provider_res_init(struct sbus_request *request)
 {
     struct be_ctx *be_ctx;
-    be_ctx = talloc_get_type(sbus_conn_get_private_data(conn), struct be_ctx);
+    be_ctx = talloc_get_type(sbus_conn_get_private_data(request->conn), struct be_ctx);
 
     resolv_reread_configuration(be_ctx->be_res->resolv);
     check_if_online(be_ctx);
 
-    return monitor_common_res_init(message, conn);
+    return monitor_common_res_init(request);
 }
 
-static int data_provider_go_offline(DBusMessage *message,
-                                    struct sbus_connection *conn)
+static int data_provider_go_offline(struct sbus_request *request)
 {
     struct be_ctx *be_ctx;
-    be_ctx = talloc_get_type(sbus_conn_get_private_data(conn), struct be_ctx);
+    be_ctx = talloc_get_type(sbus_conn_get_private_data(request->conn), struct be_ctx);
     be_mark_offline(be_ctx);
-    return monitor_common_pong(message, conn);
+    return sbus_request_return_and_finish(request, DBUS_TYPE_INVALID);
 }
 
-static int data_provider_reset_offline(DBusMessage *message,
-                                       struct sbus_connection *conn)
+static int data_provider_reset_offline(struct sbus_request *request)
 {
     struct be_ctx *be_ctx;
-    be_ctx = talloc_get_type(sbus_conn_get_private_data(conn), struct be_ctx);
+    be_ctx = talloc_get_type(sbus_conn_get_private_data(request->conn), struct be_ctx);
     check_if_online(be_ctx);
-    return monitor_common_pong(message, conn);
+    return sbus_request_return_and_finish(request, DBUS_TYPE_INVALID);
 }
 
-static int data_provider_logrotate(DBusMessage *message,
-                                struct sbus_connection *conn)
+static int data_provider_logrotate(struct sbus_request *request)
 {
     errno_t ret;
-    struct be_ctx *be_ctx = talloc_get_type(sbus_conn_get_private_data(conn),
+    struct be_ctx *be_ctx = talloc_get_type(sbus_conn_get_private_data(request->conn),
                                             struct be_ctx);
 
     ret = monitor_common_rotate_logs(be_ctx->cdb, be_ctx->conf_path);
     if (ret != EOK) return ret;
 
-    return monitor_common_pong(message, conn);
+    return sbus_request_return_and_finish(request, DBUS_TYPE_INVALID);
 }
diff --git a/src/providers/proxy/proxy_child.c b/src/providers/proxy/proxy_child.c
index b99c353..cd5a9f7 100644
--- a/src/providers/proxy/proxy_child.c
+++ b/src/providers/proxy/proxy_child.c
@@ -47,7 +47,7 @@
 
 #include "providers/dp_backend.h"
 
-static int pc_pam_handler(DBusMessage *message, struct sbus_connection *conn);
+static int pc_pam_handler(struct sbus_request *request);
 
 struct data_provider_iface pc_methods = {
     { &data_provider_iface_meta, 0 },
@@ -310,7 +310,7 @@ fail:
     return ret;
 }
 
-static int pc_pam_handler(DBusMessage *message, struct sbus_connection *conn)
+static int pc_pam_handler(struct sbus_request *request)
 {
     DBusError dbus_error;
     DBusMessage *reply;
@@ -319,7 +319,7 @@ static int pc_pam_handler(DBusMessage *message, struct sbus_connection *conn)
     void *user_data;
     struct pam_data *pd = NULL;
 
-    user_data = sbus_conn_get_private_data(conn);
+    user_data = sbus_conn_get_private_data(request->conn);
     if (!user_data) {
         ret = EINVAL;
         goto done;
@@ -330,7 +330,7 @@ static int pc_pam_handler(DBusMessage *message, struct sbus_connection *conn)
         goto done;
     }
 
-    reply = dbus_message_new_method_return(message);
+    reply = dbus_message_new_method_return(request->message);
     if (!reply) {
         DEBUG(SSSDBG_CRIT_FAILURE, "dbus_message_new_method_return failed, "
                   "cannot send reply.\n");
@@ -340,7 +340,7 @@ static int pc_pam_handler(DBusMessage *message, struct sbus_connection *conn)
 
     dbus_error_init(&dbus_error);
 
-    ret = dp_unpack_pam_request(message, pc_ctx, &pd, &dbus_error);
+    ret = dp_unpack_pam_request(request->message, pc_ctx, &pd, &dbus_error);
     if (!ret) {
         DEBUG(SSSDBG_CRIT_FAILURE,"Failed, to parse message!\n");
         ret = EIO;
@@ -375,14 +375,14 @@ static int pc_pam_handler(DBusMessage *message, struct sbus_connection *conn)
         goto done;
     }
 
-    sbus_conn_send_reply(conn, reply);
+    ret = sbus_request_finish(request, reply);
     dbus_message_unref(reply);
     talloc_free(pd);
 
     /* We'll return the message and let the
      * parent process kill us.
      */
-    return EOK;
+    return ret;
 
 done:
     exit(ret);
diff --git a/src/providers/proxy/proxy_init.c b/src/providers/proxy/proxy_init.c
index 60ae4a9..b58e06c 100644
--- a/src/providers/proxy/proxy_init.c
+++ b/src/providers/proxy/proxy_init.c
@@ -27,8 +27,7 @@
 #include "util/sss_format.h"
 #include "providers/proxy/proxy.h"
 
-static int client_registration(DBusMessage *message,
-                               struct sbus_connection *conn);
+static int client_registration(struct sbus_request *req);
 
 static struct data_provider_iface proxy_methods = {
     { &data_provider_iface_meta, 0 },
@@ -395,12 +394,11 @@ static void init_timeout(struct tevent_context *ev,
      */
 }
 
-static int client_registration(DBusMessage *message,
-                               struct sbus_connection *conn)
+static int client_registration(struct sbus_request *request)
 {
     dbus_uint16_t version = DATA_PROVIDER_VERSION;
+    struct sbus_connection *conn;
     struct proxy_client *proxy_cli;
-    DBusMessage *reply;
     DBusError dbus_error;
     dbus_uint16_t cli_ver;
     uint32_t cli_id;
@@ -412,7 +410,9 @@ static int client_registration(DBusMessage *message,
     struct tevent_req *req;
     struct proxy_child_ctx *child_ctx;
     struct pc_init_ctx *init_ctx;
+    int ret;
 
+    conn = request->conn;
     data = sbus_conn_get_private_data(conn);
     proxy_cli = talloc_get_type(data, struct proxy_client);
     if (!proxy_cli) {
@@ -427,7 +427,7 @@ static int client_registration(DBusMessage *message,
 
     dbus_error_init(&dbus_error);
 
-    dbret = dbus_message_get_args(message, &dbus_error,
+    dbret = dbus_message_get_args(request->message, &dbus_error,
                                   DBUS_TYPE_UINT16, &cli_ver,
                                   DBUS_TYPE_UINT32, &cli_id,
                                   DBUS_TYPE_INVALID);
@@ -453,31 +453,19 @@ static int client_registration(DBusMessage *message,
     }
 
     /* reply that all is ok */
-    reply = dbus_message_new_method_return(message);
-    if (!reply) {
-        DEBUG(SSSDBG_FATAL_FAILURE, "Dbus Out of memory!\n");
-        return ENOMEM;
-    }
-
-    dbret = dbus_message_append_args(reply,
-                                     DBUS_TYPE_UINT16, &version,
-                                     DBUS_TYPE_INVALID);
-    if (!dbret) {
-        DEBUG(SSSDBG_FATAL_FAILURE, "Failed to build dbus reply\n");
-        dbus_message_unref(reply);
+    ret = sbus_request_return_and_finish(request,
+                                         DBUS_TYPE_UINT16, &version,
+                                         DBUS_TYPE_INVALID);
+    if (ret != EOK) {
         sbus_disconnect(conn);
-        return EIO;
+        return ret;
     }
 
-    /* send reply back */
-    sbus_conn_send_reply(conn, reply);
-    dbus_message_unref(reply);
-
     hret = hash_lookup(proxy_cli->proxy_auth_ctx->request_table, &key, &value);
     if (hret != HASH_SUCCESS) {
         DEBUG(SSSDBG_CRIT_FAILURE,
               "Hash error [%d][%s]\n", hret, hash_error_string(hret));
-        sbus_disconnect(conn);
+        sbus_disconnect(request->conn);
     }
 
     /* Signal that the child is up and ready to receive the request */
@@ -496,7 +484,7 @@ static int client_registration(DBusMessage *message,
     }
 
     init_ctx = tevent_req_data(child_ctx->init_req, struct pc_init_ctx);
-    init_ctx->conn = conn;
+    init_ctx->conn = request->conn;
     tevent_req_done(child_ctx->init_req);
     child_ctx->init_req = NULL;
 
diff --git a/src/responder/autofs/autofssrv.c b/src/responder/autofs/autofssrv.c
index 5ce9ae0..c763992 100644
--- a/src/responder/autofs/autofssrv.c
+++ b/src/responder/autofs/autofssrv.c
@@ -29,8 +29,7 @@
 #include "providers/data_provider.h"
 #include "responder/autofs/autofs_private.h"
 
-static int autofs_clean_hash_table(DBusMessage *message,
-                                   struct sbus_connection *conn);
+static int autofs_clean_hash_table(struct sbus_request *request);
 
 struct mon_cli_iface monitor_autofs_methods = {
     { &mon_cli_iface_meta, 0 },
@@ -112,10 +111,9 @@ autofs_dp_reconnect_init(struct sbus_connection *conn,
                                  be_conn->domain->name);
 }
 
-static int autofs_clean_hash_table(DBusMessage *message,
-                                   struct sbus_connection *conn)
+static int autofs_clean_hash_table(struct sbus_request *request)
 {
-    struct resp_ctx *rctx = talloc_get_type(sbus_conn_get_private_data(conn),
+    struct resp_ctx *rctx = talloc_get_type(sbus_conn_get_private_data(request->conn),
                                             struct resp_ctx);
     struct autofs_ctx *actx =
             talloc_get_type(rctx->pvt_ctx, struct autofs_ctx);
@@ -127,7 +125,7 @@ static int autofs_clean_hash_table(DBusMessage *message,
         return ret;
     }
 
-    return monitor_common_pong(message, conn);
+    return sbus_request_return_and_finish(request, DBUS_TYPE_INVALID);
 }
 
 static int
diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h
index 81082c6..b2110a2 100644
--- a/src/responder/common/responder.h
+++ b/src/responder/common/responder.h
@@ -207,8 +207,7 @@ struct dp_callback_ctx {
 
 void handle_requests_after_reconnect(struct resp_ctx *rctx);
 
-int responder_logrotate(DBusMessage *message,
-                        struct sbus_connection *conn);
+int responder_logrotate(struct sbus_request *request);
 
 /* Each responder-specific request must create a constructor
  * function that creates a DBus Message that would be sent to
diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c
index 298994a..7e1b4d4 100644
--- a/src/responder/common/responder_common.c
+++ b/src/responder/common/responder_common.c
@@ -990,17 +990,16 @@ done:
     return ret;
 }
 
-int responder_logrotate(DBusMessage *message,
-                        struct sbus_connection *conn)
+int responder_logrotate(struct sbus_request *request)
 {
     errno_t ret;
-    struct resp_ctx *rctx = talloc_get_type(sbus_conn_get_private_data(conn),
+    struct resp_ctx *rctx = talloc_get_type(sbus_conn_get_private_data(request->conn),
                                             struct resp_ctx);
 
     ret = monitor_common_rotate_logs(rctx->cdb, rctx->confdb_service_path);
     if (ret != EOK) return ret;
 
-    return monitor_common_pong(message, conn);
+    return sbus_request_return_and_finish(request, DBUS_TYPE_INVALID);
 }
 
 void responder_set_fd_limit(rlim_t fd_limit)
diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c
index a385f29..023a870 100644
--- a/src/responder/nss/nsssrv.c
+++ b/src/responder/nss/nsssrv.c
@@ -55,10 +55,8 @@
 #define SHELL_REALLOC_INCREMENT 5
 #define SHELL_REALLOC_MAX       50
 
-static int nss_clear_memcache(DBusMessage *message,
-                              struct sbus_connection *conn);
-static int nss_clear_netgroup_hash_table(DBusMessage *message,
-                                         struct sbus_connection *conn);
+static int nss_clear_memcache(struct sbus_request *request);
+static int nss_clear_netgroup_hash_table(struct sbus_request *request);
 
 struct mon_cli_iface monitor_nss_methods = {
     { &mon_cli_iface_meta, 0 },
@@ -75,15 +73,14 @@ struct mon_cli_iface monitor_nss_methods = {
 struct sbus_interface monitor_nss_interface = {
     MONITOR_PATH,
     &monitor_nss_methods.vtable,
-    NULL
+    NULL,
 };
 
-static int nss_clear_memcache(DBusMessage *message,
-                              struct sbus_connection *conn)
+static int nss_clear_memcache(struct sbus_request *request)
 {
     errno_t ret;
     int memcache_timeout;
-    struct resp_ctx *rctx = talloc_get_type(sbus_conn_get_private_data(conn),
+    struct resp_ctx *rctx = talloc_get_type(sbus_conn_get_private_data(request->conn),
                                             struct resp_ctx);
     struct nss_ctx *nctx = (struct nss_ctx*) rctx->pvt_ctx;
 
@@ -134,14 +131,13 @@ static int nss_clear_memcache(DBusMessage *message,
     }
 
 done:
-    return monitor_common_pong(message, conn);
+    return sbus_request_return_and_finish(request, DBUS_TYPE_INVALID);
 }
 
-static int nss_clear_netgroup_hash_table(DBusMessage *message,
-                                         struct sbus_connection *conn)
+static int nss_clear_netgroup_hash_table(struct sbus_request *request)
 {
     errno_t ret;
-    struct resp_ctx *rctx = talloc_get_type(sbus_conn_get_private_data(conn),
+    struct resp_ctx *rctx = talloc_get_type(sbus_conn_get_private_data(request->conn),
                                             struct resp_ctx);
     struct nss_ctx *nctx = (struct nss_ctx*) rctx->pvt_ctx;
 
@@ -152,7 +148,7 @@ static int nss_clear_netgroup_hash_table(DBusMessage *message,
         return ret;
     }
 
-    return monitor_common_pong(message, conn);
+    return sbus_request_return_and_finish(request, DBUS_TYPE_INVALID);
 }
 
 static errno_t nss_get_etc_shells(TALLOC_CTX *mem_ctx, char ***_shells)
@@ -308,10 +304,9 @@ done:
     return ret;
 }
 
-static int nss_update_memcache(DBusMessage *message,
-                               struct sbus_connection *conn)
+static int nss_update_memcache(struct sbus_request *request)
 {
-    struct resp_ctx *rctx = talloc_get_type(sbus_conn_get_private_data(conn),
+    struct resp_ctx *rctx = talloc_get_type(sbus_conn_get_private_data(request->conn),
                                             struct resp_ctx);
     struct nss_ctx *nctx = talloc_get_type(rctx->pvt_ctx, struct nss_ctx);
 
@@ -321,15 +316,13 @@ static int nss_update_memcache(DBusMessage *message,
     return EOK;
 }
 
-static int nss_memcache_initgr_check(DBusMessage *message,
-                                     struct sbus_connection *conn)
+static int nss_memcache_initgr_check(struct sbus_request *request)
 {
-    struct resp_ctx *rctx = talloc_get_type(sbus_conn_get_private_data(conn),
+    struct resp_ctx *rctx = talloc_get_type(sbus_conn_get_private_data(request->conn),
                                             struct resp_ctx);
     struct nss_ctx *nctx = talloc_get_type(rctx->pvt_ctx, struct nss_ctx);
     DBusError dbus_error;
     dbus_bool_t dbret;
-    DBusMessage *reply;
     char *user;
     char *domain;
     uint32_t *groups;
@@ -337,7 +330,7 @@ static int nss_memcache_initgr_check(DBusMessage *message,
 
     dbus_error_init(&dbus_error);
 
-    dbret = dbus_message_get_args(message, &dbus_error,
+    dbret = dbus_message_get_args(request->message, &dbus_error,
                                   DBUS_TYPE_STRING, &user,
                                   DBUS_TYPE_STRING, &domain,
                                   DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
@@ -357,20 +350,7 @@ static int nss_memcache_initgr_check(DBusMessage *message,
 
     nss_update_initgr_memcache(nctx, user, domain, gnum, groups);
 
-    reply = dbus_message_new_method_return(message);
-    if (!reply) return ENOMEM;
-
-    dbret = dbus_message_append_args(reply, DBUS_TYPE_INVALID);
-    if (!dbret) {
-        dbus_message_unref(reply);
-        return EIO;
-    }
-
-    /* send reply back */
-    sbus_conn_send_reply(conn, reply);
-    dbus_message_unref(reply);
-
-    return EOK;
+    return sbus_request_return_and_finish(request, DBUS_TYPE_INVALID);
 }
 
 static struct data_provider_rev_iface nss_dp_methods = {
diff --git a/src/sbus/sssd_dbus.h b/src/sbus/sssd_dbus.h
index 7d00b94..257b2c2 100644
--- a/src/sbus/sssd_dbus.h
+++ b/src/sbus/sssd_dbus.h
@@ -24,9 +24,11 @@
 
 struct sbus_connection;
 
+struct sbus_request;
+
 #include <dbus/dbus.h>
 
-typedef int (*sbus_msg_handler_fn)(DBusMessage *, struct sbus_connection *);
+typedef int (*sbus_msg_handler_fn)(struct sbus_request *req);
 
 /*
  * sbus_conn_destructor_fn
@@ -170,4 +172,78 @@ int sbus_conn_send(struct sbus_connection *conn,
 void sbus_conn_send_reply(struct sbus_connection *conn,
                           DBusMessage *reply);
 
+/*
+ * This structure is passed to all dbus method and property
+ * handlers. It is a talloc context which will be valid until
+ * the request is completed with either the sbus_request_complete()
+ * or sbus_request_fail() functions.
+ */
+struct sbus_request {
+    struct sbus_connection *conn;
+    DBusMessage *message;
+    struct sbus_interface *intf;
+    const struct sbus_method_meta *method;
+};
+
+/*
+ * Complete a DBus request, and free the @request context. The @request
+ * and associated talloc context are no longer valid after this function
+ * returns.
+ *
+ * If @reply is non-NULL then the reply is sent to the caller. Not sending
+ * a reply when the caller is expecting one is fairly rude behavior.
+ *
+ * The return value is useful for logging, but not much else. In particular
+ * even if this function return !EOK, @request is still unusable after this
+ * function returns.
+ */
+int sbus_request_finish(struct sbus_request *request,
+                        DBusMessage *reply);
+
+/*
+ * Return a reply for a DBus method call request. The variable
+ * arguments are (unfortunately) formatted exactly the same as those of the
+ * dbus_message_append_args() function. Documented here:
+ *
+ * http://dbus.freedesktop.org/doc/api/html/group__DBusMessage.html
+ *
+ * Important: don't pass int or bool or such types as
+ * values to this function. That's not portable. Use actual dbus types.
+ * You must also pass pointers as the values:
+ *
+ *    dbus_bool_t val1 = TRUE;
+ *    dbus_int32_t val2 = 5;
+ *    ret = sbus_request_finish(request,
+ *                              DBUS_TYPE_BOOLEAN, &val1,
+ *                              DBUS_TYPE_INT32, &val2,
+ *                              DBUS_TYPE_INVALID);
+ *
+ * To pass arrays to this function, use the following syntax. Never
+ * pass actual C arrays with [] syntax to this function. The C standard is
+ * rather vague with C arrays and varargs, and it just plain doesn't work.
+ *
+ *    const char *array[] = { "one", "two", "three" };
+ *    int count = 3; // yes, a plain int
+ *    const char **ptr = array;
+ *    ret = sbus_request_finish(request,
+ *                              DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &ptr, 3,
+ *                              DBUS_TYPE_INVALID);
+ *
+ * The @request and associated talloc context are no longer valid after this
+ * function returns, even if this function returns an error code.
+ */
+int sbus_request_return_and_finish(struct sbus_request *request,
+                                   int first_arg_type,
+                                   ...);
+
+/*
+ * Return an error for a DBus method call request. The @error is a normal
+ * DBusError.
+ *
+ * The @request and associated talloc context are no longer valid after this
+ * function returns, even if this function returns an error code.
+ */
+int sbus_request_fail_and_finish(struct sbus_request *request,
+                                 const DBusError *error);
+
 #endif /* _SSSD_DBUS_H_*/
diff --git a/src/sbus/sssd_dbus_connection.c b/src/sbus/sssd_dbus_connection.c
index d39f1c0..95163f5 100644
--- a/src/sbus/sssd_dbus_connection.c
+++ b/src/sbus/sssd_dbus_connection.c
@@ -416,7 +416,9 @@ DBusHandlerResult sbus_message_handler(DBusConnection *dbus_conn,
     DBusMessage *reply = NULL;
     const struct sbus_method_meta *method;
     const struct sbus_interface_meta *interface;
-    sbus_msg_handler_fn handler_fn;
+    struct sbus_request *req = NULL;
+    sbus_msg_handler_fn handler_fn = NULL;
+    DBusHandlerResult result;
     int ret;
 
     if (!user_data) {
@@ -436,10 +438,11 @@ DBusHandlerResult sbus_message_handler(DBusConnection *dbus_conn,
     if (strcmp(path, intf_p->intf->path) != 0)
         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 
+    result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
     /* Validate the method interface */
     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);
@@ -451,6 +454,7 @@ DBusHandlerResult sbus_message_handler(DBusConnection *dbus_conn,
             reply = dbus_message_new_error(message, DBUS_ERROR_UNKNOWN_METHOD, NULL);
             sbus_conn_send_reply(intf_p->conn, reply);
             dbus_message_unref(reply);
+            result = DBUS_HANDLER_RESULT_HANDLED;
 
         } else if (!handler_fn) {
             /* Reply DBUS_ERROR_NOT_SUPPORTED */
@@ -459,11 +463,7 @@ DBusHandlerResult sbus_message_handler(DBusConnection *dbus_conn,
             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);
+            result = DBUS_HANDLER_RESULT_HANDLED;
         }
     }
     else {
@@ -473,21 +473,28 @@ DBusHandlerResult sbus_message_handler(DBusConnection *dbus_conn,
         if (strcmp(msg_interface, DBUS_INTROSPECT_INTERFACE) == 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
-                 * an introspection function registered, user that.
-                 */
-                ret = intf_p->intf->introspect_fn(message, intf_p->conn);
-                if (ret != EOK) {
-                    return sbus_reply_internal_error(message, intf_p->conn);
-                }
-            }
+            handler_fn = intf_p->intf->introspect_fn;
+        }
+    }
+
+    if (handler_fn) {
+        req = sbus_new_request(intf_p->conn, intf_p->intf, message);
+        if (!req) {
+            ret = ENOMEM;
+        } else {
+            req->method = method;
+            ret = handler_fn(req);
+        }
+        if (ret != EOK) {
+            if (req)
+                talloc_free(req);
+            result = sbus_reply_internal_error(message, intf_p->conn);
+        } else {
+            result = DBUS_HANDLER_RESULT_HANDLED;
         }
-        else
-            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
     }
 
-    return DBUS_HANDLER_RESULT_HANDLED;
+    return result;
 }
 
 /* Adds a new D-BUS path message handler to the connection
@@ -786,4 +793,3 @@ void sbus_conn_send_reply(struct sbus_connection *conn, DBusMessage *reply)
 {
     dbus_connection_send(conn->dbus.conn, reply, NULL);
 }
-
diff --git a/src/sbus/sssd_dbus_private.h b/src/sbus/sssd_dbus_private.h
index c62e0e3..eca5c83 100644
--- a/src/sbus/sssd_dbus_private.h
+++ b/src/sbus/sssd_dbus_private.h
@@ -96,4 +96,10 @@ dbus_bool_t sbus_add_timeout(DBusTimeout *dbus_timeout, void *data);
 void sbus_toggle_timeout(DBusTimeout *dbus_timeout, void *data);
 void sbus_remove_timeout(DBusTimeout *dbus_timeout, void *data);
 
+/* =Requests============================================================== */
+
+struct sbus_request *
+sbus_new_request(struct sbus_connection *conn, struct sbus_interface *intf,
+                 DBusMessage *message);
+
 #endif /* _SSSD_DBUS_PRIVATE_H_ */
diff --git a/src/sbus/sssd_dbus_request.c b/src/sbus/sssd_dbus_request.c
new file mode 100644
index 0000000..ab98d93
--- /dev/null
+++ b/src/sbus/sssd_dbus_request.c
@@ -0,0 +1,111 @@
+/*
+    Authors:
+        Stef Walter <stefw@redhat.com>
+
+    Copyright (C) 2014 Red Hat
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "util/util.h"
+#include "sbus/sssd_dbus.h"
+
+#include <sys/time.h>
+#include <dbus/dbus.h>
+
+static int sbus_request_destructor(struct sbus_request *req)
+{
+    dbus_message_unref(req->message);
+    return 0;
+}
+
+struct sbus_request *
+sbus_new_request(struct sbus_connection *conn,
+                 struct sbus_interface *intf,
+                 DBusMessage *message)
+{
+    struct sbus_request *req;
+
+    req = talloc_zero(conn, struct sbus_request);
+    if (!req) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory allocating DBus request\n");
+        return NULL;
+    }
+
+    req->intf = intf;
+    req->conn = conn;
+    req->message = dbus_message_ref(message);
+    talloc_set_destructor(req, sbus_request_destructor);
+
+    return req;
+}
+
+int sbus_request_finish(struct sbus_request *request,
+                        DBusMessage *reply)
+{
+    if (reply)
+        sbus_conn_send_reply(request->conn, reply);
+    return talloc_free(request);
+}
+
+int sbus_request_return_and_finish(struct sbus_request *request,
+                                   int first_arg_type,
+                                   ...)
+{
+    DBusMessage *reply;
+    dbus_bool_t ret;
+    va_list va;
+    int res;
+
+    reply = dbus_message_new_method_return(request->message);
+    if (!reply) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory allocating DBus message\n");
+        sbus_request_finish(request, NULL);
+        return ENOMEM;
+    }
+
+    va_start(va, first_arg_type);
+    ret = dbus_message_append_args_valist(reply, first_arg_type, va);
+    va_end(va);
+
+    if (ret) {
+        res = sbus_request_finish(request, reply);
+
+    } else {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Couldn't build DBus message\n");
+        sbus_request_finish(request, NULL);
+        res = EINVAL;
+    }
+
+    dbus_message_unref(reply);
+    return res;
+}
+
+int sbus_request_fail_and_finish(struct sbus_request *request,
+                                 const DBusError *error)
+{
+    DBusMessage *reply;
+    int res;
+
+    reply = dbus_message_new_error(request->message, error->name, error->message);
+    if (!reply) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory allocating DBus message\n");
+        sbus_request_finish(request, NULL);
+        return ENOMEM;
+    }
+
+    res = sbus_request_finish(request, reply);
+    dbus_message_unref(reply);
+    return res;
+}
diff --git a/src/tests/sbus_codegen_tests.c b/src/tests/sbus_codegen_tests.c
index 7386756..21fe74f 100644
--- a/src/tests/sbus_codegen_tests.c
+++ b/src/tests/sbus_codegen_tests.c
@@ -113,14 +113,14 @@ START_TEST(test_signals)
 END_TEST
 
 static int
-mock_move_universe(DBusMessage *msg, struct sbus_connection *conn)
+mock_move_universe(struct sbus_request *req)
 {
     /* not called */
     return 0;
 }
 
 static int
-mock_crash_now(DBusMessage *msg, struct sbus_connection *conn)
+mock_crash_now(struct sbus_request *req)
 {
     /* not called */
     return 0;
-- 
1.8.5.3

