summaryrefslogtreecommitdiffstats
path: root/src/sbus/sssd_dbus_invokers.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sbus/sssd_dbus_invokers.c')
-rw-r--r--src/sbus/sssd_dbus_invokers.c465
1 files changed, 465 insertions, 0 deletions
diff --git a/src/sbus/sssd_dbus_invokers.c b/src/sbus/sssd_dbus_invokers.c
new file mode 100644
index 000000000..df9104f63
--- /dev/null
+++ b/src/sbus/sssd_dbus_invokers.c
@@ -0,0 +1,465 @@
+/*
+ Authors:
+ Pavel Březina <pbrezina@redhat.com>
+
+ Copyright (C) 2014 Red Hat
+
+ SBUS: Interface introspection
+
+ 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 "config.h"
+
+#include <dbus/dbus.h>
+#include <errno.h>
+
+#include "util/util.h"
+#include "sbus/sssd_dbus.h"
+#include "sbus/sssd_dbus_meta.h"
+#include "sbus/sssd_dbus_private.h"
+#include "sbus/sssd_dbus_invokers.h"
+
+static int
+sbus_invoke_get_basic(struct sbus_request *sbus_req,
+ void *function_ptr,
+ void *value_ptr,
+ int dbus_type,
+ DBusMessageIter *iter)
+{
+ void (*handler_fn)(struct sbus_request *, void *, void *);
+ dbus_bool_t value_bool;
+ dbus_bool_t dbret;
+
+ handler_fn = function_ptr;
+ handler_fn(sbus_req, sbus_req->intf->handler_data, value_ptr);
+
+ if (dbus_type == DBUS_TYPE_BOOLEAN) {
+ /* Special case to convert bool into dbus_bool_t. */
+ value_bool = *((bool *) value_ptr);
+ value_ptr = &value_bool;
+ }
+
+ dbret = dbus_message_iter_append_basic(iter, dbus_type, value_ptr);
+ return dbret ? EOK : EIO;
+}
+
+static int
+sbus_invoke_get_string(struct sbus_request *sbus_req,
+ void *function_ptr,
+ const char *default_value,
+ int dbus_type,
+ DBusMessageIter *iter)
+{
+ void (*handler_fn)(struct sbus_request *, void *, const char **);
+ const char *value = NULL;
+ dbus_bool_t dbret;
+
+ handler_fn = function_ptr;
+ handler_fn(sbus_req, sbus_req->intf->handler_data, &value);
+
+ value = value == NULL ? default_value : value;
+
+ dbret = dbus_message_iter_append_basic(iter, dbus_type, &value);
+ return dbret ? EOK : EIO;
+}
+
+static int
+sbus_invoke_get_array(struct sbus_request *sbus_req,
+ void *function_ptr,
+ unsigned int item_size,
+ int dbus_type,
+ DBusMessageIter *iter)
+{
+ void (*handler_fn)(struct sbus_request *, void *, void *, int *);
+ const char array_type[2] = {dbus_type, '\0'};
+ DBusMessageIter array;
+ dbus_bool_t dbret;
+ uint8_t *values;
+ void *addr;
+ int num_values;
+ int i;
+
+ handler_fn = function_ptr;
+ handler_fn(sbus_req, sbus_req->intf->handler_data, &values, &num_values);
+
+ dbret = dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+ array_type, &array);
+ if (!dbret) {
+ return EIO;
+ }
+
+ for (i = 0; i < num_values; i++) {
+ addr = values + i * item_size;
+
+ dbret = dbus_message_iter_append_basic(&array, dbus_type, addr);
+ if (!dbret) {
+ return ENOMEM;
+ }
+ }
+
+ dbret = dbus_message_iter_close_container(iter, &array);
+ if (!dbret) {
+ return EIO;
+ }
+
+ return EOK;
+}
+
+int sbus_invoke_get_y(DBusMessageIter *iter,
+ struct sbus_request *sbus_req,
+ void *function_ptr)
+{
+ uint8_t value;
+
+ return sbus_invoke_get_basic(sbus_req, function_ptr, &value,
+ DBUS_TYPE_BYTE, iter);
+}
+
+int sbus_invoke_get_b(DBusMessageIter *iter,
+ struct sbus_request *sbus_req,
+ void *function_ptr)
+{
+ bool value;
+
+ return sbus_invoke_get_basic(sbus_req, function_ptr, &value,
+ DBUS_TYPE_BOOLEAN, iter);
+}
+
+int sbus_invoke_get_n(DBusMessageIter *iter,
+ struct sbus_request *sbus_req,
+ void *function_ptr)
+{
+ int16_t value;
+
+ return sbus_invoke_get_basic(sbus_req, function_ptr, &value,
+ DBUS_TYPE_INT16, iter);
+}
+
+int sbus_invoke_get_q(DBusMessageIter *iter,
+ struct sbus_request *sbus_req,
+ void *function_ptr)
+{
+ uint16_t value;
+
+ return sbus_invoke_get_basic(sbus_req, function_ptr, &value,
+ DBUS_TYPE_UINT16, iter);
+}
+
+int sbus_invoke_get_i(DBusMessageIter *iter,
+ struct sbus_request *sbus_req,
+ void *function_ptr)
+{
+ int32_t value;
+
+ return sbus_invoke_get_basic(sbus_req, function_ptr, &value,
+ DBUS_TYPE_INT32, iter);
+}
+
+int sbus_invoke_get_u(DBusMessageIter *iter,
+ struct sbus_request *sbus_req,
+ void *function_ptr)
+{
+ uint32_t value;
+
+ return sbus_invoke_get_basic(sbus_req, function_ptr, &value,
+ DBUS_TYPE_UINT32, iter);
+}
+
+int sbus_invoke_get_x(DBusMessageIter *iter,
+ struct sbus_request *sbus_req,
+ void *function_ptr)
+{
+ int64_t value;
+
+ return sbus_invoke_get_basic(sbus_req, function_ptr, &value,
+ DBUS_TYPE_INT64, iter);
+}
+
+int sbus_invoke_get_t(DBusMessageIter *iter,
+ struct sbus_request *sbus_req,
+ void *function_ptr)
+{
+ uint64_t value;
+
+ return sbus_invoke_get_basic(sbus_req, function_ptr, &value,
+ DBUS_TYPE_UINT64, iter);
+}
+
+int sbus_invoke_get_d(DBusMessageIter *iter,
+ struct sbus_request *sbus_req,
+ void *function_ptr)
+{
+ double value;
+
+ return sbus_invoke_get_basic(sbus_req, function_ptr, &value,
+ DBUS_TYPE_DOUBLE, iter);
+}
+
+int sbus_invoke_get_s(DBusMessageIter *iter,
+ struct sbus_request *sbus_req,
+ void *function_ptr)
+{
+ return sbus_invoke_get_string(sbus_req, function_ptr, "",
+ DBUS_TYPE_STRING, iter);
+}
+
+int sbus_invoke_get_o(DBusMessageIter *iter,
+ struct sbus_request *sbus_req,
+ void *function_ptr)
+{
+ return sbus_invoke_get_string(sbus_req, function_ptr, "/",
+ DBUS_TYPE_OBJECT_PATH, iter);
+}
+
+int sbus_invoke_get_ay(DBusMessageIter *iter,
+ struct sbus_request *sbus_req,
+ void *function_ptr)
+{
+ return sbus_invoke_get_array(sbus_req, function_ptr, sizeof(uint8_t),
+ DBUS_TYPE_BYTE, iter);
+}
+
+int sbus_invoke_get_an(DBusMessageIter *iter,
+ struct sbus_request *sbus_req,
+ void *function_ptr)
+{
+ return sbus_invoke_get_array(sbus_req, function_ptr, sizeof(int16_t),
+ DBUS_TYPE_INT16, iter);
+}
+
+int sbus_invoke_get_aq(DBusMessageIter *iter,
+ struct sbus_request *sbus_req,
+ void *function_ptr)
+{
+ return sbus_invoke_get_array(sbus_req, function_ptr, sizeof(uint16_t),
+ DBUS_TYPE_UINT16, iter);
+}
+
+int sbus_invoke_get_ai(DBusMessageIter *iter,
+ struct sbus_request *sbus_req,
+ void *function_ptr)
+{
+ return sbus_invoke_get_array(sbus_req, function_ptr, sizeof(int32_t),
+ DBUS_TYPE_INT32, iter);
+}
+
+int sbus_invoke_get_au(DBusMessageIter *iter,
+ struct sbus_request *sbus_req,
+ void *function_ptr)
+{
+ return sbus_invoke_get_array(sbus_req, function_ptr, sizeof(uint32_t),
+ DBUS_TYPE_UINT32, iter);
+}
+
+int sbus_invoke_get_ax(DBusMessageIter *iter,
+ struct sbus_request *sbus_req,
+ void *function_ptr)
+{
+ return sbus_invoke_get_array(sbus_req, function_ptr, sizeof(int64_t),
+ DBUS_TYPE_INT64, iter);
+}
+
+int sbus_invoke_get_at(DBusMessageIter *iter,
+ struct sbus_request *sbus_req,
+ void *function_ptr)
+{
+ return sbus_invoke_get_array(sbus_req, function_ptr, sizeof(uint64_t),
+ DBUS_TYPE_UINT64, iter);
+}
+
+int sbus_invoke_get_ad(DBusMessageIter *iter,
+ struct sbus_request *sbus_req,
+ void *function_ptr)
+{
+ return sbus_invoke_get_array(sbus_req, function_ptr, sizeof(double),
+ DBUS_TYPE_DOUBLE, iter);
+}
+
+int sbus_invoke_get_as(DBusMessageIter *iter,
+ struct sbus_request *sbus_req,
+ void *function_ptr)
+{
+ return sbus_invoke_get_array(sbus_req, function_ptr, sizeof(const char *),
+ DBUS_TYPE_STRING, iter);
+}
+
+int sbus_invoke_get_ao(DBusMessageIter *iter,
+ struct sbus_request *sbus_req,
+ void *function_ptr)
+{
+ return sbus_invoke_get_array(sbus_req, function_ptr, sizeof(const char *),
+ DBUS_TYPE_OBJECT_PATH, iter);
+}
+
+void sbus_invoke_get(struct sbus_request *sbus_req,
+ const char *type,
+ sbus_get_invoker_fn invoker_fn,
+ sbus_msg_handler_fn handler_fn)
+{
+ DBusMessage *reply = NULL;
+ DBusMessageIter iter;
+ DBusMessageIter variant;
+ dbus_bool_t dbret;
+ errno_t ret;
+
+ reply = dbus_message_new_method_return(sbus_req->message);
+ if (reply == NULL) {
+ ret = ENOMEM;
+ goto fail;
+ }
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ dbret = dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
+ type, &variant);
+ if (!dbret) {
+ ret = ENOMEM;
+ goto fail;
+ }
+
+ ret = invoker_fn(&variant, sbus_req, handler_fn);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Invoker error [%d]: %s\n", ret, sss_strerror(ret));
+ goto fail;
+ }
+
+ dbret = dbus_message_iter_close_container(&iter, &variant);
+ if (!dbret) {
+ ret = EIO;
+ goto fail;
+ }
+
+ sbus_request_finish(sbus_req, reply);
+ return;
+
+fail:
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Unable to reply [%d]: %s\n", ret, sss_strerror(ret));
+
+ if (reply != NULL) {
+ dbus_message_unref(reply);
+ }
+ sbus_request_finish(sbus_req, NULL);
+
+ return;
+}
+
+void sbus_invoke_get_all(struct sbus_request *sbus_req)
+{
+ const struct sbus_property_meta *props;
+ sbus_msg_handler_fn *handler_fn;
+ DBusMessage *reply = NULL;
+ DBusMessageIter iter;
+ DBusMessageIter array;
+ DBusMessageIter dict;
+ DBusMessageIter variant;
+ dbus_bool_t dbret;
+ errno_t ret;
+ int i;
+
+ reply = dbus_message_new_method_return(sbus_req->message);
+ if (reply == NULL) {
+ ret = ENOMEM;
+ goto fail;
+ }
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ dbret = dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+ &array);
+ if (!dbret) {
+ ret = ENOMEM;
+ goto fail;
+ }
+
+ props = sbus_req->intf->vtable->meta->properties;
+
+ if (props != NULL) {
+ for (i = 0; props[i].name != NULL; i++) {
+ dbret = dbus_message_iter_open_container(&array,
+ DBUS_TYPE_DICT_ENTRY, NULL,
+ &dict);
+ if (!dbret) {
+ ret = ENOMEM;
+ goto fail;
+ }
+
+ /* key */
+ dbret = dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING,
+ &props[i].name);
+ if (!dbret) {
+ ret = ENOMEM;
+ goto fail;
+ }
+
+ /* value */
+ dbret = dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT,
+ props[i].type, &variant);
+ if (!dbret) {
+ ret = ENOMEM;
+ goto fail;
+ }
+
+ handler_fn = VTABLE_FUNC(sbus_req->intf->vtable,
+ props[i].vtable_offset_get);
+ if (handler_fn == NULL) {
+ ret = ERR_INTERNAL;
+ goto fail;
+ }
+
+ ret = props[i].invoker_get(&variant, sbus_req, handler_fn);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Invoker error [%d]: %s\n", ret, sss_strerror(ret));
+ goto fail;
+ }
+
+ dbret = dbus_message_iter_close_container(&dict, &variant);
+ if (!dbret) {
+ ret = EIO;
+ goto fail;
+ }
+
+ dbret = dbus_message_iter_close_container(&array, &dict);
+ if (!dbret) {
+ ret = EIO;
+ goto fail;
+ }
+ }
+ }
+
+ dbret = dbus_message_iter_close_container(&iter, &array);
+ if (!dbret) {
+ ret = EIO;
+ goto fail;
+ }
+
+ sbus_request_finish(sbus_req, reply);
+ return;
+
+fail:
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Unable to reply [%d]: %s\n", ret, sss_strerror(ret));
+
+ dbus_message_unref(reply);
+ sbus_request_finish(sbus_req, NULL);
+
+ return;
+}