diff options
Diffstat (limited to 'src/sbus/sssd_dbus_invokers.c')
-rw-r--r-- | src/sbus/sssd_dbus_invokers.c | 465 |
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; +} |